HighInBC
10th July 2005, 18:51
I have made an avisynth function that allows masks to be automatically generated using a master frame and RGB threshholds.
This allows you to replace your 'blue screen' with any stationary high contract background. It also allows for effects that cannot be done with a bluescreen(see the demo below for a nice color effect).
Here is the function itself:
function diff_mask(clip clip, clip mask, clip master, int r_thresh, int g_thresh, int b_thresh, bool invert)
{
# LoadPlugin("C:/DVD Tools/AviSynth 2.5/plugins/MaskTools.dll")
clip = clip.ConvertToRGB24()
master = master.Loop(FrameCount(clip)).ConvertToRGB24()
r_bin = (r_thresh >= 0) ? get_red(clip,master,r_thresh,invert) : BlankClip(clip,length=FrameCount(clip), pixel_type="YV12")
g_bin = (g_thresh >= 0) ? get_green(clip,master,g_thresh,invert) : BlankClip(clip,length=FrameCount(clip), pixel_type="YV12")
b_bin = (b_thresh >= 0) ? get_blue(clip,master,b_thresh,invert) : BlankClip(clip,length=FrameCount(clip), pixel_type="YV12")
combined = r_bin.Logic(g_bin,mode="or").Logic(b_bin,mode="or").Greyscale().ConvertToRGB32.Mask(mask.ConvertToRGB32())
final = Layer(Blankclip(clip, pixel_type="RGB32"),combined)
return final
function get_red(clip clip, clip master, int r_thresh, bool invert)
{
r = clip.RGBAdjust(1,0,0,1).ConvertToYV12()
r_mast = master.RGBAdjust(1,0,0,1).ConvertToYV12()
r_sub = YV12Subtract(r, r_mast, tol = 0, widerange = false, y=3, u=3, v=3)
return ((invert) ? (r_sub.Binarize(threshold=r_thresh).Invert()) : (r_sub.Binarize(threshold=r_thresh)))
}
function get_green(clip clip, clip master, int g_thresh, bool invert)
{
g = clip.RGBAdjust(0,1,0,1).ConvertToYV12()
g_mast = master.RGBAdjust(0,1,0,1).ConvertToYV12()
g_sub = YV12Subtract(g, g_mast, tol = 0, widerange = false, y=3, u=3, v=3)
return ((invert) ? (g_sub.Binarize(threshold=g_thresh).Invert()) : (g_sub.Binarize(threshold=g_thresh)))
}
function get_blue(clip clip, clip master, int b_thresh, bool invert)
{
b = clip.RGBAdjust(0,0,1,1).ConvertToYV12()
b_mast = master.RGBAdjust(0,0,1,1).ConvertToYV12()
b_sub = YV12Subtract(b, b_mast, tol = 0, widerange = false, y=3, u=3, v=3)
return ((invert) ? (b_sub.Binarize(threshold=b_thresh).Invert()) : (b_sub.Binarize(threshold=b_thresh)))
}
}
Please note this requires MaskTools.dll, here is a link to the version I am using, it may not be the latest version but it is the one that works with this routine: http://adserton.crackerjack.net/~rambler/MaskTools.dll
This routine expects all of the following paramaters:
clip:
This is of course the clip you wish to genereate the mask for.
mask:
This is a basic static mask to limit the effect to a specific area, unfourtunatly effecting a smaller area will not increase the speed of the function.
master:
This should be a single frame, the routine will compare each frame of the clip to the master frame, then use the RGB thresholds to decide if it is 'different' enought to mask any particular pixel. You should choose a frame that has only the static background in the effected area.
r,g,b:
These values decide at what point a pixel is masked, if the number is negetive then that channel will be ignored. You will want to work on one color at a time, keeping the other 2 negative, start with a low number, then a high number, and keep going in between till you get the best results. You want a mask that has as much white as possible, but not showing white in areas that should be black. The masks from R,G, and B are all OR'd together. Remeber to make the numbers positive again once you have all three set. In some cases it may be better to not use one or two of the channels.
invert:
This is used to reverse the mask, depending on the situation you will want the to be true or false, usually true
This is a little tricky to grasp so I am including a 10mb demo.
http://adserton.crackerjack.net/~rambler/Diff%20Mask%20Demo.rar
This allows you to replace your 'blue screen' with any stationary high contract background. It also allows for effects that cannot be done with a bluescreen(see the demo below for a nice color effect).
Here is the function itself:
function diff_mask(clip clip, clip mask, clip master, int r_thresh, int g_thresh, int b_thresh, bool invert)
{
# LoadPlugin("C:/DVD Tools/AviSynth 2.5/plugins/MaskTools.dll")
clip = clip.ConvertToRGB24()
master = master.Loop(FrameCount(clip)).ConvertToRGB24()
r_bin = (r_thresh >= 0) ? get_red(clip,master,r_thresh,invert) : BlankClip(clip,length=FrameCount(clip), pixel_type="YV12")
g_bin = (g_thresh >= 0) ? get_green(clip,master,g_thresh,invert) : BlankClip(clip,length=FrameCount(clip), pixel_type="YV12")
b_bin = (b_thresh >= 0) ? get_blue(clip,master,b_thresh,invert) : BlankClip(clip,length=FrameCount(clip), pixel_type="YV12")
combined = r_bin.Logic(g_bin,mode="or").Logic(b_bin,mode="or").Greyscale().ConvertToRGB32.Mask(mask.ConvertToRGB32())
final = Layer(Blankclip(clip, pixel_type="RGB32"),combined)
return final
function get_red(clip clip, clip master, int r_thresh, bool invert)
{
r = clip.RGBAdjust(1,0,0,1).ConvertToYV12()
r_mast = master.RGBAdjust(1,0,0,1).ConvertToYV12()
r_sub = YV12Subtract(r, r_mast, tol = 0, widerange = false, y=3, u=3, v=3)
return ((invert) ? (r_sub.Binarize(threshold=r_thresh).Invert()) : (r_sub.Binarize(threshold=r_thresh)))
}
function get_green(clip clip, clip master, int g_thresh, bool invert)
{
g = clip.RGBAdjust(0,1,0,1).ConvertToYV12()
g_mast = master.RGBAdjust(0,1,0,1).ConvertToYV12()
g_sub = YV12Subtract(g, g_mast, tol = 0, widerange = false, y=3, u=3, v=3)
return ((invert) ? (g_sub.Binarize(threshold=g_thresh).Invert()) : (g_sub.Binarize(threshold=g_thresh)))
}
function get_blue(clip clip, clip master, int b_thresh, bool invert)
{
b = clip.RGBAdjust(0,0,1,1).ConvertToYV12()
b_mast = master.RGBAdjust(0,0,1,1).ConvertToYV12()
b_sub = YV12Subtract(b, b_mast, tol = 0, widerange = false, y=3, u=3, v=3)
return ((invert) ? (b_sub.Binarize(threshold=b_thresh).Invert()) : (b_sub.Binarize(threshold=b_thresh)))
}
}
Please note this requires MaskTools.dll, here is a link to the version I am using, it may not be the latest version but it is the one that works with this routine: http://adserton.crackerjack.net/~rambler/MaskTools.dll
This routine expects all of the following paramaters:
clip:
This is of course the clip you wish to genereate the mask for.
mask:
This is a basic static mask to limit the effect to a specific area, unfourtunatly effecting a smaller area will not increase the speed of the function.
master:
This should be a single frame, the routine will compare each frame of the clip to the master frame, then use the RGB thresholds to decide if it is 'different' enought to mask any particular pixel. You should choose a frame that has only the static background in the effected area.
r,g,b:
These values decide at what point a pixel is masked, if the number is negetive then that channel will be ignored. You will want to work on one color at a time, keeping the other 2 negative, start with a low number, then a high number, and keep going in between till you get the best results. You want a mask that has as much white as possible, but not showing white in areas that should be black. The masks from R,G, and B are all OR'd together. Remeber to make the numbers positive again once you have all three set. In some cases it may be better to not use one or two of the channels.
invert:
This is used to reverse the mask, depending on the situation you will want the to be true or false, usually true
This is a little tricky to grasp so I am including a 10mb demo.
http://adserton.crackerjack.net/~rambler/Diff%20Mask%20Demo.rar