Log in

View Full Version : UnBlend for VapourSynth


KingLir
11th February 2019, 21:03
Anyone able to port unblend to VapourSynth ?
I found it quite useful at removing blends from PAL sources that just can't be removed by latest srestore.

"Unblend is based on warpenterprise's deblend algorithm and neuron2's decimate code, with YV12 support only."

http://avisynth.nl/users/warpenterprises/files/unblend_5F25_dll_2003.zip

StainlessS
11th February 2019, 23:32
Here some modded source (mod ~2010) from v0.02, after removing AvisynthPluginInit.cpp, internal.h, Utilities.h, Utilities.cpp,
(Info.h also need update to Info.h refactor by IanB ~2013, to fix wrap off frame crash, also chars above 128 dont print proper).
Also need avisynth.h version3 (v2.58) to match below mods.

Some small mods below, but mainly posting for a few comments I added, no idea what they mean.

PVideoFrame __stdcall unblend::GetFrame(int inframe, IScriptEnvironment* env)
{
int blend, useframe;
PVideoFrame src;
char buf[255];

useframe = inframe;

Findblend(useframe, &blend, env); // also changed a bit, does not call GetFrame_YV12

useframe += blend;

GETFRAME(useframe, src);

if (show == true)
{
env->MakeWritable(&src);

sprintf(buf, "unblend %s", VERSION);
DrawStr(vi,src, 0, 0, buf);
sprintf(buf, "Copyright 2003 Bach");
DrawStr(vi,src, 0, 1, buf);
sprintf(buf,"Using frm %d %c", useframe,(inframe==useframe)?' ':'!');
DrawStr(vi,src, 0, 2, buf);
sprintf(buf,"Instead of frm %d", inframe);
DrawStr(vi,src, 0, 3, buf);
sprintf(buf,"the diff threshold is %d", threshold);
DrawStr(vi,src, 0, 4, buf);
sprintf(buf,"the noise threshold is %f", dthresh);
DrawStr(vi,src, 0, 5, buf);
}

return src;
}

void __stdcall unblend::Findblend(int frame, int *bblend, IScriptEnvironment* env)

{
int f, x, y;
PVideoFrame store[5];
const unsigned char *storepY[5];
float t;
float metric02, metric13, metric24;
int metric_count02, metric_count13, metric_count24;
int count02, count13, count24;
float p0, p1, p2, p3, p4;
float percent02, percent13, percent24;

if (firsttime == true || frame == 0)
{
firsttime=false;
reference=0;
}

for (f = 0; f <= 4; f++)
{
GETFRAME(frame + f - 1, store[f]);
storepY[f] = store[f]->GetReadPtr(PLANAR_Y);
}

pitchY = store[0]->GetPitch(PLANAR_Y);
row_sizeY = store[0]->GetRowSize(PLANAR_Y);
heightY = store[0]->GetHeight(PLANAR_Y);

metric_count02=1;
metric_count13=1;
metric_count24=1;
metric02=0.0;
metric13=0.0;
metric24=0.0;
count02=0;
count13=0;
count24=0;

for ( y=0; y<vi.height-1; y=y+2)
{
for ( x=0; x<row_sizeY-1; x=x+2) {

p0 = (float)(storepY[0][x] + storepY[0][x+pitchY])/2;
p1 = (float)(storepY[1][x] + storepY[1][x+pitchY])/2;
p2 = (float)(storepY[2][x] + storepY[2][x+pitchY])/2;
p3 = (float)(storepY[3][x] + storepY[3][x+pitchY])/2;
p4 = (float)(storepY[4][x] + storepY[4][x+pitchY])/2;

t=1000;
if (fabs(p1- p3)>threshold ) {
// Calc ratio between p2delta and p3delta relative to p1
// 32 represents approx 0.125
// 128 represents 0.5
// 224 represent approx 0.87
// 32-127 means p3delta considerably bigger than p2delta, use p2
// 128 means p3delta same as p2delta, use original frame
// 128-244 means p3 considerably smaller than p2delta, use p3
t = 255 * (p2 - p1)/(p3 - p1); // tmax = +-255/1 tmin = +-1/255
if (t>32 && t<224) {
count13++;
metric_count13++;
metric13 = metric13 + t;
} else {
count13--;
}
}

// prev frame
if (fabs(p0 - p2)>threshold ) {
t = 255 * (p1 - p0)/(p2 - p0);
if (t>32 && t<224) {
count02++;
metric02 = metric02 + t; // This is not used
metric_count02++; // This is not used
} else {
count02--;
}
}
// next frame
if (fabs(p2 - p4)>threshold ) {
t = 255 * (p3 - p2)/(p4 - p2);
if (t>32 && t<224) {
count24++;
metric24 = metric24 + t; // This is not used
metric_count24++; // This is not used
} else {
count24--;
}
}
}

storepY[0] += 2 * pitchY;
storepY[1] += 2 * pitchY;
storepY[2] += 2 * pitchY;
storepY[3] += 2 * pitchY;
storepY[4] += 2 * pitchY;
}

// metric02 = metric02 / metric_count02; // This is not used
metric13 = metric13 / metric_count13; // Average of total metric13
// metric24 = metric24 / metric_count24; // This is not used

percent02 = (float)200 * count02 / (vi.height * vi.width);
percent13 = (float)200 * count13 / (vi.height * vi.width); // 200 because pairs of pixels
percent24 = (float)200 * count24 / (vi.height * vi.width);

if (percent13>dthresh && (percent02<dthresh ) && (percent24<dthresh ))
{
if (metric13<128 && metric13>32) reference=(-1);
else if(metric13>128 && metric13<224) reference=1;
}
else reference=0;

*bblend = reference;

}

Maybe of small use in remod.
EDIT: Not sure if I ever tested it.

KingLir
12th February 2019, 06:43
Here some modded source


Thanks. Is it possible to build a VapourSynth DLL from it ?

StainlessS
12th February 2019, 10:59
Dont know, I know nothing of Vapoursynth.
I could though move it to VS2008, avs+ x86 and x64, with v2.60 colorspaces.