View Full Version : Avisynth Descratch Improvement
VideoMilk78
21st November 2024, 15:31
Hello, I've been using my own variation of John Meyers and VideoFreds scripts for film restoration for a while now but sometimes their scripts have issues with scratches that last multiple frames, that's where Fizick's Descratch filter comes in handy, but it removes things that resemble scratches as well like lamp poles and fence posts. I was wondering if any people a bit more skilled at Avisynth could make a function where you crop out the area with the scratch, apply descratch and then overlay the cleaned portion onto the original frame something like this:
DescratchC(left,top,-right,-bottom,mindif,maxwidth)
Thanks in advance to anyone who decides to contribute.
StainlessS
21st November 2024, 18:36
from here:- https://forum.doom9.org/showthread.php?p=1980812#post1980812
I think this works OK (Not much testing),
does similar to above post, but with x,y,w,h coords for inner area (as in crop),
It requires YUV444 (eg YV24) or RGB input OR colorspace compatible crop coords.
Function AreaOp_444(clip c,int x,int y,int w, int h, String Op) {
/*
YUV444 (eg YV24) or RGB only (or coords already crop compatible with colorspace eg all mod 2 for YV12, else error)
x,y,w,h, coords of inner area as per crop(x,y,w,h), w and h can be <= 0 where width or height relative.
op is Operation eg "BlackNess()" OR "Levels(16,1.0,235,235,16,coring=False)"
*/
# Make w and h -ve or 0, ie width or height relative.
w = (w <= 0) ? w : (x + w) - c.Width()
h = (h <= 0) ? h : (y + h) - c.Height()
Area=c.crop(x,y,w,h) # Inner Area
# Borders, Full width top and bottom, short left and right
Above = (y>0) ? c.crop(0,0,c.width(),y) : NOP
Below = (h<0) ? c.crop(0,c.Height()+h,c.width(),0) : NOP
Left = (x>0) ? c.crop(0,y,x,h) : NOP
Right = (w<0) ? c.crop(c.Width+w,y,0,h) : NOP
Eval("Area." + OP)
IsClip(Left) ? StackHorizontal(Left, Last) : NOP
IsClip(Right) ? StackHorizontal(Last, Right) : NOP
IsClip(Above) ? StackVertical(Above, Last) : NOP
IsClip(Below) ? StackVertical(Last, Below) : NOP
Return Last
}
BlankClip(Color=$FF0000) # RGB32 crop mod 1
# Coords as for crop
AreaOp_444(5,7,-2,-54,"BlackNess()")
https://i.postimg.cc/pTyFczxG/Cool-Git-00.jpg (https://postimages.org/)
EDIT: I think Descratch is YV12 only, so coords must be even.
So something like
AreaOp_444(Left,Top,-Right,-Bottom,"DescratchC(mindif,maxwidth)") # mindif and maxwidth MUST be numbers
EDIT: ("mindif and maxwidth MUST be numbers")
Can use explicit numbers, OR, RT_Stats to embed mindif,maxwidth as numbers into the OP string.
eg
...
mindif=8.0 # [dont offhand know if float or int]
maxwidth=6
OP_Template = "DescratchC(%f,%d)" # %f=Float, %d=int [Use %d for both if Descratch mindif is type int]
OP = RT_String(OP_Template,mindif,maxwidth) # OP = "DescratchC(8.0,6)"
AreaOp_444(Left,Top,-Right,-Bottom, OP)
EDIT: Is that a mistake in your post, DescratchC [or maybe chroma only descratch] ???
EDIT: Or without RT_Stats()
...
mindif=8.0 # [dont offhand know if float or int]
maxwidth=6
OP = "Descratch(" + String(mindif) + "," + String(maxwidth) + ")"
AreaOp_444(Left,Top,-Right,-Bottom, OP)
VideoMilk78
21st November 2024, 19:09
from here:- https://forum.doom9.org/showthread.php?p=1980812#post1980812
EDIT: I think Descratch is YV12 only, so coords must be even.
So something like
AreaOp_444(Left,Top,-Right,-Bottom,"DescratchC(mindif,maxwidth)") # mindif and maxwidth MUST be numbers
EDIT: ("mindif and maxwidth MUST be numbers")
Can use explicit numbers, OR, RT_Stats to embed mindif,maxwidth as numbers into the OP string.
eg
...
mindif=8.0 [dont offhand know if float or int]
maxwidth=6
OP_Template = "DescratchC(%f,%d)" # %f=Float, %d=int [Use %d for both if Descratch mindif is type int]
OP = RT_String(OP_Template,mindif,maxwidth) # OP = "DescratchC(8.0,6)"
AreaOp_444(Left,Top,-Right,-Bottom, OP)
EDIT: Is that a mistake in your post, DescratchC [or maybe chroma only descratch] ???
the C is a typo, my bad
StainlessS
21st November 2024, 19:17
OK, I've added an EDIT:
good luck.
EDIT: and fixed bug, inserted comment '#' before "[dont offhand know if float or int]"
VideoMilk78
21st November 2024, 23:12
OK, I've added an EDIT:
good luck.
EDIT: and fixed bug, inserted comment '#' before "[dont offhand know if float or int]"
keep in mind that I'm pretty new to this and it probably isn't as efficient as possible but this is what I got and I'm pretty satisfied.
Function AreaOp_444(clip c,int x,int y,int w, int h, String Op) {
/*
YUV444 (eg YV24) or RGB only (or coords already crop compatible with colorspace eg all mod 2 for YV12, else error)
x,y,w,h, coords of inner area as per crop(x,y,w,h), w and h can be <= 0 where width or height relative.
op is Operation eg "BlackNess()" OR "Levels(16,1.0,235,235,16,coring=False)"
*/
# Make w and h -ve or 0, ie width or height relative.
w = (w <= 0) ? w : (x + w) - c.Width()
h = (h <= 0) ? h : (y + h) - c.Height()
Area=c.crop(x,y,w,h) # Inner Area
# Borders, Full width top and bottom, short left and right
Above = (y>0) ? c.crop(0,0,c.width(),y) : NOP
Below = (h<0) ? c.crop(0,c.Height()+h,c.width(),0) : NOP
Left = (x>0) ? c.crop(0,y,x,h) : NOP
Right = (w<0) ? c.crop(c.Width+w,y,0,h) : NOP
Eval("Area." + OP)
IsClip(Left) ? StackHorizontal(Left, Last) : NOP
IsClip(Right) ? StackHorizontal(Last, Right) : NOP
IsClip(Above) ? StackVertical(Above, Last) : NOP
IsClip(Below) ? StackVertical(Last, Below) : NOP
Return Last
}
Function DescratchArea(clip o,int "Left",int "Top",int "Right",int "Bottom",int "mindif", int "asym", int "maxgap", int "maxwidth",
\ int "minlen", int "maxlen", int "maxangle", int "blurlen", int "keep", int "border", int "modeY", int "modeU", int "modeV",
\ int "mindifUV", bool "mark")
{
mindif = default(mindif,5)
asym = default(asym,10)
maxgap = default(maxgap,3)
maxwidth = default(maxwidth,3)
minlen = default(minlen,100)
maxlen = default(maxlen,100)
maxangle = default(maxangle,5)
blurlen = default(blurlen,15)
keep = default(keep,100)
border = default(border,2)
modeY = default(modey,1)
modeU = default(modeu,0)
modeV = default(modev,0)
mindifUV = default(mindifuV,0)
mark = default(mark,false)
Left = default(left,0)
Top = default(top,0)
Right = default(right,-0)
Bottom = default(bottom,-0)
OP = "Descratch(" + String(mindif) + ", " + String(asym) + ", " + String(maxgap) + ", " + String(maxwidth) + ", " + String(minlen) + ", " + String(maxlen) + ", " + String(maxangle) + ", " + String(blurlen) + ", " + String(keep) + ", " + String(border) + ", " + String(modeY) + ", " + String(modeU) + ", " + String(modeV) + ", " + String(mindifUV) + ", " + String(mark) + ")"
final=o.AreaOp_444(Left,Top,-Right,-Bottom, OP)
return final
}
EDIT: I was testing this with auto white to see a noticeable difference but when I changed it back to descratch it's not actually removing scratches, not throwing any errors either however
EDIT #2: for some reason now whenever I crop left it crops the right and vice versa
StainlessS
22nd November 2024, 03:07
You're lucky, I only usually visit once per day for a few minutes.
How bout this, I integrated the AreaOp thingy. (totally untested).
/*
DescratchArea():- https://forum.doom9.org/showthread.php?p=2010311#post2010311
as for Descratch but area processed X,Y,W,H, specified as for crop(x,y,w,h), Original Descratch args Left and Right NOT USED.
Supported color formats: YV12, YV16, YV24, as for Descratch.
Coords MUST be crop compatible with colorspace eg all mod 2 for YV12, else error.
x,y,w,h, coords of inner area as per crop(x,y,w,h), w and h can be <= 0 where width or height relative.
Prototype (with defaults):
DescratchArea (clip, int "x"=0, int "y"=0, int "w"=0, int "h"=0,
\ int "mindif"=5, int "asym"=10, int "maxgap"=3, int "maxwidth"=3, int "minlen"=100, int "maxlen"=4096, float "maxangle"=5,
\ int "blurlen"=15, int "keep"=100, int "border"=2, int "modeY"=1, int "modeU"=0, int "modeV"=0, int "mindifUV"=0, bool "mark"=false, int "minwidth"=1)
Default x=0, y=0, w=0, h=0, is full frame. To skip eg 16 pixels from right use w=-16.
With exception of x,y,w,h, MOST other args are just passed on and defaulted within Descratch(),
Left and Right are passed to Descratch as 0, ie we are selecting area ourselves. # Actually now not passed, defaulted in Descratch.
*/
Function DescratchArea(clip c , int "x, int "y", int "w", int "h",
\ int "mindif", int "asym", int "maxgap", int "maxwidth",
\ int "minlen", int "maxlen", int "maxangle", int "blurlen", int "keep", int "border", int "modeY", int "modeU", int "modeV",
\ int "mindifUV", bool "mark", int "minwidth" )
{
x = default(x, 0) # We set defaults for our new args,
y = default(y, 0) # others args just passed on and defaulted within Descratch().
w = default(w, 0)
h = default(h, 0)
# Make w and h -ve or 0, ie width or height relative.
w = (w <= 0) ? w : (x + w) - c.Width()
h = (h <= 0) ? h : (y + h) - c.Height()
Area=c.crop(x,y,w,h) # Inner Area
# Borders, Full width top and bottom, short height left and right
Above = (y>0) ? c.crop(0,0,c.width(),y) : NOP
Below = (h<0) ? c.crop(0,c.Height()+h,c.width(),0) : NOP
Left = (x>0) ? c.crop(0,y,x,h) : NOP
Right = (w<0) ? c.crop(c.Width+w,y,0,h) : NOP
Area.Descratch(
\ mindif=mindif,asym=asym,maxgap=maxgap,maxwidth=maxwidth,minlen=minlen,maxlen=maxlen,maxangle=maxangle,
\ blurlen=blurlen, keep=keep, border=border, modeY=modeY, modeU=modeU, modeV=modeV, mindifUV=mindifUV,mark=mark,minwidth=minwidth,
\ ) # BUG REMOVED "left=0, right=0", let them default inside Descratch.
IsClip(Left) ? StackHorizontal(Left, Last) : NOP
IsClip(Right) ? StackHorizontal(Last, Right) : NOP
IsClip(Above) ? StackVertical(Above, Last) : NOP
IsClip(Below) ? StackVertical(Last, Below) : NOP
Return Last
}
EDIT: Descratch on Wiki:- http://avisynth.nl/index.php/DeScratch
Note, you had default maxlen=100, should have been maxlen=2048 [EDIT: Oops, 4096] as on wiki.
EDIT:
With exception of x,y,w,h, MOST other args are just passed on and defaulted within Descratch(), Left and Right are passed to Descratch as 0, ie we are selecting area ourselves.
When args not supplied by caller, then is UnDefined on entry to the function, you can pass an Undefined arg to eg DeScratch where it will do the
equivalent to arg = Default(arg, Some_Default_Value)
EDIT: OOps, below in blue was period '.' not comma ','.
Area.Descratch(
\ mindif=mindif,asym=asym,maxgap=maxgap,maxwidth=maxwidth,minlen=minlen,maxlen=maxlen,maxangle=maxangle,
\ blurlen=blurlen, keep=keep, border=border, modeY=modeY, modeU=modeU, modeV=modeV, mindifUV=mindifUV,mark=mark,minwidth=minwidth,
\ left=0, right=0)
EDIT: If "right=0" in call to DeScratch causes problem, then change to 2048 [EDIT: Oops, 4096] as in below from Wiki.
int right =
Right margin of processing window (exclusive), default=frame width or 4096.
or remove ", right=0" altogether and let Descratch default it, YES, thats probably the best solution.
I'll change in code above.
EDIT: REMOVED the lot, ie "left=0, right=0", both defaulted inside Descratch.
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.