Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
23rd June 2012, 20:00 | #1 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,869
|
Average all frames in a clip
Hi,
I'd like a script for this, just can't think of how to do it. It's easy to use overlay or even average plugin to do a few frames, but I want to average an entire clip. Even better if it can ignore certain pixels that changed too much. I'm extracting a noisy background from a perfectly still camera. |
23rd June 2012, 21:23 | #2 | Link |
Registered User
Join Date: Jul 2010
Posts: 448
|
Possible starting point
Code:
function AvgAll2(clip c) { c.FrameCount() <= 1 ? c : AvgAll2( Merge(c.SelectEven(),c.SelectOdd()) ) } More usable for long clips with Average (tested on 100000 frame clip, took less than a minute): Code:
function AvgAll8(clip c) { c.FrameCount() <= 1 ? c \ : AvgAll8( Average(c.SelectEvery(8,0),0.125,c.SelectEvery(8,1),0.125,c.SelectEvery(8,2),0.125,c.SelectEvery(8,3),0.125, \ c.SelectEvery(8,4),0.125,c.SelectEvery(8,5),0.125,c.SelectEvery(8,6),0.125,c.SelectEvery(8,7),0.125 ) ) } Last edited by -Vit-; 23rd June 2012 at 21:32. |
23rd June 2012, 22:29 | #3 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,433
|
Quote:
Code:
function AvgAll2(clip c) { c.FrameCount() <= 1 ? c : Merge(AvgAll2(c.SelectEven()), AvgAll2(c.SelectOdd())) } Code:
function AvgAll8(clip c) { c.FrameCount() <= 1 ? c \ : Average(AvgAll8(c.SelectEvery(8,0)),0.125, AvgAll8(c.SelectEvery(8,1)),0.125, ... ) } |
|
24th June 2012, 00:45 | #4 | Link |
Registered User
Join Date: Jul 2010
Posts: 448
|
No, that will still have a similar problem. Consider framecount=3, it will do a 50/50 merge of a 2-frame average and a 1-frame average - uneven weights.
I think this would be correct: Code:
function AvgAll2(clip c) { c.FrameCount() <= 1 ? c \ : Merge( AvgAll2(c.SelectEven()), AvgAll2(c.SelectOdd()), c.SelectOdd().FrameCount()/Float(c.FrameCount) ) } I think a different approach is needed for longer clips if precision is required. Although for extracting a static background, the original may be good enough. Last edited by -Vit-; 24th June 2012 at 00:47. |
24th June 2012, 00:48 | #5 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,869
|
Code:
#avg all #make test case y1=blankclip(length=1,pixel_type="YV12",color_yuv=$7F8080) y2=blankclip(length=1,pixel_type="YV12",color_yuv=$008080) y3=blankclip(length=1,pixel_type="YV12",color_yuv=$808080) y1+y2+y3 avgall function AvgAll(clip c){ c.FrameCount() <= 1 ? c : Merge(AvgAll(c.SelectEven()), AvgAll(c.SelectOdd())) } round((round((a+c)/2)+c)/2)=64. With this test, I can see that merge does rounding, and that Gavino's idea works as expected, the even frames of the first clip and the odd frame(s) of the 2nd. Even for small noise like +0 to +5, the error can be -2. The max error is -42 in 3 frames. Increasing the inner split like avgall8 doesn't actually help because now it just takes a specific pattern to cause the errors, I believe. For example, adding 3 at a time, but with 3 frames, you get ((a+c)/2+b)/2 There's another pattern possible with 6 frames. There's a limit to eval strings as well. |
24th June 2012, 01:00 | #6 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,869
|
Yes, the new function gives the exact answer 85 in the test. I needed the redaverage plugin. http://forum.doom9.org/showthread.php?t=163018 click the 1.43
I actually used 1.35 but it worked. And yes the weights were wrong, it was approx. .25*a+.5*b+.25*c,=64 Last edited by jmac698; 24th June 2012 at 01:09. |
24th June 2012, 03:21 | #7 | Link |
Registered User
Join Date: Jul 2010
Posts: 448
|
This version has precision and decent performance. Uses the first version of AvgAll2 for speed. Splits the clip into blocks of power-of-2 lengths (effectively treats the frame count as binary). Each block's average is calculated correctly with the simple AvgAll2 since powers of 2 blocks will always split into equal odd/even lists. Blocks are averaged together with weighted merges. Processes 100000 480p frames in around 30s. Needs GScript:
Code:
function AvgAll(clip c) { GScript(""" frms = c.FrameCount() pow2 = 1 totl = 0 while (frms > 0) { if (frms % 2 > 0) { blkAvg = c.Trim(0,-pow2).AvgAll2() c = c.Trim(pow2,0) if (totl == 0) { avg = blkAvg } else { avg = Merge( avg, blkAvg, Float(pow2)/(totl+pow2) ) } totl = totl + pow2 } frms = frms / 2 pow2 = pow2 * 2 } """) return avg } function AvgAll2(clip c) { c.FrameCount() <= 1 ? c : AvgAll2( Merge(c.SelectEven(), c.SelectOdd()) ) } Edit2: So go 16-bit. Accurate, slower, 10000 frames in a minute. Needs DitherTools: Code:
function AvgAll_16(clip c) { GScript(""" c = c.Dither_convert_8_to_16() # To 16 bit c = c.Dither_lut16("x 0.5 *", U=3,V=3) # down to 15-bit to get faster average below frms = c.FrameCount() pow2 = 1 totl = 0 while (frms > 0) { if (frms % 2 > 0) { blkAvg = c.Trim(0,-pow2).AvgAll2_16() c = c.Trim(pow2,0) if (totl == 0) { avg = blkAvg } else { avg = Merge_16( avg, blkAvg, Float(pow2)/(totl+pow2) ) } totl = totl + pow2 } frms = frms / 2 pow2 = pow2 * 2 } """) return Dither_add16(avg,avg).DitherPost(mode=-1) # Back to 16 bit then to 8 again } # Same as AvgAll2 for 8-bit, but uses faster average (assumes 15-bit input values) function AvgAll2_16(clip c) { c.FrameCount() <= 1 ? c \ : AvgAll2_16( Dither_add16(c.SelectEven(),c.SelectOdd()).Dither_lut16("x 0.5 *", U=3,V=3) ) } # Like Avisynth native Merge but for 16-bit clips function Merge_16(clip a, clip b, float "weight") { weight = default(weight, 0.5) mul1 = String(1.0-weight) a = a.Dither_lut16("x "+mul1+" *", U=3,V=3) mul2 = String(weight) b = b.Dither_lut16("x "+mul2+" *", U=3,V=3) return Dither_add16(a, b) } Last edited by -Vit-; 24th June 2012 at 04:46. |
24th June 2012, 04:46 | #8 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,869
|
Hmm if we go to gscript, what if we stack each line and resize the whole thing? Should have 32bit accuracy...
Code:
function AvgAll3(clip c){ c=c.pointresize(c.width,c.height*2)#use fat lines to workaround minheight GScript(""" frms = c.FrameCount() for (y=0, c.Height/2-1) { for (t=0, frms-1) { f=t==0?getline(c,y,t):stackvertical(f,getline(c,y,t)) } f=f.pointresize(f.width,4)#this has to change to some command to get averageluma #maybe f.blankclip(f.width,2,color_yuv=averageluma) result=y==0?f:stackvertical(result,f) } result.pointresize(result.width, result.height/2) """) } function getline(clip c, int y, int t){ y=y*2 c.trim(t,t==0?-1:t) #return a line of height 2 from y to y+1 crop(0,y,0,-(last.height-y-2)) } @Gavino Which brings me to a point, it's not trivial to write practical (fast) pixel manipulation in Avisynth. People keep telling me to just write plugins, but I'd have to write a dozen plugins by now just to do simple pixel manipulation tasks (measuring pixels, draw rectangles, plot test patterns etc.) I just don't think you should need a new plugin for these tasks. So my conclusion, is something is wrong with the language. Being turing complete is not an answer, it has to be convenient and also fast, in this case expressive to pixel tasks. Interesting, I've asked you this before http://forum.videohelp.com/threads/3...=1#post2119128 Last edited by jmac698; 24th June 2012 at 06:01. |
24th June 2012, 14:57 | #9 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,433
|
Quote:
The slowdown is because Merge is optimised for a weight of 0.5 (or 0.0 or 1.0). Really neat algorithm. |
|
24th June 2012, 15:07 | #10 | Link | |||
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,433
|
Quote:
Quote:
Once you've written one plugin, writing another one (especially if similar) is very easy. You wouldn't even need a new plugin - just keep adding new functions which could use shared code for common tasks. And once you have your development environment set up, recompilation and reloading your DLL only takes a few seconds. Quote:
|
|||
24th June 2012, 18:00 | #11 | Link | |
Excessively jovial fellow
Join Date: Jun 2004
Location: rude
Posts: 1,100
|
Quote:
There are things that are very easy to do in Avisynth script, and there are things that are very hard, because unlike, say, C, Avisynth script isn't intended to be a general-purpose language. If your tool isn't suited to the task at hand, use a different tool. Your obstinate insistence on using Avisynth script for absolutely everything under the sun and then complaining about how there is "something wrong with the language" is getting really annoying. Last edited by TheFluff; 24th June 2012 at 18:02. |
|
9th July 2012, 05:42 | #12 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,869
|
I made a plugin in for this. Only problem, the script is faster! Thanks vit.
http://www.sendspace.com/filegroup/9...%2BWcMacRzuyCQ My plan now is write a pixel manipulation plugin, so I don't have to make a dozen plugins |
11th July 2012, 12:25 | #13 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,990
|
3 new plugins in two days,
methinks we witness the birth of a monster. EDIT: 4 new plugins in two days, Will this madness never end. EDIT: Ref to following post, Frankenstein was the scientist fellow, don't think the monster was ever named.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 11th July 2012 at 18:26. |
11th July 2012, 13:00 | #14 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,869
|
You're only to blame man, you threw the switch with that plugin sample! Frankenstein is born!
But I have to thank you heaps for that I'm telling you, I need *dozens* of plugins for the stuff I do, that's why I think it's gonna get ridiculous. I'm thinking of a meta plugin that does vector operations on all lines in parallel, as most of my stuff operates on the line level. Stuff like limit change per line, random values per line, cast to deep color stacked format, array operations, basic math, subpixel shifting, resizing, indexed replacements from video list, etc. |
Thread Tools | Search this Thread |
Display Modes | |
|
|