Mug Funky
22nd March 2004, 08:23
hey yo, before you point out there's an "autogain" function already...
this script functions in a similar manner to a a VCR's AGC circuit, or in more general terms, a dynamic compressor. the difference here is that it's based on temporalsoften, meaning it has scenechange detection :)
AGC circuits will amplify a too-dark video and reduce a too-bright signal. (this is how Macrovision works - by putting 3-4x white lines in the overscan area, the AGC circuit is fooled into turning the brightness down to stupidly low levels.)
i made this because i have a wide variety of too-dark videos, and the pumping effects of colorYUV(autogain=true) were just too horrible for compressibility and aesthetics, as it works on every frame.
this script will average over several frames (originally i had a lot of scripting for this, until i had a brain freeze and realised temporalsoften(4,255,255,255,2) did exactly what i wanted), then up the gain (in RGB).
this is rather like having an attack time and a release time...
here's the script:
global gl_lum=1
function AGC (clip c, int "mode",float "multiplier", float "gamma", int "radius",int "scenechange", bool "luma")
{
global gl_radius = default(radius,4)
global gl_scenechange = default(scenechange,20)
global gl_multiplier = default(multiplier,.96)
global gl_c = c
global gl_gamma = default(gamma,1)
mode= default(mode, 2)
luma = default(luma,true)
global gl_multiplier = (mode==2)? float(gl_multiplier*2) :
\ float(gl_multiplier)
global gl_method = (mode==1)? "averageluma()" :
\ (mode==2)? "YplaneMax()" : "YplaneMedian()"
gl_c=gl_c.frameevaluate("global gl_lum = gl_multiplier*128/
\ (gl_c.deleteframe(0).reduceby2().reduceby2().
\ temporalsoften(gl_radius,255,255,gl_scenechange,2).
\ levels(0,gl_gamma,255,0,255,coring=false)." + string(gl_method + ")")
\ ,after_frame=false)
(luma==true)? gl_c.scriptclip("coloryuv(gain_y=round(gl_lum * 256)-256)") :
\ gl_c.scriptclip("converttorgb32().RGBadjust(gl_lum,gl_lum,gl_lum,0).converttoyv12()")
}
WARNING: this script is EXTREMELY unstable - i'm new to conditional filtering, so that's bound to be the problem. put this last in your script - any temporal filters after it will crash avisynth (i've been able to run spatial filters after it with varying reliability, so you can experiment... funkydenoise() works)
if anybody can help make this more useful they are very much encouraged to do so :)
usage:
mode - integer defining whether averageluma() is used (1), YplaneMax() (2), or YplaneMedian (3). i wouldn't bother with median, as it is hell on dark videos. probably the most useful one is mode 2.
multiplier - global scale of the output... you may need to lower this for particularly colourful clips, where luma is unexpectedly low and chroma high.
radius - this is attack/release time in frames (the radius param in temporalsoften). default is 4, to prevent small pumping in mode=2, try increase it (but if you get error text decrease it again)
scenechange - best left at default, or if you want to have fading after scenechanges (too make it look like an old tape), raise it to 255.
gamma - this will move the average level around, if need be. useful for videos with dark backround and light foreground - increase the gamma value and the average goes up, meaning less gain is applied. more predictable then tweaking multiplier... agc(gamma=2) will make a video come out lower, agc(gamma=0.75) will make it brighter by a lot.
luma - boolean. default true. this will only add gain to luma, rather than converting to RGB and doing each channel (which is a truer kind of gain, but often meaningless for TV caps, and slower to boot)
have fun people!
[edit]
updated the script so multiplier is doubled for mode = 2
[edit edit]
another slight update. it's now way more stable, and a little faster in certain situations. you can now run filters after it, it seems.
[edit 3]
added some line breaks for Scharfis_Brain, careful not to break the script in the process. :)
[edit 4]
added gamma (well added this before but forgot to document it) and luma-only mode.
this script functions in a similar manner to a a VCR's AGC circuit, or in more general terms, a dynamic compressor. the difference here is that it's based on temporalsoften, meaning it has scenechange detection :)
AGC circuits will amplify a too-dark video and reduce a too-bright signal. (this is how Macrovision works - by putting 3-4x white lines in the overscan area, the AGC circuit is fooled into turning the brightness down to stupidly low levels.)
i made this because i have a wide variety of too-dark videos, and the pumping effects of colorYUV(autogain=true) were just too horrible for compressibility and aesthetics, as it works on every frame.
this script will average over several frames (originally i had a lot of scripting for this, until i had a brain freeze and realised temporalsoften(4,255,255,255,2) did exactly what i wanted), then up the gain (in RGB).
this is rather like having an attack time and a release time...
here's the script:
global gl_lum=1
function AGC (clip c, int "mode",float "multiplier", float "gamma", int "radius",int "scenechange", bool "luma")
{
global gl_radius = default(radius,4)
global gl_scenechange = default(scenechange,20)
global gl_multiplier = default(multiplier,.96)
global gl_c = c
global gl_gamma = default(gamma,1)
mode= default(mode, 2)
luma = default(luma,true)
global gl_multiplier = (mode==2)? float(gl_multiplier*2) :
\ float(gl_multiplier)
global gl_method = (mode==1)? "averageluma()" :
\ (mode==2)? "YplaneMax()" : "YplaneMedian()"
gl_c=gl_c.frameevaluate("global gl_lum = gl_multiplier*128/
\ (gl_c.deleteframe(0).reduceby2().reduceby2().
\ temporalsoften(gl_radius,255,255,gl_scenechange,2).
\ levels(0,gl_gamma,255,0,255,coring=false)." + string(gl_method + ")")
\ ,after_frame=false)
(luma==true)? gl_c.scriptclip("coloryuv(gain_y=round(gl_lum * 256)-256)") :
\ gl_c.scriptclip("converttorgb32().RGBadjust(gl_lum,gl_lum,gl_lum,0).converttoyv12()")
}
WARNING: this script is EXTREMELY unstable - i'm new to conditional filtering, so that's bound to be the problem. put this last in your script - any temporal filters after it will crash avisynth (i've been able to run spatial filters after it with varying reliability, so you can experiment... funkydenoise() works)
if anybody can help make this more useful they are very much encouraged to do so :)
usage:
mode - integer defining whether averageluma() is used (1), YplaneMax() (2), or YplaneMedian (3). i wouldn't bother with median, as it is hell on dark videos. probably the most useful one is mode 2.
multiplier - global scale of the output... you may need to lower this for particularly colourful clips, where luma is unexpectedly low and chroma high.
radius - this is attack/release time in frames (the radius param in temporalsoften). default is 4, to prevent small pumping in mode=2, try increase it (but if you get error text decrease it again)
scenechange - best left at default, or if you want to have fading after scenechanges (too make it look like an old tape), raise it to 255.
gamma - this will move the average level around, if need be. useful for videos with dark backround and light foreground - increase the gamma value and the average goes up, meaning less gain is applied. more predictable then tweaking multiplier... agc(gamma=2) will make a video come out lower, agc(gamma=0.75) will make it brighter by a lot.
luma - boolean. default true. this will only add gain to luma, rather than converting to RGB and doing each channel (which is a truer kind of gain, but often meaningless for TV caps, and slower to boot)
have fun people!
[edit]
updated the script so multiplier is doubled for mode = 2
[edit edit]
another slight update. it's now way more stable, and a little faster in certain situations. you can now run filters after it, it seems.
[edit 3]
added some line breaks for Scharfis_Brain, careful not to break the script in the process. :)
[edit 4]
added gamma (well added this before but forgot to document it) and luma-only mode.