mg262
11th September 2005, 17:42
Here's a YV12 filter I recently built on request from one thrash_sensei... the idea and method are his:
http://people.pwf.cam.ac.uk/mg262/posts/ColourMask_11Sep05.dll
ColourMask(clip, int y, int u, int v, int lumathreshold, int chromathreshold)
returns a mask of those pixels whose colour is near (y,u,v), where nearness is defined by lumathreshold and chromathreshold. Chroma of the returned clip is nonsense.
ColourStabilise(clip, int y, int u, int v, int lumathreshold, int chromathreshold)
Replaces pixels whose colour is near (y,u,v) with colour (y,u,v), where nearness is defined by lumathreshold and chromathreshold. (Chroma subsampling is treated sensibly.)
RGBColourStabilise(clip, int colour, int lumathreshold, int chromathreshold)
Just like ColourStabilise but takes the colour as a RGB hex value. ( Rec.601 conversion ).
I think this is meant to be used on a scene by scene basis... I haven't tried this filter above and beyond making sure it was working correctly. Ask if you want the source or any technical details.
Mug Funky
12th September 2005, 04:18
hey cool! i was thinking last night of muddling something like this together using tweak and vtoy,utoy, but a plugin is always welcome :)
mg262
12th September 2005, 16:05
thrash_sensei did actually make a script to do this, but it ran at 13 FPS, which is why I made the plug-in -- which he measured at about 300 FPS (though it could probably be made faster if there were any point).
I'm not masochistic enough to go through scene by scene fixing up colours like this... actually, I did at one point try to use the fact that the foreground is typically drawn with a limited palette to separate foreground and background, but it didn't work too well... I always ended up picking up a reasonable amount of background. On the other hand the material I work with is very much noisier than what most of you seem to be playing with...
VoodooFX
11th June 2022, 17:54
ColourMask() doesn't work, always "Invalid arguments error".
EDIT:
Works if you don't add argument names: ColourMask(176, 40, 166, 60, 30)
StainlessS
11th June 2022, 18:57
Yep, none of the args are named nor optional.
extern "C" __declspec(dllexport) const char *__stdcall AvisynthPluginInit2(IScriptEnvironment *env)
{
env->AddFunction("ColourMask", "ciiiii", Create_ColourMask, 0);
env->AddFunction("ColourStabilise", "ciiiii", Create_ColourStabilise, 0);
env->AddFunction("RGBColourStabilise", "ciii", Create_RGBColourStabilise, 0);
return "ColourStabilise plugin";
}
from Here, https://forum.doom9.org/showthread.php?t=118430
EDIT: And just the source for ColourMask,
class ColourMask : public GenericVideoFilter
{
unsigned char y,u,v;
int lumathreshold, chromathreshold;
public:
ColourMask(PClip _child, unsigned char _y, unsigned char _u,unsigned char _v, int _lumathreshold, int _chromathreshold,IScriptEnvironment *env);
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment *env);
};
ColourMask::ColourMask(PClip _child, unsigned char _y, unsigned char _u,unsigned char _v, int _lumathreshold, int _chromathreshold,IScriptEnvironment *env) : GenericVideoFilter(_child) ,
y(_y),u(_u),v(_v),lumathreshold (_lumathreshold), chromathreshold(_chromathreshold)
{
}
inline bool closerthan(unsigned char a, unsigned char b, int distance)
{
int difference =int (a) -b;
return difference < distance && - difference < distance;
}
PVideoFrame __stdcall ColourMask::GetFrame(int n, IScriptEnvironment *env)
{
if (!vi.IsYV12())
env->ThrowError("ColourMask requires YV12.");
PVideoFrame source = child->GetFrame(n, env);
PVideoFrame result = env->NewVideoFrame(vi);
const int width = source->GetRowSize();
const int height = source->GetHeight();
const int sourcepitch = source->GetPitch();
const int sourcepitchU = source->GetPitch(PLANAR_U);
const int sourcepitchV = source->GetPitch(PLANAR_V);
const int resultpitch = result->GetPitch();
const unsigned char *sourcerow = source->GetReadPtr();
const unsigned char *sourcerowU = source->GetWritePtr(PLANAR_U);
const unsigned char *sourcerowV = source->GetWritePtr(PLANAR_V);
unsigned char *resultrow = result->GetWritePtr();
for(int yy = 0; yy < height; yy+=2)
{
for(int x = 0; x < width; ++x)//yy
{
int halfx = x/2;
if (closerthan(sourcerow[x],y, lumathreshold)/**/ &&
closerthan(sourcerowU[halfx],u, chromathreshold) &&
closerthan(sourcerowV[halfx],v, chromathreshold))
resultrow[x]= 255;
else
resultrow[x]= 0;
}
sourcerow += sourcepitch;
resultrow += resultpitch;
for(int x = 0; x < width; ++x)//yy+1
{
int halfx = x/2;
if (closerthan(sourcerow[x],y, lumathreshold) /**/&&
closerthan(sourcerowU[halfx],u, chromathreshold) &&
closerthan(sourcerowV[halfx],v, chromathreshold))
resultrow[x]= 255;
else
resultrow[x]= 0;
}
sourcerow += sourcepitch;
sourcerowU += sourcepitchU;
sourcerowV += sourcepitchV;
resultrow += resultpitch;
}
return result;
}
AVSValue __cdecl Create_ColourMask(AVSValue args, void *user_data, IScriptEnvironment *env)
{
return new ColourMask(args[0].AsClip(), args[1].AsInt(), args[2].AsInt(), args[3].AsInt(), args[4].AsInt(), args[5].AsInt(), env);
}
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.