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. |
|
|
Thread Tools | Search this Thread | Display Modes |
19th March 2013, 21:03 | #1 | Link |
Registered User
Join Date: Oct 2001
Posts: 106
|
Measure grain level of clip? (how to use static type variable to calc avg?)
Is there a way, through an AVISynth script, to put some number (even if it's just some unit-less number with little meaning other than being a scale) on the amount of grain contained in a clip? I suppose it could be normalized in a range of 0.0 - 1.0, where the values indicate the amount of graininess. Numbers closer to 0 indicate less grain, while numbers closer to 1.0 indicate more grain.
The reason I ask, is it'd be nice to first run a small portion of a clip (N frames worth) through a script that measures graininess, and then I adjust whether or not to degrain the source (and with what strength) before fulling encoding it. Perhaps I would bucket the clips. Movies with grain between 0.0 - 0.2 get these settings, movies between 0.2 - 0.4 get these settings, etc. Too much grain and the file size of an x264 encode is huge. Too little grain and a lot of banding can result in the x264 encode. Last edited by bennynihon; 25th March 2013 at 19:12. |
20th March 2013, 11:12 | #2 | Link | |
Registered User
Join Date: Oct 2001
Posts: 106
|
Quote:
|
|
25th March 2013, 19:11 | #3 | Link |
Registered User
Join Date: Oct 2001
Posts: 106
|
So the GrainEvaluate function is below. Is there a way to use a static variable (or mimic one) that accumulates the grain that's calculated for each frame and finds the average grain for the entire clip? I tried using a global variable (ydiff) in my main script and have the GrainEvaluate function accumulate the value to that global variable (the 'ydiff = ydiff + grainStrY' line below). However, it complains that it doesn't know what grainStrY is. Odd because it's assigned a value directly above in the FrameEvaluate line.
Code:
Function GrainEvaluate(clip c, string "file", bool "Y", bool "U", bool "V"){ file = Default( file, "GrainEvaluateFile.txt") Y = Default( Y, true ) U = Default( U, false ) V = Default( V, U ) last = c global GE_nr = RemoveGrain(Y?4:-1, U?4:-1, V?4:-1) global sepF = "frame " global sepY = Y ? "; Y grain strength = " : "" global sepU = U ? "; U grain strength = " : "" global sepV = V ? "; V grain strength = " : "" Y ? FrameEvaluate("global grainStrY = LumaDifference(GE_nr)" ) : nop U ? FrameEvaluate("global grainStrU = ChromaUDifference(GE_nr)") : nop V ? FrameEvaluate("global grainStrV = ChromaVDifference(GE_nr)") : nop ydiff = ydiff + grainStrY WriteFile(file, \ "sepF", "current_frame", \ "sepY", Y ? "grainStrY" : "", \ "sepU", U ? "grainStrU" : "", \ "sepV", V ? "grainStrV" : "", \ append=false) return last } |
25th March 2013, 20:41 | #4 | Link | |
Registered User
Join Date: Feb 2002
Location: California
Posts: 2,691
|
Quote:
function GenerateMask Scroll down in the code section to the last function in the code. The reason I did it that way is that the luma differences (which is what I was trying to estimate, instead of grain) tend to vary over the course of any clip, and the only thing that matters is the behavior in the local vicinity of each frame. By using a moving average, the function adapts to local conditions and therefore produces better results. If this applies to your situation, perhaps you can adapt the idea (and the code) to your function. If this IS useful to you, then perhaps you could add some code to adapt the moving average at scene changes, something I didn't bother to do. |
|
25th March 2013, 20:47 | #5 | Link |
Registered User
Join Date: Oct 2001
Posts: 106
|
@johnmeyer
I'm only using this to ascertain how "grainy" a clip is (I use SelectRangeEvery to analyze just a few minutes of a long movie), and then choose whether or not (and how strong) to degrain it using MDegrain with motion compensation. The idea is to use something like the GrainEvaluate function (which currently prints out the grain level per frame to a file), but instead accumulate those per frame grain values to calculate an average over the frames I evaluate. It doesn't have to be perfect, but with enough of a sample size it gives a good relative metric for how grainy a movie is. |
25th March 2013, 20:49 | #6 | Link | |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Look into what JM said, but this might be an immediate problem you have
Code:
Global ydiff = ydiff + grainStrY # need to use Global when assigning to a global, Also a little code that gives more accurate results over entire clip (float is quite limited) Code:
# Requires GScript and ShowChannels plugins. AviSource("D:\avs\avi\1.avi").trim(0,0999) Sum = 0.0 SumHi=0.0 # Hi part Extra precision (need for long scans) SumLo=0.0 # Lo part Extra precision GScript(""" for(n=0,FrameCount()-1) { Tmp = RT_AverageLuma(n) RT_Debug("RT_Debug:","["+String(n)+"]","AveLuma = "+String(Tmp)) # Real Time Debug Info using DebugView # Sum = Sum + Tmp # Were gonna use extra precision instead SumLo = SumLo + Tmp SumHi = SumHi + floor(SumLo / 256.0) # Hi part, Extra Precision SumLo = frac(SumLo / 256.0) * 256.0 # Lo part, Extra Precision } """) # Sum=Sum/Float(FrameCount()) # Were gonna use extra precision instead Sum = (SumHi / Float(FrameCount()) * 256.0) + (SumLo / Float(FrameCount())) s=ShowChannels(ver=true) # Show eg Ave Luma for frame and Accumulated Ave luma for all frames visited s.Subtitle(String(Sum),Align=1) # The sum variable shown on bottom left via Subtitle, is the accumulated Average Luma for entire clip, will be valid on the LAST FRAME. # ShowChannels used for result comparison. EDIT: Quote:
ie Code:
Y ? FrameEvaluate("global grainStrY = LumaDifference(GE_nr)" ,after_frame=true ) : nop
__________________
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; 25th March 2013 at 21:25. |
|
25th March 2013, 21:03 | #7 | Link | ||
Registered User
Join Date: Oct 2001
Posts: 106
|
Quote:
Quote:
|
||
25th March 2013, 21:11 | #8 | Link | ||
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Quote:
Quote:
__________________
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 ??? |
||
25th March 2013, 21:15 | #9 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
Code:
FrameEvaluate("global ydiff = ydiff + grainStrY", after_frame=true) |
|
25th March 2013, 21:17 | #10 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Aha, Big G to the rescue again.
EDIT: Does the After_frame=true, also hold or not ? EDIT: Oops, you already included that, but is it true of the Code:
Y ? FrameEvaluate("global grainStrY = LumaDifference(GE_nr)" ,after_frame=true ) : nop See you replying, Thanx in advance.
__________________
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; 25th March 2013 at 21:38. |
25th March 2013, 21:41 | #11 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
@bennynihon: Another problem I foresee with your script is that you will need to use WriteFile() to get the final value of ydiff out of your script, since it is accumulated at run-time. You could use the ScriptClip("WriteFile(..., append=false")) trick (see this post) so that only the final value is left in the file. An alternative would be to loop over the frames at compile-time using GScript, as in StainlessS's approach in post #7. |
|
25th March 2013, 21:46 | #12 | Link | |
Registered User
Join Date: Oct 2001
Posts: 106
|
Quote:
|
|
25th March 2013, 21:50 | #13 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
Although WriteFileEnd() doesn't actually write its output until script closure, the value itself is evaluated at compile-time, so is no good for what you want to do here. |
|
Thread Tools | Search this Thread |
Display Modes | |
|
|