Gavino
12th January 2011, 13:07
I just don't see why overlay couldn't be "improved" to detect when all inputs are rgb and just do processing in that mode. I can't see any backwards compatibility issues or disadvantage to it.
Well, the 'disadvantage' is that someone would have to do the work to implement that. :)
And we already have Layer as a better alternative for RGB.
BTW Here's a very simple demo of the Overlay issue:
function OverlayN(clip c, clip c2, int n) {
GScript("for (i=1, n) { c = c.Overlay(c2, y=32) }")
return c
}
grey = $b4b4b4
BlankClip(10,128,128, color=grey)
b = BlankClip(last, height=height/2)
Animate(0, 9, "OverlayN", b, 0, b, 99)
Oh - you must think GScript obsoletes recursion - yeah, good point :)
Recursion is still necessary for certain types of processing (eg tree-based algorithms). But for the majority of cases where recursion was needed in Avisynth, most people will find it easier to use a loop.
fvisagie
11th December 2012, 20:45
It seems that the Block statements documentation (http://avisynth.org/mediawiki/Block_statements) overlooks one of the main features, being the Avisynth execution model itself. That is if I understand it correctly ;). "Only filters -ie their resulting clips- that are linked by the final clip returned by the script are part of the filter graph." I understand that to mean that when _clips_ are used as operands in conditional statements, any code, filters and clips associated with clips _not_ used in the result will be excluded from the filter graph, without the scripter having to explicitly subject such code, filters or clips to conditions for processing or performance reasons.
If that's understood correctly, it not only makes writing conditional code implicit to Avisynth scripting, it also automatically optimises the script for execution performance - no unnecessary code is executed. Provided clips are used as operands in the conditional statement.
Here's a somewhat long-winded but at least actual example. You can actually skip straight from the function definition to the conditional statement at the bottom.
function ALBR(clip a, string "mode", ... ) {
...
mode = Default(mode, "AdSharp")
Assert((mode == "AdSharp") ? true : \
(mode == "Sharpen") ? true : \
(mode == "Denoise") ? true : \
false, """'mode' choice """" + mode + """" is invalid""")
...
#-------------------------------------------
# Save source clip motion vectors
#
# Identify large moving areas using larger blocks
# For blurry source choose lambda and pnew values that slightly relax coherence to prevent too many MVs being discarded and causing motion distortion
#
a.MSuper(hpad=hpad, vpad=vpad, pel=pel, rfilter=rfilter)
bvec3 = (degrain == 3) ? \
MAnalyse(isb=true, delta=3, blksize=blksizA, overlap=ovrlapA, temporal=temporl, lambda=lambda, pnew=pnew) : BlankClip()
bvec2 = (degrain >= 2) ? \
MAnalyse(isb=true, delta=2, blksize=blksizA, overlap=ovrlapA, temporal=temporl, lambda=lambda, pnew=pnew) : BlankClip()
bvec1 = MAnalyse(isb=true, delta=1, blksize=blksizA, overlap=ovrlapA, temporal=temporl, lambda=lambda, pnew=pnew)
fvec1 = MAnalyse(isb=false, delta=1, blksize=blksizA, overlap=ovrlapA, temporal=temporl, lambda=lambda, pnew=pnew)
fvec2 = (degrain >= 2) ? \
MAnalyse(isb=false, delta=2, blksize=blksizA, overlap=ovrlapA, temporal=temporl, lambda=lambda, pnew=pnew) : BlankClip()
fvec3 = (degrain == 3) ? \
MAnalyse(isb=false, delta=3, blksize=blksizA, overlap=ovrlapA, temporal=temporl, lambda=lambda, pnew=pnew) : BlankClip()
# Refine motion vectors using smaller blocks to capture fine motion detail, edges and more complex motion
# For blurry source relax re-estimation threshold to prevent too many MVs being discarded and causing motion distortion
bvec3 = (degrain == 3) ? \
MRecalculate(bvec3, thSAD=thSADR, blksize=blksizR, overlap=ovrlapR, lambda=lambda, pnew=pnew) : bvec3
bvec2 = (degrain >= 2) ? \
MRecalculate(bvec2, thSAD=thSADR, blksize=blksizR, overlap=ovrlapR, lambda=lambda, pnew=pnew) : bvec2
bvec1 = MRecalculate(bvec1, thSAD=thSADR, blksize=blksizR, overlap=ovrlapR, lambda=lambda, pnew=pnew)
fvec1 = MRecalculate(fvec1, thSAD=thSADR, blksize=blksizR, overlap=ovrlapR, lambda=lambda, pnew=pnew)
fvec2 = (degrain >=2 ) ? \
MRecalculate(fvec2, thSAD=thSADR, blksize=blksizR, overlap=ovrlapR, lambda=lambda, pnew=pnew) : fvec2
fvec3 = (degrain == 3) ? \
MRecalculate(fvec3, thSAD=thSADR, blksize=blksizR, overlap=ovrlapR, lambda=lambda, pnew=pnew) : fvec3
# Save copies of motion vector data for display and tuning purposes
a_super = last
afvec = fvec1
#-------------------------------------------
# Create frame-adaptive repair mask
#
# Identify detailed vs. flat areas (luma only)
#
edgemsk = a.mt_edge(mode="hprewitt", thY1=thshlow, thY2=thshhi, y=3, u=-128, v=-128)
# Consolidate detailed and flat areas
consmsk = edgemsk.medianblur(rc, 0, 0)
# Normalise mask levels to around full range to prevent sharp transitions around mask edges
consmsk.Levels(Max(0, thshlow-1), 1.000, Min(255,(thshhi+1)), 0, 255, coring=false)
# Deband mask
binomialBlur(vmdb, 0.0, 3, 2, 2, true)
albmask = mt_invert(y=3, u=-128, v=-128)
#-------------------------------------------
# Create sharpened clip
#
# Purposely try to "sharpen" chroma too
#
Eval(Select(shrpnum, \
"""a.gaussianblur(varY=vshy, varC=vshc, y=ysh, u=ush, v=vsh).mt_lutxy(a, "y x - " + String(strsh) + " * y +", y=ysh, u=ush, v=vsh)""", \
"""a.unsharp(varY=vshy, varC=vshc, strength=strsh, y=ysh, u=ush, v=vsh)""", \
"""a.mt_lutxy(a.repair(a.repair(a.repair(a.repair(a.repair(a.repair(a.repair(a.repair(a.medianblur(rshy, rshc, rshc), 4), 4), 4), 4), 4), 4), 4), 4), \
"x x y - abs " + string(strsh, "%#.2f") + " 2 ^ / 1 " + string(strsh, "%#.2f") + " / ^ " + string(strsh, "%#.2f") + " 3 ^ * x y - x y - abs " \
+ string(strsh, "%#.2f") + " + / * +", y=ysh, u=ush, v=vsh)""", \
"""a.mt_lutxy(a.medianblur(rshy, rshc, rshc), "x x y - abs " + string(strsh, "%#.2f") + " 2 ^ / 1 " + string(strsh, "%#.2f") + " / ^ " \
+ string(strsh, "%#.2f") + " 3 ^ * x y - x y - abs " + string(strsh, "%#.2f") + " + / * +", y=ysh, u=ush, v=vsh)""", \
"""a.TUnSharp(strength=Int(strsh), thresholdL=thL, thresholdU=thU, type=type, map=map, lim=lim, radius=rshy, gui=false)""" \
) \
)
# Normalise levels somewhat after including chroma above
shrp = ((hue != 0.0) || (sat != 1.0) || (bright != 0.0) || (cont != 1.0)) ? Tweak(hue=hue, sat=sat, bright=bright, cont=cont, coring=false) : last
#-------------------------------------------
# Use motion-compensated averaging to temporally smooth sharpening artifacts and remove some noise
#
shrp_super = shrp.MSuper(hpad=hpad, vpad=vpad, pel=pel, rfilter=rfilter, levels=1)
# Recalculate vectors to account for improved structure
bvec3 = (degrain == 3) ? \
shrp_super.MRecalculate(bvec3, thSAD=thSADR, blksize=blksizR, overlap=ovrlapR, lambda=lambda, pnew=pnew) : bvec3
bvec2 = (degrain >= 2) ? \
shrp_super.MRecalculate(bvec2, thSAD=thSADR, blksize=blksizR, overlap=ovrlapR, lambda=lambda, pnew=pnew) : bvec2
bvec1 = shrp_super.MRecalculate(bvec1, thSAD=thSADR, blksize=blksizR, overlap=ovrlapR, lambda=lambda, pnew=pnew)
fvec1 = shrp_super.MRecalculate(fvec1, thSAD=thSADR, blksize=blksizR, overlap=ovrlapR, lambda=lambda, pnew=pnew)
fvec2 = (degrain >= 2) ? \
shrp_super.MRecalculate(fvec2, thSAD=thSADR, blksize=blksizR, overlap=ovrlapR, lambda=lambda, pnew=pnew) : fvec2
fvec3 = (degrain == 3) ? \
shrp_super.MRecalculate(fvec3, thSAD=thSADR, blksize=blksizR, overlap=ovrlapR, lambda=lambda, pnew=pnew) : fvec3
# Leave thSAD high enough (400) for only really bad vectors potentially to be re-evaluated - balance against introducing noise
sharpnd = (degrain == 3) ? shrp.MDegrain3(shrp_super, bvec1, fvec1, bvec2, fvec2, bvec3, fvec3) : \
(degrain == 2) ? shrp.MDegrain2(shrp_super, bvec1, fvec1, bvec2, fvec2) : \
shrp.MDegrain1(shrp_super, bvec1, fvec1)
#-------------------------------------------
# Mode decision
#
# "AdSharp" : use repair mask to merge original with sharpened clip
# "Sharpen" : continue with sharpened clip directly
# "Denoise" : continue with input clip
#
mrgd = (mode == "AdSharp") ? mt_merge(a, sharpnd, albmask, luma=false, y=ysh, u=ush, v=vsh) : \
(mode == "Sharpen") ? sharpnd : \
a
...
}
So, when mode == "Denoise", effectively everything up to the last conditional statement is excluded from the filter graph.
If I have this right, in my view this is a major benefit of the Avisynth execution model, and perhaps deserves a mention in the Block statements section?
Gavino
11th December 2012, 22:24
So, when mode == "Denoise", effectively everything up to the last conditional statement is excluded from the filter graph.
That's right.
Note however that 'unused' filters, although no frames will be requested from them at run-time, still get instantiated at compile-time, potentially consuming memory, unless they are on the 'false' part of a conditional branch.
So here the MAnalyses of bvec1 and fvec1, for example, are always instantiated.
Also, in code like
bvec3 = (degrain == 3) ? \
MAnalyse(isb=true, delta=3, blksize=blksizA, overlap=ovrlapA, temporal=temporl, lambda=lambda, pnew=pnew) : BlankClip()
MAnalyse is not instantiated unless degrain==3, but BlankClip is instead. In cases like this I prefer to use NOP() instead of BlankClip() - as well as a (notional) efficiency gain, this shows that the result is not intended to be used (and will provoke an error if I have screwed up the later logic and actually did use it).
Finally note that the '||' operator (and similarly for '&&') is optimised to only evaluate as far as it needs to determine its result, so
Assert((mode == "AdSharp") ? true : \
(mode == "Sharpen") ? true : \
(mode == "Denoise") ? true : \
false, """'mode' choice """" + mode + """" is invalid""")
could be written simply as
Assert((mode == "AdSharp") || (mode == "Sharpen") || (mode == "Denoise"), \
"""'mode' choice """" + mode + """" is invalid""")
As for the block statements (http://avisynth.org/mediawiki/Block_statements) page, the constructs described there are really ugly, which is why I developed GScript. ;)
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.