View Full Version : quad - quadrilateral transform (split from New Utils thread due to bug report)
wonkey_monkey
24th September 2012, 14:18
2019-01-14: quad is now superseded by warp (https://forum.doom9.org/showthread.php?t=176031)
Download: quad.zip (http://horman.net/quad.zip)
Last update: 2012-09-30 - ~10% speed increase, bicubic interpolation
Last update: 2012-10-02 - another ~10% speed increase
Last update: 2012-10-05 - 100% speed increase!
Last update: 2012-11-01 - output levels bugfix
quad is a quadrilateral transformation filter similar to vcmohan's reform, although (so far) quad doesn't crash ;) and does a true quadrilateral transformation. It uses bicubic interpolation (can be switched off for speed purposes) and is multi-threaded.
Minimum parameter requirements are 4 x,y pairs defining the corners of the target quadrilateral. The source quadrilateral can also be specified, if required.
No source, sorry - it makes use of too many half-written libraries scattered around my hard drive.
quad
====
An Avisynth plugin to perform quadrilateral transformations.
Usage
=====
quad(clip, tx0,ty0, tx1,tx1, tx2,ty2, tx3,ty3, [sx0,sy0, sx1,sy1, tx2,ty2, tx3,ty3, bool invert, bool normal, bool draft])
Parameters:
-----------
tx0,ty0-tx3,ty3: the four corners of the target quadrilateral.
sx0,sy0-sx3,sy3: the four corners of the source quadrilateral (default: clip's corners, clockwise from top left)
invert: invert the transformation (transpose t and s)
normal: specify that the coordinates are normalised to the range 0-1.
draft: don't use spline16 interpolation
martin53
25th September 2012, 17:59
Can you post a screenshot?
Yes, of course. See _quad000022.jpg, made with the script
ColorBars()
quad(0,0, 1,0, 1,1, 0,1, normal=true)
...Uh., funny. There was the black area inside AvsPmod's preview, but the jpg is stored with a correct picture. I'll try on to catch the picture.
EDIT
I made screenshots now. Looks like 'the thread responsible for the upmost quarter of the image is not finished when the frame is forwarded'. Maybe the thread continues to write afterwards, and then issues the illegal access?
wonkey_monkey
25th September 2012, 19:03
Strange that the thread for the top strip - which is the first thread to be created - is so far behind, although you were right that the code was failing to wait for that thread (it waited for all the others). Also strange that the edge is slanted like that.
I've updated the DLL (download link as at top of thread) which also includes some very slight speed improvements, though I don't know whether that will fix your scriptclip problem.
David
martin53
25th September 2012, 22:59
David,
I think you solved it!:thanks:
Looks very promising:
ColorBars()
Subtitle("Flying Colorbars()",text_color=$d0c000,align=5,size=40)
ScriptClip("""
c=last
t=0.061*current_frame
t2=0.127*current_frame
a=0.501+0.5*sin(t/pi)
t1x=-0.2*cos(t2)
t1y=0.5-0.5*cos(t2)
t2x=1.0+0.2*cos(t2)
t2y=0.5-0.5*cos(t2)
t3x=1.0+0.2*cos(t2)
t3y=0.5+0.5*cos(t2)
t4x=-0.2*cos(t2)
t4y=0.5+0.5*cos(t2)
c1x=0.5+a*cos(t)
c1y=0.5+a*sin(t)
c2x=0.5-a*sin(t)
c2y=0.5+a*cos(t)
c3x=0.5-a*cos(t)
c3y=0.5-a*sin(t)
c4x=0.5+a*sin(t)
c4y=0.5-a*cos(t)
c.quad(t1x,t1y, t2x,t2y, t3x,t3y, t4x,t4y, normal=true)
quad(c1x,c1y, c2x,c2y, c3x,c3y, c4x,c4y, normal=true)
""")
I only once suffered a crash when I had a=0.5+0.5*sin(t/pi), i.e. a can get ==0 - and it's a hard test to set all coordinates identical! Not realistic, I think it is perfect the way it is. Thanks that you took the time to put this together. I feel that this kind of transform really fills a gap and that now, people can create cool new animations that were impossible till now.
Please add the short description file to the new dll for the future downloaders. If you don't mind, you might add the types (float...) of the parameters, and maybe a bit more precise, which ones are optional.
:)
wonkey_monkey
30th September 2012, 19:13
Updated with ~10% speed increase and now using bicubic interpolation (I may make this switchable in future, sorry if you liked spline16!)
David
wonkey_monkey
5th October 2012, 18:05
http://horman.net/quad.zip
Updated again - now twice as fast as the last version :)
David
StainlessS
9th October 2012, 13:20
David, a version number or date on your zips might be good, the one in New Plugins is still the old one (with the same name).
EDIT: Suggest remove zip from New Plugins and point link here.
vcmohan
11th October 2012, 12:16
I am testing using the script given in a post above. While the earlier version of Quad was running at least through some frames prior to crashing, the latest version (oct 5) virtualdub does not start and gives a message
"An instruction not supported by the CPU was executed in module 'quad'."
My cpu is AMD two core 5000+ x2 and running windows xp.
Is there a problem?
wonkey_monkey
11th October 2012, 12:33
Is there a problem?
Definitely. I'd guess it's down to the SSE instructions I've used - I thought I wasn't using anything beyond regular SSE3 (and only one instruction beyond SSE2, HADDPS) but I must be wrong. I'll check my code later and add some fallback code, although I'll have to ask you to test it as I don't have any other CPUs to test it on.
David
wonkey_monkey
11th October 2012, 17:40
Could you give this DLL a try?
quad(amd).zip (http://horman.net/quad(amd).zip)
I inadvertently used an SSSE3 instruction, which isn't supported by the X2. This alternative DLL replaces it with pure <=SSE3 instructions, with only a minor performance hit.
David
IanB
11th October 2012, 22:26
The polite thing to do is codeif (!(env->GetCPUFlags() & CPUF_SSSE3)) env->ThrowError("Help, I need the SSSE3 instruction set");it's very poor form to just HCF (Halt and Catch Fire)
vcmohan
12th October 2012, 13:10
Could you give this DLL a try?
David
I tried and with Martin53 script above it was executing witout any crash. Thank you.
I however noted that the color strips at the edges were narrower than those inside. There is enough space on the screen to display them fully or at least lot wider. This must be true for the regular version also. It appears the edges are truncated.
wonkey_monkey
12th October 2012, 13:59
I however noted that the color strips at the edges were narrower than those inside. There is enough space on the screen to display them fully or at least lot wider. This must be true for the regular version also. It appears the edges are truncated.
I think (if I understand the problem correctly) that's because Martin's funky script applies quad twice. The first call to quad, depending on the point in the animation, sometimes expands the image outside the frame, so when the second quad is applied, it's already cropped.
David
wonkey_monkey
1st November 2012, 19:06
Hi all,
quad.dll (http://horman.net/quad.zip) has been updated to fix a bug which was causing RGBA values to be up to +2 above what they should have been - sorry about that!
David
martin53
11th November 2012, 17:32
You can see it work here (http://forum.doom9.org/showthread.php?p=1600151#post1600151) now, thanks again david.
Wilbert
24th November 2012, 17:27
I was trying to use FSubstitute, but i'm running into trouble with this plugin. It simply won't load it (error: unable to load ...quad.dll, error=0x7e ...). I have an old athlon where sse(2), SSSE3 is not supported (only mmx and isse). Perhaps this is the problem read the posts above. Could you support mmx for me too (and release the sources)?
Many thanks ...
StainlessS
24th November 2012, 19:30
VS6 Dependency Walker shows quad.dll as needing "Msvcr100.dll" from
Microsoft Visual C++ 2010 Redistributable Package
32 bit
http://www.microsoft.com/download/en/details.aspx?id=5555
64 bit
http://www.microsoft.com/download/en/details.aspx?id=14632
EDIT: Error 0x7e, missing module. Probably not even getting to the point where CPU could be an issue.
Wilbert
24th November 2012, 20:56
VS6 Dependency Walker shows quad.dll as needing "Msvcr100.dll" from
Microsoft Visual C++ 2010 Redistributable Package
Thx, i installed it. But i get now an other warning:
Evaluate: System exception - Illegal Instruction
wonkey_monkey
24th November 2012, 23:10
Hi Wilbert,
Sorry you've had trouble. I've tried to use Ian's suggestion:
if (!(env->GetCPUFlags() & CPUF_SSSE3)) env->ThrowError("Help, I need the SSSE3 instruction set");
but it didn't work - perhaps it's an Avisynth 2.6 thing, while I've stuck with 2.58.
This may work for you: http://horman.net/quad-no-sse.zip
It's about half the speed of the SSE version, but since that doesn't work for you at all it shouldn't be a problem :)
(and release the sources)?
Ah, sorry, I'm still reluctant to do so. The library I'm using is a tangle of inter-connected files and under constant revision/being messed about with, so I'd rather not release it until/unless I tidy it up a lot (my Avisynth filters only using a small subset of it).
David
Wilbert
25th November 2012, 00:07
This may work for you: http://horman.net/quad-no-sse.zip
It's about half the speed of the SSE version, but since that doesn't work for you at all it shouldn't be a problem
Sorry, i still get the same error.
StainlessS
25th November 2012, 00:33
From here:http://forum.doom9.org/showthread.php?p=1298430#post1298430
What processor and version of Avisynth are you using? If you run debugview when loading the script nnedi2 should output a line like:
nnedi2: auto-detected opt setting = %d
what value does it give? It works correctly on my laptop that only has sse2.
EDIT: It looks like Avisynth's GetCPUFlags() function is off by 1 bit when checking ecx for SSSE3/SSE4.1/SSE4.2. For SSSE3 on intel cpus it is actually checking the Thermal Monitor 2 bit, which happens to be 1 on my Q6600 and 0 on my laptop so it ends up working correctly here :p. I'll just make auto-detection only go up to SSE3, the one SSSE3 routine didn't really make any difference speedwise.
EDIT2: Actually, it doesn't crash on my laptop because I had an old version of Avisynth on it that didn't check beyond SSE3 support.
@David, Can you just verify that you are using Avisynth.h v3 (just incase the problem was in old header).
EDIT: FYI, Info() gives a little CPU info.
EDIT: Just installed vs2010. If you set "Project Properties/Code Generation/Runtime Library" to "Multi-threaded (/MT )"
avoids the requirement for "Msvcr100.dll".
Did timing test on my 3GHz 2 dual core on this source filter GetFrame(): http://forum.doom9.org/showthread.php?p=1602470#post1602470
Got about 40FPS on both VS6 and TK3, and only 26FPS on vc2010 (about same on vs2008). Dont have VS2005 installed
at present but might expect about 45FPS from that).
wonkey_monkey
26th November 2012, 17:38
@David, Can you just verify that you are using Avisynth.h v3 (just incase the problem was in old header).
It says v2.5 at the top of the file...
Sorry, i still get the same error.
I've updated (horman.net/quad-no-sse.zip) it, hopefully this time with no SSE instructions (although this time I left the DLL name as quad.dll)
David
StainlessS
26th November 2012, 17:54
David, latest v3 should have this at top of file, after GPL
#ifndef __AVISYNTH_H__
#define __AVISYNTH_H__
enum { AVISYNTH_INTERFACE_VERSION = 3 };
wonkey_monkey
26th November 2012, 18:37
David, latest v3 should have this at top of file, after GPL
Oh! Then yes.
David
Wilbert
26th November 2012, 19:48
I've updated it, hopefully this time with no SSE instructions (although this time I left the DLL name as quad.dll)
Thanks, it seems to work! Could anyone of your post some examples of what it should look like?
StainlessS
26th November 2012, 20:45
Here the example given already by martin53
ColorBars()
Subtitle("Flying Colorbars()",text_color=$d0c000,align=5,size=40)
ScriptClip("""
c=last
t=0.061*current_frame
t2=0.127*current_frame
a=0.501+0.5*sin(t/pi)
t1x=-0.2*cos(t2)
t1y=0.5-0.5*cos(t2)
t2x=1.0+0.2*cos(t2)
t2y=0.5-0.5*cos(t2)
t3x=1.0+0.2*cos(t2)
t3y=0.5+0.5*cos(t2)
t4x=-0.2*cos(t2)
t4y=0.5+0.5*cos(t2)
c1x=0.5+a*cos(t)
c1y=0.5+a*sin(t)
c2x=0.5-a*sin(t)
c2y=0.5+a*cos(t)
c3x=0.5-a*cos(t)
c3y=0.5-a*sin(t)
c4x=0.5+a*sin(t)
c4y=0.5-a*cos(t)
c.quad(t1x,t1y, t2x,t2y, t3x,t3y, t4x,t4y, normal=true)
quad(c1x,c1y, c2x,c2y, c3x,c3y, c4x,c4y, normal=true)
""")
Trim(0,562).KillAudio().ConvertToYV12()
http://www.mediafire.com/?hyz3tlpii3mlqed
Really quite nice :) EDIT: 1.42 MB, 18 seconds mp4
I guess that you've done that already yourself, but perhaps for others that want to know what it can do.
Well done to both David and martin53. I used the non SSE version just to check it out.
EDIT: Now all we need is a Flying Tardis disappearing down an xyremap vortex :cool:
martin53
20th December 2012, 16:19
Since that little script found such an echo, and david made a nice suggestion to me about how to profit from the alpha layer too, I updated the script a bit.
Note the background gradient, the starfield and how the color bars partially obscure it.
Btw did you ever wonder if frames have a front and a back side? ;)
function stars(clip c, int r) {
c.Overlay(x=rand(c.width),y=rand(c.height),BlankClip(c,width=1,height=1,color=$030301*rand(85)))
(r==0)? last : stars(r-1)
Trim(0,-1).Loop(c.Framecount, 0, 0)
}
width=1080
height=720
length=100000
Tcolor=$000040
Bcolor=$000018
StackVertical(BlankClip(length=length,width=2,height=1,color=TColor,pixel_type="RGB32"),BlankClip(length=length,width=2,height=1,color=BColor)).BilinearResize(width,2*height,src_top=0,src_height=2).Crop(0,height/2,0,-height/2).Stars(width*height/3072)
#BlankClip(length=length,FPS=25,width=640,height=480,color=$000018,pixel_type="RGB32")
ScriptClip("""
c=last
t=0.061*current_frame
t3=0.127*current_frame
t2=-0.9
a=exp(-3.0+3.0*cos(t/pi))
t1x=0.4*cos(t3)
t1dx=1.0+0.2*sin(t2)
t1y=0.4*cos(t2)
t1dy=1.0+0.2*sin(t3)
c1x=0.5+a*cos(t)
c1y=0.5+a*sin(t)
cb=Colorbars(width=width,height=height,pixel_type="rgb32")
cos(t2)*cos(t3)>=0? cb.Subtitle(string(current_frame)+"\nFlying Colorbars",text_color=$d0c000,lsp=0,align=5,size=60) : cb
ResetMask
quad(0.5+t1x*t1dx,0.5+t1y*t1dy, 0.5-t1x*t1dx,0.5+t1y/t1dy, 0.5-t1x/t1dx,0.5-t1y/t1dy, 0.5+t1x/t1dx,0.5-t1y*t1dy, normal=true)
quad(c1x,c1y, 1.0-c1y,c1x, 1.0-c1x,1.0-c1y, c1y,1.0-c1x, normal=true)
Overlay(c,last,mask=last.ShowAlpha)
""")
wonkey_monkey
20th December 2012, 17:53
Avisynth open failure:
Resize: Source image too small for this resize method. Width=1. Support=1
Might be a 2.58 thing?
vampiredom
18th February 2013, 08:16
Hi, I am not sure if this is by design or not but I have noticed a behavior that is counter-intuitive to me.
BlankClip(width=75,height=75, color=$ffffff)
AddBorders(25,25,25,25, color=$000000)
quad(0.5, 0, 1.0, 0.0, 1.0,1.0, 0,1.0, normal=true)
Only the float value in blue has been shifted from the rectangular values. However, you can see that the right edge of the box now skews slightly and the entire image has shifted upward.
I would have assumed that only the top-left corner would have been affected by the transform. Am I missing something?
wonkey_monkey
18th February 2013, 09:55
I would have assumed that only the top-left corner would have been affected by the transform. Am I missing something?
Yes :)
It emulates a 3D transform. If you draw a box and connect the diagonals, then push the top left corner of the box in, the point where the diagonals cross will shift up and right.
David
vampiredom
18th February 2013, 10:21
Yeah, I figured it was something like that! It's unfortunate for my purpose, however, as I need to control each corner of the box independently.
wonkey_monkey
18th February 2013, 13:16
xyremap (http://forum.doom9.org/showthread.php?t=166087) can probably do it, but you'd have to work out the correct expressions for yourself.
David
vampiredom
19th February 2013, 03:11
Thanks!
wonkey_monkey
20th February 2013, 13:51
function corners(clip in, float x0,float y0, float x1,float y1, float x2,float y2, float x3,float y3) {
return in.xyremap(x="x "+string(x0)+" 1 b - 1 a - * * - "+string(x1)+" 1 b - a * * + "+string(x2)+" b a * * + "+string(x3)+" b 1 a - * * -",\
y="y "+string(y0)+" 1 b - 1 a - * * - "+string(y1)+" 1 b - a * * - "+string(y2)+" b a * * + "+string(y3)+" b 1 a - * * +")
}
corners takes an input clip and four pairs of variables, each of which determines how far inward each of the four corners comes in towards the center (starting at the top left corner and working clockwise).
Caveat: due to xyremap's backwards mapping you will get curvature of the image sides, but it may go unnoticed for small shifts.
I may recompile xyremap later as I think I can squeeze some more accuracy out of the interpolator.
David
vampiredom
21st February 2013, 08:42
Cool. I will try that out. Thank you very much!
martin53
26th February 2013, 17:54
Might be a 2.58 thing?
Sorry I only noticed your reply a minute ago. Yes I use 2.60 - did you check with smaller width/height constants, e.g. 640*480?
Forensic
12th May 2016, 15:44
#davidhorman
Your Quad (11/01/2012 version) is undergoing peer review by the scientific community. The QUAD call is with the coordinates plus "invert=true, normal=true". Can you help me explain the reduction of only the Vertical clarity with the skew test detailed at (http://VideoCleaner.com/SquareTest.pdf)? NOTE: All Quad coordinates are 1/100th, and thus between 0.0 and 1.0, of the slider values listed in that PDF.
Thank you in advance.
wonkey_monkey
12th May 2016, 19:45
Your Quad (11/01/2012 version) is undergoing peer review by the scientific community.
Umm, okay. Not sure why... do I get a certificate if it passes?
Can you help me explain the reduction of only the Vertical clarity with the skew test detailed at (http://VideoCleaner.com/SquareTest.pdf)?
It's hard to tell exactly what problem is being looked at. I'm generally against relating such issues through the medium of PDF since the images will be scaled on view, and there's no indication of the correct scale to use to get a 1:1 mapping to my screen. Plus adding the grid behind the image confuses things.
I assume it's the broken-ness of the vertical edges. I just did a skew and an inverse skew in Photoshop and I got the same imperfect remapping of vertical lines. It's not possible to perfectly retrieve the original image if you're doing resampling.
Paint's skew feature doesn't do any resampling, so its result is much coarser than quad's. But it has the "advantage" that you can undo it perfectly.
Forensic
14th May 2016, 21:39
Actually, there can be a certificate or award from the forensic/scientific community. Would you be willing to release the source code?
In your testing, without the grids, do you also find that the vertical perspective blurs more than the horizontal?
wonkey_monkey
14th May 2016, 22:40
Actually, there can be a certificate or award from the forensic/scientific community.
Well, that'd be more than I got for discovering a supernova...
But quad is hardly worthy of an accolade. It was cobbled together out of some matlab code I found on some website and some pixel interpolation code. There's really nothing innovative to it.
In your testing, without the grids, do you also find that the vertical perspective blurs more than the horizontal?
Yes, because there's no vertical (horizontal lines are made of vertical detail) resampling. It's the same as if you resized it horizontally only. Vertical lines would be blurred, horizontal lines would be unchanged.
Forensic
15th May 2016, 21:46
Your QUAD is called by a massive (nearly 2000 line) Avisynth script running under AvsPmod. All this free code is in active use by hundreds, or thousands, of law enforcement (LE) agencies worldwide. I know for a fact that it has helped to identify the guilty, save lives and exonerate the innocent. Each DLL snippet contributes to its overall capabilities, which is why your code is worthy of accolades too. On a related note, can you release the source code? LE has reviewed most of the code that they rely upon, with QUAD being one of the rare exceptions. They were the one's posing my question to you, and I have informed them of your responses.
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.