Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* Inpainting experiments in Avisynth
- Dependencies:
- Avisynth+ (or wrap all the ifs and whiles in GScript blocks)
- CLExpr
- Dither tools
- MaskTools v2
- RgTools
- VariableBlur
- */
- /* first, we have Gaussian blur functions.
- these use three box filters for large variance and fall back to binomial blur and/or a three-tap
- kernel. expect slowness and also note that the speed is not necessarily continuous wrt variance or
- sigma. they should still be faster than GaussianBlur though (not that you have a choice if you're
- doing 16-bit). */
- function blur_var(clip c,float "var")
- {
- if (var <= 0) {return c}
- while (var >= 4)
- {
- r = floor(sqrt(var))
- w = 2*r-1
- c = (r == 2) ? c.removegrain(20,0,0) : c.averageblur(r-1)
- c = (r == 2) ? c.removegrain(20,0,0) : c.averageblur(r-1)
- c = (r == 2) ? c.removegrain(20,0,0) : c.averageblur(r-1)
- var = var - (w*w-1)/4
- }
- if (var >= 0.5)
- {
- fvar = floor(var*2)*0.5
- c = c.binomialblur(fvar)
- var = var - fvar
- }
- return c.blur(log(1-var)/log(0.5)) # why is this logarithmic? :avisynth:
- }
- function blur_var16(clip c,float "var")
- {
- if (var <= 0) {return c}
- while (var >= 4)
- {
- r = floor(sqrt(var))
- w = 2*r-1
- c = (r == 2) ? c.Dither_removegrain16(20,0,0) : c.Dither_box_filter16(radius=r,u=2,v=2)
- c = (r == 2) ? c.Dither_removegrain16(20,0,0) : c.Dither_box_filter16(radius=r,u=2,v=2)
- c = (r == 2) ? c.Dither_removegrain16(20,0,0) : c.Dither_box_filter16(radius=r,u=2,v=2)
- var = var - (w*w-1)/4
- }
- while (var >= 0.5)
- {
- c = c.Dither_removegrain16(11,0,0)
- var = var - 0.5
- }
- a = " "+string(var*0.5)
- b = " "+string(1-var)
- return c.dither_resize16(c.width(),c.height()/2,kernel="impulse"+a+b+a,fh=-1,fv=-1,u=2,v=2)
- }
- function blur_sigma(clip c,float sigma)
- {
- return blur_var(c,sigma*sigma)
- }
- function blur_sigma16(clip c,float sigma)
- {
- return blur_var16(c,sigma*sigma)
- }
- /* this is for merging clips with a binary mask, which avoids the 255/256 error when using mt_merge.
- (this error is actually very significant when trying to do in-painting with only 8-bit precision.)
- it's also a bit slower than mt_merge (4000-ish fps versus 7000-ish fps on SD) but durr. */
- function binarymerge(clip a,clip b,clip mask,int "y",int "u",int "v",string "chroma")
- {
- aa = mt_logic(mask,a,mode="andn",y=y,u=u,v=v,chroma=chroma) # recall that andn has the input arguments "switched"
- bb = mt_logic(mask,b,mode="and",y=y,u=u,v=v,chroma=chroma)
- mt_logic(aa,bb,mode="or",y=y,u=u,v=v,chroma=chroma)
- }
- /* now, the actual inpainting filters.
- the 8-bit filter is actually quite bad because the blurring itself already loses a lot of precision,
- and then the dynamic range expansion in removing the alpha channel makes the error even worse. could
- probably be mitigated by using some form of dithering, but :effort: and that might still look bad.
- for all intents and purposes, the 16-bit filter should be considered the only working version. it
- works identically, just with a lot less rounding error. note that the "binary mask" for the 16-bit
- version should have values 0 and 65535, not 0 and 255*256.
- in either version, if the area to be inpainted is too large and sigma is too small, the resulting
- frames will have black patches near the centre of the inpainting regions. raise sigma if that
- happens. */
- function inpaint(clip src,clip mask,float sigma,int n,int "y")
- {
- c = binarymerge(src,src.mt_lut(y=0),mask)
- alpha = mask.mt_invert()
- for (i=n, 1, -1)
- {
- s = sigma*i/n
- c = binarymerge(src,c.blur_sigma(s),mask)
- alpha = binarymerge(mask.mt_invert(),alpha.blur_sigma(s),mask)
- c = mt_lutxy(c,alpha,"y 100 < x x y / 255 * round ?")
- alpha = alpha.mt_binarize(99,mode="255 x")
- }
- return mt_lutxy(c,alpha,"x y / 255 * round",y=y).mergechroma(src)
- }
- function inpaint16(clip src,clip mask,float sigma,int n,int "y")
- { # src/mask are stacked 16-bit clips
- c = binarymerge(src,src.mt_lut(y=0),mask)
- alpha = mask.mt_invert()
- for (i=n, 1, -1)
- {
- s = sigma*i/n
- c = binarymerge(src,c.blur_sigma16(s),mask)
- alpha = binarymerge(mask.mt_invert(),alpha.blur_sigma16(s),mask)
- c = cl_exprxy(c,alpha,"y 25600 < x x y / 65535 * round ?",lsb=true)
- alpha = alpha.cl_expr("x 25600 < x 65535 ?",lsb=true)
- }
- return cl_exprxy(c,alpha,"x y / 65535 * round",y=y,lsb=true).mergechroma(src)
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement