Motenai Yoda
17th May 2016, 15:20
Here a sharpen I'm worked on some time ago, it's inspired to Didée's prof of concept (http://forum.doom9.org/showthread.php?p=1380002#post1380002),
dependencies:
- Dither tools by cretindesalpes
- MVTools 2.6.x/2.7.x
- MaskTools2 and RgTools by tp7
function MCLS_16(clip c, float "strength", clip "sharp", int "thsad", int "plane",\
float "ss", bool "repair", int "dmode", bool "masked", bool "blur_gaussian")
{
#Motion Compensate Limited Sharpen for a 16bit stacked clip by Motenai Yoda
#first relase - beta 7
#it works (or should) with 16bit stacked clip input/output
strength = Default(strength, 1.0)
thsad = Default(thsad, 400)
plane = Default(plane, 0)
ss = Default(ss, Defined(sharp) ? 1.0 : 1.25)
repair = Default(repair, Defined(sharp) ? false : true)
dmode = Default(dmode, 1)
masked = Default(masked, true)
blur_gaussian = Default(blur_gaussian, false)
str = String(strength)
HD = (c.width > 1280) ? 2 : (c.width > 720) ? 1 : 0
Pel = Select(HD, 2, 1, 1)
Truemotion = Select(HD, True, False, False)
Blksize = Select(HD, 8, 16, 32)
Overlap = Select(HD, 4, 8, 8)
Yp = (plane == 0 || plane == 4) ? 3 : 1
Up = (plane == 1 || plane == 3 || plane == 4) ? 3 : 1
Vp = (plane == 2 || plane == 3 || plane == 4) ? 3 : 1
Chromap = (plane == 0) ? false : true
width2 = Round(c.width*ss)
height2 = Round(c.height*ss/2.0)
wpad = 16-(width2%16)
hpad = 16-(height2%16)
bRadius = Round(Select(HD, 3, 3, 4) / 1.25 * ss)
resized_source = (ss != 1.0) ? c.Dither_resize16(width2+wpad, height2+hpad, y=3, u=Up,\
v=Vp) : c
resized_sharp = Defined(sharp) ? (ss != 1.0) ? sharp.Dither_resize16(width2+wpad, height2+hpad,\
y=Yp, u=Up, v=Vp) : sharp : nop()
pre = resized_source.Dither_removegrain16(3, (Up == 3) ? 3 : -1, (Vp == 3) ? 3 : -1)
sharp0 = Defined(sharp) ? Dither_sub16(resized_sharp, resized_source, wrap=False, y=Yp, u=Up,\
v=Vp, dif=true) : Dither_sub16(resized_source, blur_gaussian ? Dither_box_filter16(resized_source,\
radius=max(bRadius-2, 1), y=Yp, u=Up, v=Vp).Dither_box_filter16(radius=max(bRadius-1,1), y=Yp, u=Up, v=Vp).\
Dither_box_filter16(radius=max(bRadius-1,1), y=Yp, u=Up, v=Vp) : Dither_box_filter16(resized_source,\
radius=bRadius, y=Yp, u=Up, v=Vp), wrap=False, y=Yp, u=Up, v=Vp, dif=true)
source0 = Ditherpost(pre, mode=-1, y=3, u=Up, v=Vp)
mask = (masked) ? source0.mt_edge("min/max", y=3, u=1, v=1).mt_deflate(y=3, u=1, v=1).\
removegrain(12, -1, -1) : nop()
mask = (masked) ? stackvertical(mask, mask) : nop()
sup0 = source0.MSuper(pel=Pel, sharp=2, chroma=Chromap)
sharp0m = sharp0.Dither_get_msb()
sup1 = sharp0m.MSuper(pel=Pel, sharp=2, chroma=Chromap)
sharp0l = sharp0.Dither_get_lsb()
sup2 = sharp0l.MSuper(pel=Pel, sharp=2, chroma=Chromap)
bv1 = sup0.MAnalyse(isb=true, delta=1, chroma=Chromap, blksize=Blksize, truemotion=Truemotion, overlap=Overlap)
fv1 = sup0.MAnalyse(isb=false, delta=1, chroma=Chromap, blksize=Blksize, truemotion=Truemotion, overlap=Overlap)
nullclip = source0.mt_lut(y= (Yp==3) ? -0 : 1, u= (Up==3) ? -0 : 1, v= (Vp==3) ? -0 : 1)
diff1 = sharp0m.MDegrain1(sup1, bv1, fv1, plane=plane, thsad=thsad, lsb=true)
diff2 = sharp0l.MDegrain1(sup2, bv1, fv1, plane=plane, thsad=thsad, lsb=false)
diff2_16 = stackvertical(nullclip, diff2)
diff3 = Dither_add16(diff1, diff2_16, wrap=False, y=Yp, u=Up, v=Vp, dif=false)
sharped_back = Dither_add16(resized_source, diff3, wrap=False, y=Yp, u=Up, v=Vp, dif=true)
repaired = (repair) ? Dither_repair16(sharped_back, resized_source, (Yp == 3) ? 1 : -1 ,\
(Up == 3) ? 1 : -1, (Vp == 3) ? 1 : -1).Dither_merge16(sharped_back,sharped_back.mt_lut(y=-76,\
u=1,v=1),luma=true, y=Yp, u=Up, v=Vp): sharped_back
bias = (dmode == 1) ? resized_source.Dither_lut16("x 4096. - 56064. / 0 1 clip pi * sin 0.5 ^ 65536. * "+\
str+" *", y=3, u=1, v=1) : nop()
bias = (masked) ? (dmode == 1) ? bias.mt_logic(mask, "min", y=3, u=1, v=1) : mask : bias
repaired = (dmode == 1 || masked) ? Dither_merge16(resized_source, repaired, bias, y=Yp, u=Up, v=Vp, luma=true) :\
repaired
resized_back = (ss != 1.0) ? Dither_resize16(repaired, c.width(), c.height()/2, y=Yp, u=Up, v=Vp) : repaired
return ytouv((Up == 3) ? resized_back.utoy() : c.utoy(), (Vp == 3) ? resized_back.vtoy() : c.vtoy(),\
(Yp == 3) ? resized_back : c)
}
edit: removed "keep" and do the blur/sharp on resized_source instead of pre
edit2: fixed some flaw about chroma processing when Y plane is not processed (a bit slower than before if plane = 1/2/3)
note 22/06/2016 : I used mt_logic "min" to merge edgemask and lumamask, as edgemask is basically 0/255, when it's 0 it's the minimum, when it's 255 isn't the minimum, moreover with a lumamask value X = x/256 , if multiplied togheter X*0 = 0, X*(255/255) = X*1 = X
so using a lut to multiply them should give roughtly same result.
dependencies:
- Dither tools by cretindesalpes
- MVTools 2.6.x/2.7.x
- MaskTools2 and RgTools by tp7
function MCLS_16(clip c, float "strength", clip "sharp", int "thsad", int "plane",\
float "ss", bool "repair", int "dmode", bool "masked", bool "blur_gaussian")
{
#Motion Compensate Limited Sharpen for a 16bit stacked clip by Motenai Yoda
#first relase - beta 7
#it works (or should) with 16bit stacked clip input/output
strength = Default(strength, 1.0)
thsad = Default(thsad, 400)
plane = Default(plane, 0)
ss = Default(ss, Defined(sharp) ? 1.0 : 1.25)
repair = Default(repair, Defined(sharp) ? false : true)
dmode = Default(dmode, 1)
masked = Default(masked, true)
blur_gaussian = Default(blur_gaussian, false)
str = String(strength)
HD = (c.width > 1280) ? 2 : (c.width > 720) ? 1 : 0
Pel = Select(HD, 2, 1, 1)
Truemotion = Select(HD, True, False, False)
Blksize = Select(HD, 8, 16, 32)
Overlap = Select(HD, 4, 8, 8)
Yp = (plane == 0 || plane == 4) ? 3 : 1
Up = (plane == 1 || plane == 3 || plane == 4) ? 3 : 1
Vp = (plane == 2 || plane == 3 || plane == 4) ? 3 : 1
Chromap = (plane == 0) ? false : true
width2 = Round(c.width*ss)
height2 = Round(c.height*ss/2.0)
wpad = 16-(width2%16)
hpad = 16-(height2%16)
bRadius = Round(Select(HD, 3, 3, 4) / 1.25 * ss)
resized_source = (ss != 1.0) ? c.Dither_resize16(width2+wpad, height2+hpad, y=3, u=Up,\
v=Vp) : c
resized_sharp = Defined(sharp) ? (ss != 1.0) ? sharp.Dither_resize16(width2+wpad, height2+hpad,\
y=Yp, u=Up, v=Vp) : sharp : nop()
pre = resized_source.Dither_removegrain16(3, (Up == 3) ? 3 : -1, (Vp == 3) ? 3 : -1)
sharp0 = Defined(sharp) ? Dither_sub16(resized_sharp, resized_source, wrap=False, y=Yp, u=Up,\
v=Vp, dif=true) : Dither_sub16(resized_source, blur_gaussian ? Dither_box_filter16(resized_source,\
radius=max(bRadius-2, 1), y=Yp, u=Up, v=Vp).Dither_box_filter16(radius=max(bRadius-1,1), y=Yp, u=Up, v=Vp).\
Dither_box_filter16(radius=max(bRadius-1,1), y=Yp, u=Up, v=Vp) : Dither_box_filter16(resized_source,\
radius=bRadius, y=Yp, u=Up, v=Vp), wrap=False, y=Yp, u=Up, v=Vp, dif=true)
source0 = Ditherpost(pre, mode=-1, y=3, u=Up, v=Vp)
mask = (masked) ? source0.mt_edge("min/max", y=3, u=1, v=1).mt_deflate(y=3, u=1, v=1).\
removegrain(12, -1, -1) : nop()
mask = (masked) ? stackvertical(mask, mask) : nop()
sup0 = source0.MSuper(pel=Pel, sharp=2, chroma=Chromap)
sharp0m = sharp0.Dither_get_msb()
sup1 = sharp0m.MSuper(pel=Pel, sharp=2, chroma=Chromap)
sharp0l = sharp0.Dither_get_lsb()
sup2 = sharp0l.MSuper(pel=Pel, sharp=2, chroma=Chromap)
bv1 = sup0.MAnalyse(isb=true, delta=1, chroma=Chromap, blksize=Blksize, truemotion=Truemotion, overlap=Overlap)
fv1 = sup0.MAnalyse(isb=false, delta=1, chroma=Chromap, blksize=Blksize, truemotion=Truemotion, overlap=Overlap)
nullclip = source0.mt_lut(y= (Yp==3) ? -0 : 1, u= (Up==3) ? -0 : 1, v= (Vp==3) ? -0 : 1)
diff1 = sharp0m.MDegrain1(sup1, bv1, fv1, plane=plane, thsad=thsad, lsb=true)
diff2 = sharp0l.MDegrain1(sup2, bv1, fv1, plane=plane, thsad=thsad, lsb=false)
diff2_16 = stackvertical(nullclip, diff2)
diff3 = Dither_add16(diff1, diff2_16, wrap=False, y=Yp, u=Up, v=Vp, dif=false)
sharped_back = Dither_add16(resized_source, diff3, wrap=False, y=Yp, u=Up, v=Vp, dif=true)
repaired = (repair) ? Dither_repair16(sharped_back, resized_source, (Yp == 3) ? 1 : -1 ,\
(Up == 3) ? 1 : -1, (Vp == 3) ? 1 : -1).Dither_merge16(sharped_back,sharped_back.mt_lut(y=-76,\
u=1,v=1),luma=true, y=Yp, u=Up, v=Vp): sharped_back
bias = (dmode == 1) ? resized_source.Dither_lut16("x 4096. - 56064. / 0 1 clip pi * sin 0.5 ^ 65536. * "+\
str+" *", y=3, u=1, v=1) : nop()
bias = (masked) ? (dmode == 1) ? bias.mt_logic(mask, "min", y=3, u=1, v=1) : mask : bias
repaired = (dmode == 1 || masked) ? Dither_merge16(resized_source, repaired, bias, y=Yp, u=Up, v=Vp, luma=true) :\
repaired
resized_back = (ss != 1.0) ? Dither_resize16(repaired, c.width(), c.height()/2, y=Yp, u=Up, v=Vp) : repaired
return ytouv((Up == 3) ? resized_back.utoy() : c.utoy(), (Vp == 3) ? resized_back.vtoy() : c.vtoy(),\
(Yp == 3) ? resized_back : c)
}
edit: removed "keep" and do the blur/sharp on resized_source instead of pre
edit2: fixed some flaw about chroma processing when Y plane is not processed (a bit slower than before if plane = 1/2/3)
note 22/06/2016 : I used mt_logic "min" to merge edgemask and lumamask, as edgemask is basically 0/255, when it's 0 it's the minimum, when it's 255 isn't the minimum, moreover with a lumamask value X = x/256 , if multiplied togheter X*0 = 0, X*(255/255) = X*1 = X
so using a lut to multiply them should give roughtly same result.