HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Quote:
Would it be hard to modify the InPaintFunc script so it doesn't convert the whole frame to RGB?
|
I'll take a look, not promising anything.
Quote:
The weird green frames of which you speak.... are they something you've experienced in the output video? I've only ever seen them when using debug=true
|
It looks like I was wrong about DeblendLogo(), looks like weird green stuff is purely down to maybe filter ordering or something, I've added a couple of
bits to the script to set chroma=128 in a couple of mt_ calls, fixes the debug output and less worrying to look at. I might actually use this script now.
RM_logo.avs v0.6
Code:
# rm_logo() Version 0.6 -- 02.01.2016.
# v0.6, fixed weird green frames in Debug=true mode, StainlessS.
#
# Script to help in the removal of channel logos or other distracting objects
#
# Required filters:
# AVSInpaint: Ver 2008-01-06
# Discussion & Code : http://forum.doom9.org/showthread.php?t=133682
# ExInpaint: Ver 0.1+
# Code http://avisynth.org.ru/exinpaint/exinpaint.html
# mt_masktools: Ver 2.0.32+
# Code http://manao4.free.fr/masktools-v2.0a32.zip
# removegrain: Ver 1.0 (8/2005)
# Code http://www.removegrain.de.tf
# fft3dfilter: Ver 2.1.1 or later
# Code http://avisynth.org.ru/fft3dfilter/fft3dfilter.html
# ttempsmoothf Ver 0.9.4 or later
# Code http://bengal.missouri.edu/~kes25c/
# medianblur Ver 0.8.4
# Code http://www.avisynth.org/tsp/medianblur084.zip
#
function rm_logo( clip clp, string "logomask", string "loc",float "par", string "mode",int "percent",int "deblendfalloff",\
int "AlphaToRepair", float "RepairRadius", float "InpaintRadius", float "InpaintSharpness",\
float "InpaintPreBlur", float "InpaintPostBlur", string "cutsize", bool "lmask", int "pp", bool "debug", \
int "cutwidth", int "cutheight") {
logomask = default( logomask, "" ) # file location of the logo, the must be masked in pure white
loc = default( loc, "" ) # where is the logo, TR, TL, BR, BL for top right, top left, bottom right, bottom left
cutsize = default( cutsize, "small" ) # how big a cut to make, small, medium, large
cutwidth = default( cutwidth, 0 ) # how wide a cut to make in pixels, -1 for full width of frame
cutheight = default( cutheight, 0 ) # how tall a cut to make in pixels, -1 for full height of frame
par = default( par, 1.0 ) # pixel aspect ratio
mode = default( mode, "both" ) # deblend, inpaint or both
percent = default( percent, 25 ) # how much of the clip to analyse in creating color&alpha masks, more is better but slower
deblendfalloff = default( deblendfalloff, 5 ) # graidient fallout from logo mask
AlphaToRepair = default( AlphaToRepair, 130 ) # what is the luma value of the solid part of the logo
RepairRadius = default( RepairRadius, 1.0 ) # used to expand the mask for none alpha ie solid areas
InpaintRadius = default( InpaintRadius, 6.0 ) # radius around a damaged pixel from where values are taken when the pixel is inpainted. Bigger values prevent
# inpainting in the wrong direction, but also create more blur
InpaintSharpness = default( InpaintSharpness, 25.0 ) # Higher values can prevent blurring caused by high Radius values.
InpaintPreBlur = default( InpaintPreBlur, 1.5 ) # Standard deviation of the blur which is applied to the image before the structure tensor is computed. Higher values
# help connecting isophotes which have been cut by the inpainting region, but also increase CPU usage. PreBlur=0.0
# disables pre-blurring.
InpaintPostBlur = default( InpaintPostBlur, 5.0 ) # standard deviation of the blur which is applied to the structure tensors before they are used to determine the
# inpainting direction. Higher values help gather more directional information when there are only few valid pixels
# available, but increases CPU usage
lmask = default( lmask, true ) # apply post process through a repair mask
PP = default( PP, 1 ) # Post process function 0,1,2 to help reduce damage left behind by logo removal
debug = default( debug, false ) # show mask to help in tunning the output
# set up some values that we need to run
clp_width = width( clp )
clp_height = height( clp )
RGB = isRGB( clp )
RGB32 = isRGB32( clp )
RGB24 = isRGB24( clp )
par = ( par!= 1.0 ) ? float( clp_height ) / float( clp_width ) * par : 1.0
percent = ( percent < 0) ? 25 : (percent > 100) ? 100 : percent
# Get the always fun input error checking done
assert ( logomask != "" , "You have to define a logomask")
assert ( loc != "" , "You must provide a value for Loc UL,UR,LL,LR")
assert ( loc == "TR" || loc == "TL" || loc == "BR" || loc == "BL" , "Loc must be one of TR, TL, BR, BL")
assert ( mode == "both" || mode == "inpaint" || mode == "deblend", "Specified mode doesn't exist.")
# Get our crop locations based on the passed location
loc = UCase( loc )
cutsize = UCase( cutsize )
multi = ( cutsize == "SMALL" ) ? 2.25 : ( cutsize == "MEDIUM" ) ? 2.15 : 2
chunk = ( clp_height > 720 ) ? 2.9 : 3
cutwidth = ( cutwidth == 0 || cutwidth == -1 ) ? cutwidth : m4(cutwidth)
cutheight = ( cutheight == 0 || cutheight == -1 ) ? cutheight : m4(cutheight)
a = ( Rightstr( loc, 1 ) == "L" ) ? 0 : (cutwidth == 0 ) ? m4( (clp_width / chunk ) * multi ) : (cutwidth == -1 ) ? 0 : (clp_width - cutwidth)
b = ( Leftstr( loc, 1 ) == "T" ) ? 0 : (cutheight == 0 ) ? m4( (clp_height / chunk ) * multi ) : (cutheight == -1 ) ? 0 : (clp_height - cutheight)
c = ( Rightstr( loc, 1 ) == "R" ) ? 0 : (cutwidth == 0) ? -m4( (clp_width / chunk ) * multi ) : (cutwidth == -1 ) ? 0 : -(clp_width - cutwidth)
d = ( Leftstr( loc, 1 ) == "B" ) ? 0 : (cutheight == 0 ) ? -m4( (clp_height / chunk ) * multi ) : (cutheight == -1 ) ? 0 : -(clp_height - cutheight)
cropped = clp.crop(a,b,c,d)
# Anaylse the entire clip or a percentage for speed.
snipSize = round( framecount( cropped ) / (framecount( cropped ) * (percent / 100.0) ))
analyse = ( percent != 100 ) ? cropped.SelectRangeEvery( snipSize, 1 ) : cropped
# Read in our logo mask, prepare it and crop out the corner of interest
logo_mask = imagesource(logomask,start=0,end=1)
logo_mask = logo_mask.crop(a,b,c,d)
logo_mask = logo_mask.ConvertToYV12(Matrix="PC.601")
logo_mask = logo_mask.DistanceFunction(255/deblendfalloff,PixelAspect=par).Greyscale
# Clean the analyse clip to improve results
analyse = (IsYV12(analyse)) ? analyse : analyse.ConvertToYV12
analyse = analyse.TTempSmoothF(maxr=2,lthresh=256,cthresh=256,scthresh=255).converttoRGB24()
input = ( RGB24 == true ) ? cropped : cropped.converttoRGB24()
# seperate out the directory and logo names so we can save a unique ebmp file
sl = logomask.revstr().findstr("\") - 1
Assert((sl >= 0),"specify a fully qualified directory and logomask name to use")
logo_name = (sl < 0 ) ? "" : rightstr(logomask,sl) # name and extension
s2 = logo_name.findstr(".") - 1 # find the length of the extension
logo_name = leftstr(logo_name,s2) # just the name !
Analyse_Name = logo_name + loc + string(percent) + "AnalyzeResult%06d.ebmp"
# Time to run the analysis on the logo, we want the color map and alpha map out of the file.
try {
# Analyze is a bit slow so we only do it once and store the result in a file, check if it exists or if it has changed
ImageSource(Analyse_Name,0,0)
(Interleave( AssumeFPS(input.FrameRate), input.Trim(0,-2).AnalyzeLogo(logo_mask) ).FrameCount > 3) ? last : last
}
catch( dummy ) {
# Nice catch, we are here since we need to perform our logo analysis as none already exists
analyse.AnalyzeLogo(logo_mask)
# The analysis is complete, save a frame (all frames are the same)
Trim( 0, -1 )
ImageWriter( logo_name + loc + string(percent) + "AnalyzeResult", 0, 1, "ebmp" )
}
# The color map is the top half of the Analyze result, The alpha channel is in the bottom half
AssumeFPS(analyse.FrameRate)
LogoColor = Crop(0,0,0,last.Height/2)
LogoAlpha = Crop(0,last.Height/2,0,0).ConvertToYV12(Matrix="PC.601")
# Create a Deblend mask, this is a mask that falls off the marked logo area, we use this to blend the delogoed area back into the clip
DeblendMask = logo_mask.DistanceFunction( 255.0 / DeblendFalloff, PixelAspect=par )
# Create a repair mask for pixels that cannot be deblended
LogoAlpha.Invert.mt_lut(expr="x " + " " + string(alphatorepair) + " " + "< 255 0 ?").mt_expand.mt_inflate(chroma="-128") # ssS, added (chroma="-128")
RepairMask = ( RepairRadius > 0.1 ) ? DistanceFunction( 84.0 / RepairRadius, PixelAspect=par ) : last
# InpaintLogo and DeblendLogo based on user preferance
deblend = ( mode == "both" ) ? input.DeblendLogo(LogoColor,LogoAlpha) \
: ( mode == "deblend" ) ? input.DeblendLogo(logoColor,logoAlpha) : input
repaired = ( mode == "both" ) ? deblend.InpaintLogo(RepairMask, Radius=InpaintRadius, Sharpness=InpaintSharpness, \
PreBlur=InpaintPreBlur, PostBlur=InpaintPostBlur, PixelAspect=par) \
: ( mode == "inpaint" ) ? deblend.InpaintLogo(RepairMask,Radius=InpaintRadius, Sharpness=InpaintSharpness, PreBlur=InpaintPreBlur,\
PostBlur=InpaintPostBlur, PixelAspect=par) : deblend
#repaired = ExInpaint (repaired.converttorgb32, repairmask.converttorgb32, color=$ffffff,xsize=5, ysize=3, radius=36)
output = Layer(input.ConvertToRGB32, repaired.ConvertToRGB32.Mask(DeblendMask.ConvertToRGB32(Matrix="PC.601")))
output = output.converttoyv12
# post processing of the results if requested
postmask = LogoAlpha.Invert.mt_lut(expr="x " + " " + string(alphatorepair) + " " + "< 255 0 ?").mt_expand.mt_inflate(chroma="-128") # ssS, added (chroma="-128")
postmask = postmask.DistanceFunction( 64.0 / RepairRadius, PixelAspect=par )
#postmask = (pp > 0 && lmask) ? repairmask.DistanceFunction( 512.0 / DeblendFalloff, PixelAspect=par ) : blankclip(output,color=$000000)
post = ( PP == 1 ) ? output.minblur(1,uv=3).medianblur(3,0,0).removegrain(11) \
: ( pp == 2 ) ? output.fft3dfilter(sigma=16,sigma2=12,sigma3=8,sigma4=4,bt=3,bw=16,bh=16,ow=8,oh=8,plane=4) \
: ( pp == 3 ) ? output.mt_convolution("1 8 28 56 76 56 28 8 1","1 8 28 56 76 56 28 8 1",y=3,v=2,u=2) \
: output
output = ( pp > 0 ) ? mt_merge(output,post,postmask) : output
aa = debug ? stackhorizontal(logo_mask.ConvertToYV12.subtitle("logo mask"),logocolor.ConvertToYV12.subtitle("Logo Color"),logoalpha.ConvertToYV12.subtitle("Logo Alpha")) : nop
bb = debug ? stackhorizontal(deblendmask.ConvertToYV12.subtitle("Deblend Mask"),repairmask.ConvertToYV12.subtitle("Repair Mask"),postmask.ConvertToYV12.subtitle("Post Mask")) : nop
cc = debug ? stackhorizontal(cropped.ConvertToYV12.subtitle("Original"),repaired.ConvertToYV12.subtitle("Repaired"),output.ConvertToYV12.subtitle("Post")) : nop
# Almost done, lets blend in our repair
output = (RGB == true) ? (RGB24 == true) ? output : output.converttoRGB32() : output.converttoYV12()
final = clp.overlay(output,a, b)
RETURN debug ? stackvertical(aa,bb,cc) : final
}
FUNCTION MinBlur(clip input, int r, int "uv") {
# Nifty Gauss/Median combination
# Taken from MCBob.avs:
uv = default(uv,3)
# process chroma if uv==3, otherwise just luma
uv2 = (uv==2) ? 1 : uv
rg4 = (uv==3) ? 4 : -1
rg11 = (uv==3) ? 11 : -1
rg20 = (uv==3) ? 20 : -1
medf = (uv==3) ? 1 : -200
# make our blur clips, r controls amount
RG11D = (r==1) ? mt_makediff(input,input.removegrain(11, rg11),U=uv2,V=uv2)
\ : (r==2) ? mt_makediff(input,input.removegrain(11,rg11).removegrain(20,rg20),U=uv2,V=uv2)
\ : mt_makediff(input,input.removegrain(11,rg11).removegrain(20,rg20).removegrain(20,rg20),U=uv2,V=uv2)
RG4D = (r==1) ? mt_makediff(input,input.removegrain(4,rg4),U=uv2,V=uv2)
\ : (r==2) ? mt_makediff(input,input.medianblur(2,2*medf,2*medf),U=uv2,V=uv2)
\ : mt_makediff(input,input.medianblur(3,3*medf,3*medf),U=uv2,V=uv2)
DD = mt_lutxy(RG11D,RG4D,"x 128 - y 128 - * 0 < 128 x 128 - abs y 128 - abs < x y ? ?",U=uv2,V=uv2)
RETURN (input.mt_makediff(DD,U=uv,V=uv))
}
FUNCTION m4(float x) {RETURN( x<16?16:int(round(x/4.0)*4)) }
2 Mods Marked in Blue.
EDIT: If you spot any more green frames in Debug, shout out and give args and I'll take another look, there are other calls to MT_
that do not have chroma setting set.
Last edited by StainlessS; 2nd January 2017 at 20:14.
|