Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
|
|
Thread Tools | Search this Thread | Display Modes |
21st November 2013, 11:27 | #221 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Another way of looking at it is that
Code:
Defined(slices) && slices Quote:
It seems to me that when slices is false there is some double counting going on. As StainlessS said: This means that, not only are you duplicating work unnecessarily, but also, because all pixels are not treated equally, you are skewing the results. |
|
21st November 2013, 18:56 | #222 | Link | |
Registered User
Join Date: Apr 2008
Location: California, USA
Posts: 127
|
The code seems right
Quote:
Code:
---- ---- ---- ---- ---- ---- --x- ---- -xx- --xx --x- --x- ---- ---- ---- --x- ---- ---- ---- ---- Last edited by Forensic; 21st November 2013 at 18:58. |
|
21st November 2013, 19:59 | #223 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
I don't think that's true.
In your example, each of the four pairs is processed twice. For example pixels (3,3) and (3,4) are compared first when x=2 and y=3, then again when x=3 and y=3. Similarly, (3,3) and (4,3) are compared first when x=3 and y=2, then again when x=3 and y=3. If all relevant pairs were compared twice, it would be unnecesary work, but would not affect the result. However, some pairs are compared only once, eg (1,1) and (2,1), or (3,1) and (3,2) - any pair where at least one pixel is on the edge of the processed region. I think for each (x,y) the algorithm needs to compare that pixel with only at most two other pixels: (x,y+1) and (x+1,y), omitting a comparison when the other pixel is outside the region to be processed. |
21st November 2013, 22:41 | #224 | Link |
Registered User
Join Date: Apr 2008
Location: California, USA
Posts: 127
|
Darn!!!! Gavino is correct. The problem is fixed by having either X or Y increment by two when slices is false. Good catch Gavino. Thank you.
Code:
Function AvgLumaDif_MOD(Clip c, bool "slices", int "n") { # Suggested implementation, same result as modified logic above c step = (Defined(slices) && slices) ? 4 : 1 xstep = (step==4) ? 4 : 2 n = Default(n,0) # default current_frame = 0 W = (Width / 4) * 4 # Ignore RHS odds and ends, FULL 4x4 pixel blocks only H = (Height / 4) * 4 # Assert(W>0 && H>0,"AvgLumaDif_MOD: Illegal Frame Size") value=0.0 GScript(""" for (y=1,H-3,step) { for (x=1,W-3,xstep) { value=value \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x+1, y2=y, w=1, h=1) \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x, y2=y+1, w=1, h=1) \ + RT_YDifference(c,n,delta=0, x=x+1, y=y, x2=x+1, y2=y+1, w=1, h=1) \ + RT_YDifference(c,n,delta=0, x=x, y=y+1, x2=x+1, y2=y+1, w=1, h=1) } } count = (step==1) ? ((W-3) * (H-3) *2) : (W * H /4) value = value / count """) return value } Last edited by Forensic; 21st November 2013 at 23:28. Reason: Also have to fix the count |
22nd November 2013, 00:40 | #225 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
Some pairs are still compared twice (eg (1,2) and (2,2)), while others are not compared at all (eg (2,2) and (3,2)). As I suggested, the algorithm when step=1 needs to be: Code:
for (y=1,H-3) { for (x=1,W-3) { value=value \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x+1, y2=y, w=1, h=1) \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x, y2=y+1, w=1, h=1) } } for (y=1,H-3) { # do last column value=value + RT_YDifference(c,n,delta=0, x=W-2, y=y, x2=W-2, y2=y+1, w=1, h=1) } for (x=1,W-3) { # do last row value=value + RT_YDifference(c,n,delta=0, x=x, y=H-2, x2=x+1, y2=H-2, w=1, h=1) } |
|
22nd November 2013, 00:51 | #226 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Damn, have already implemented as previous script, he tis (I shall make the mods later)
Code:
Function AvgLumaDif_1(Clip c, bool "slices", int "n",int "Matrix") { # Equivalent to Original c step= (Defined(slices) && slices) ? 4 : 1 n = Default(n,0) # default current_frame = 0 Matrix = Default(Matrix, Height < 600 ? 2 : 3) # REC601 : 1=REC709 : 2 = PC601 : 3 = PC709 value=0.0 count=0.0 GScript(""" for (y=1,Height-step,step) { for (x=1,Width-step,step) { Try { value=value \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x+1, y2=y, w=1, h=1,matrix=Matrix) \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x, y2=y+1, w=1, h=1,matrix=Matrix) \ + RT_YDifference(c,n,delta=0, x=x+1, y=y, x2=x+1, y2=y+1, w=1, h=1,matrix=Matrix) \ + RT_YDifference(c,n,delta=0, x=x, y=y+1, x2=x+1, y2=y+1, w=1, h=1,matrix=Matrix) count=count+1 } Catch (err) {} } } if (count>0) {value=value/(4*count)} """) return value } Function AvgLumaDif_2(Clip c, bool "slices", int "n",int "Matrix") { # Same logic, Modifed to remove nonsense eg width-step for limit c step= (Defined(slices) && slices) ? 4 : 1 n = Default(n,0) # default current_frame = 0 Matrix = Default(Matrix, Height < 600 ? 2 : 3) # REC601 : 1=REC709 : 2 = PC601 : 3 = PC709 W = (Width / 4) * 4 # Ignore RHS odds and ends, FULL 4x4 pixel blocks only H = (Height / 4) * 4 # value=0.0 count=0.0 GScript(""" for (y=1,H-3,step) { for (x=1,W-3,step) { Try { value=value \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x+1, y2=y, w=1, h=1,matrix=Matrix) \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x, y2=y+1, w=1, h=1,matrix=Matrix) \ + RT_YDifference(c,n,delta=0, x=x+1, y=y, x2=x+1, y2=y+1, w=1, h=1,matrix=Matrix) \ + RT_YDifference(c,n,delta=0, x=x, y=y+1, x2=x+1, y2=y+1, w=1, h=1,matrix=Matrix) count=count+1 } Catch (err) {} } } if (count>0) {value=value/(4*count)} """) return value } Function AvgLumaDif_MOD(Clip c, bool "slices", int "n",int "Matrix") { # Suggested implementation, same result as modified logic above c step = (Defined(slices) && slices) ? 4 : 1 n = Default(n,0) # default current_frame = 0 Matrix = Default(Matrix, Height < 600 ? 2 : 3) # REC601 : 1=REC709 : 2 = PC601 : 3 = PC709 W = (Width / 4) * 4 # Ignore RHS odds and ends, FULL 4x4 pixel blocks only H = (Height / 4) * 4 # Assert(W>0 && H>0,"AvgLumaDif_MOD: Illegal Frame Size") value=0.0 GScript(""" for (y=1,H-3,step) { for (x=1,W-3,step) { value=value \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x+1, y2=y, w=1, h=1,matrix=Matrix) \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x, y2=y+1, w=1, h=1,matrix=Matrix) \ + RT_YDifference(c,n,delta=0, x=x+1, y=y, x2=x+1, y2=y+1, w=1, h=1,matrix=Matrix) \ + RT_YDifference(c,n,delta=0, x=x, y=y+1, x2=x+1, y2=y+1, w=1, h=1,matrix=Matrix) } } count = (step==1) ? ((W-3) * (H-3)) : (W/4 * H/4) value = value / (4*count) """) return value } W=512 H=64 T=False Avisource("D:\avs\test.avi").ConvertToYV12().BilinearResize(W,H) A=AvgLumaDif_1(T) B=AvgLumaDif_2(T) C=AvgLumaDif_MOD(T) D=AvgLumaDif(T,n=0) # dll defaults to current_frame rather than 0, can change in source. RT_DebugF ("%f %f %f %f",A,B,C,D) RT_SubTitle("%f %f %f %f",A,B,C,D) return last Code:
/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <windows.h> #include <stdio.h> // dprintf #include "Avisynth.h" #define DEFAULT_CURRENT_FRAME // comment out to default n to 0 //#define BUGPRINT // uncomment to print something to debugview #ifdef BUGPRINT // Perhaps useful for debug purposes int dprintf(char* fmt, ...) { char printString[2048]; char *p=printString; va_list argp; va_start(argp, fmt); vsprintf(p, fmt, argp); va_end(argp); for(;*p++;); --p; // @ null term if(printString == p || p[-1] != '\n') { p[0]='\n'; // append n/l if not there already p[1]='\0'; OutputDebugString(printString); } else { OutputDebugString(printString); } return p-printString; // strlen printString } #endif #ifdef DEFAULT_CURRENT_FRAME // helper function AVSValue GetVar(IScriptEnvironment* env, const char* name) { try {return env->GetVar(name);} catch (IScriptEnvironment::NotFound) {} return AVSValue(); } #endif // AvgLumaDif function AVSValue __cdecl AvgLumaDif(AVSValue args, void* user_data, IScriptEnvironment* env) { const char *myName="AvgLumaDif: "; // In case of error, we have pointer to our own name handy // args is an array of type AVSValue (variant) holding calling args // Below not necessary as clip is compulsory arg (ie avisynth already made sure clip was supplied) // if(!args[0].IsClip()) env->ThrowError("%sMust have a source clip",myName); PClip child = args[0].AsClip(); // Clip, compulsory arg, no default const bool slices = args[1].AsBool(false); // slices, default false int n; // Allows selection of default for n,current_frame or 0 #ifdef DEFAULT_CURRENT_FRAME if(args[2].IsInt()) {n = args[2].AsInt(); } // Frame n else { AVSValue cn = GetVar(env,"current_frame"); if (!cn.IsInt()) env->ThrowError("%s'current_frame' only available in runtime scripts",myName); n = cn.AsInt(); // current_frame } #else n = args[2].AsInt(0); // n, default 0 #endif // Get reference to VideoInfo const VideoInfo &vi = child->GetVideoInfo(); const int matrix = args[3].AsInt(vi.height<600?2:3); // matrix, default PC range, 601/709 dependent upon height // Matrix: REC601 : 1=REC709 : 2 = PC601 : 3 = PC709 #ifdef BUGPRINT // Output something interesting when debugging dprintf("%s slices=%s n=%d matrix=%d",myName,slices?"True":"False",n,matrix); #endif // width=0 means no video, most plugins dont bother with below check (I dont either usually, but probably should) if(vi.num_frames <= 0 || vi.width==0) env->ThrowError("%sClip must have video",myName); n = (n < 0) ? 0 : (n >= vi.num_frames) ? vi.num_frames - 1 : n; // range limit n to valid frames const int step = (slices) ? 4 : 1; // Ignore RHS odds and ends, FULL 4x4 pixel blocks only const int W = vi.width & (~0x03); // clear bits 0 and 1, ie make mod 4 const int H = vi.height & (~0x03); if(W<=0 || H <=0) env->ThrowError("%sIllegal Frame Size (at least 4x4)",myName); PVideoFrame src = child->GetFrame(n,env); // pointer to video frame const int pitch = src->GetPitch(PLANAR_Y); // PLANAR_Y no effect on non-Planar (equates to 0) const BYTE *srcp = src->GetReadPtr(PLANAR_Y); const int ystride = pitch*step; // how much to step data pointer for each y iteration int dif = 0; // init, dif sum as int (not double) const int x_end=W-3, y_end=H-3; // end limits int x,y; if(vi.IsPlanar()) { srcp += pitch; // y=1 for(y=1; y <= y_end; y += step) { for(x=1; x <= x_end; x += step) { // x step appropriate for slices const int a=srcp[x]; // x , y const int b=srcp[x+1]; // x+1, y const int c=srcp[x+pitch]; // x , y+1 const int d=srcp[x+1+pitch]; // x+1, y+1 dif += abs(a-b); // x,y <-> x+1,y dif += abs(a-c); // x,y <-> x,y+1 dif += abs(b-d); // x+1,y <-> x+1,y+1 dif += abs(c-d); // x,y+1 <-> x+1,y+1 } srcp += ystride; // y step appropriate for slices } } else if(vi.IsYUY2()) { srcp += pitch; // y=1 const int xstride = step * 2; // double up for YUY2 stepping (*2) const int x_lim = x_end * 2; // luma samples 2 apart for YUY2 for(y=1; y <= y_end; y += step) { for(x=2; x <= x_lim; x += xstride) { // x=2 is offset to YUY2(1).Y const int a=srcp[x]; // x , y const int b=srcp[x+2]; // x+1, y const int c=srcp[x+pitch]; // x , y+1 const int d=srcp[x+2+pitch]; // x+1, y+1 dif += abs(a-b); // x,y <-> x+1,y dif += abs(a-c); // x,y <-> x,y+1 dif += abs(b-d); // x+1,y <-> x+1,y+1 dif += abs(c-d); // x,y+1 <-> x+1,y+1 } srcp += ystride; // y step appropriate for slices } } else if(vi.IsRGB()) { // only bother to check matrix if RGB if(matrix < 0 || matrix > 3) env->ThrowError("%sIllegal Matrix %d (0->3)",myName,matrix); // RGB to YUV-Y Conversion // Matrix: REC601 : 1=REC709 : 2 = PC601 : 3 = PC709 double Kr,Kb; int Sy,offset_y; if(matrix & 0x01) {Kr = 0.2126; Kb = 0.0722;} // 709 1 or 3 else {Kr = 0.2990; Kb = 0.1140;} // 601 0 or 2 if(matrix & 0x02) {Sy = 255 ; offset_y = 0;} // PC 2 or 3 else {Sy = 219 ; offset_y = 16;} // TV 0 or 1 const int shift = 15; const int half = 1 << (shift - 1); const double mulfac = double(1<<shift); double Kg = 1.0 - Kr - Kb; const int Srgb = 255; const int Yb = int(Sy * Kb * mulfac / Srgb + 0.5); //B const int Yg = int(Sy * Kg * mulfac / Srgb + 0.5); //G const int Yr = int(Sy * Kr * mulfac / Srgb + 0.5); //R const int OffyPlusHalf = (offset_y<<shift) + half; // // RGB is weird upside down frame srcp += ((vi.height-1) * pitch); // Upside down RGB, height-1 is top line (y=0) srcp -= pitch; // y=1, (could of course be combined with above, NOTE subtract) const int xstep = (vi.IsRGB24()) ? 3 : 4; const int xstride = step * xstep; // scale step for RGB24/32 const int x_lim = x_end * xstep; // scale x_end for RGB24/32 for(y=1; y <= y_end; y += step) { for(x=xstep; x <= x_lim;x += xstride) { // x stride appropriate for slices int a = (srcp[x] * Yb + srcp[x+1] * Yg + srcp[x+2] * Yr + OffyPlusHalf) >> shift; // x ,y int x2= x + xstep; int b = (srcp[x2] * Yb + srcp[x2+1] * Yg + srcp[x2+2] * Yr + OffyPlusHalf) >> shift; // x+1, y x2= x - pitch; // NOTE - pitch int c = (srcp[x2] * Yb + srcp[x2+1] * Yg + srcp[x2+2] * Yr + OffyPlusHalf) >> shift; // x ,y+1 x2= x + xstep - pitch; // NOTE - pitch int d = (srcp[x2] * Yb + srcp[x2+1] * Yg + srcp[x2+2] * Yr + OffyPlusHalf) >> shift; // x+1,y+1 dif += abs(a - b); // x,y <-> x+1,y dif += abs(a - c); // x,y <-> x,y+1 dif += abs(b - d); // x+1,y <-> x+1,y+1 dif += abs(c - d); // x,y+1 <-> x+1,y+1 } srcp -= ystride; // y step appropriate for slices, NOTE subtract } } else { env->ThrowError("%sUnknown Colorspace",myName); } int count = (!slices) ? ((W-3) * (H-3)) : (W/4 * H/4); double value = double(dif) / (4*count); // (4 * count) will be coerced to double during division AVSValue ret = value; // create type variant AVSValue and init with double (converted to float for AVSValue) return ret; // return value; // This would also work, value is implicitly converted to type AVSValue } // Avisynth v2.5 plugin initializer, requires AVISYNTH_INTERFACE_VERSION 3 Avisynth.h extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) { // Tell Aviynth name and args and which function to call env->AddFunction("AvgLumaDif", "c[slices]b[n]i[matrix]i", AvgLumaDif, 0); return "`AvgLumaDif' AvgLumaDif plugin"; // A freeform name of the plugin. } Defaulted n to current_frame, changeable in source. About 50FPS on UT_Video (EDIT: YV12) Compressed AVI DVD Size EDIT: Above 50FPS in error, should have been higher.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 22nd November 2013 at 06:40. |
22nd November 2013, 02:01 | #227 | Link |
Registered User
Join Date: Apr 2008
Location: California, USA
Posts: 127
|
Gavino: I created a mess by trying to handle both states of "slices" in the same loop (sorry StainlessS). From how I read your version:
If slices is TRUE then your method only gets half of four possible central pixel pairs per 4x4 pixel block, and the last two loops (last row & last column) cross through all the slice boundaries. If slices is FALSE then did you mean -2 and not -3 for the last two loops? I think that this version solves everything. Code:
Function AvgLumaDif_MOD(Clip c, bool "slices", int "n") { # Suggested implementation, same result as modified logic above c n = Default(n,0) # default current_frame = 0 W = (Width / 4) * 4 # Ignore RHS odds and ends, FULL 4x4 pixel blocks only H = (Height / 4) * 4 # Assert(W>0 && H>0,"AvgLumaDif_MOD: Illegal Frame Size") value=0.0 GScript(""" if (Defined(slices) && slices) { for (y=1,H-3,4) { for (x=1,W-3,4) { value=value \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x+1, y2=y, w=1, h=1) \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x, y2=y+1, w=1, h=1) \ + RT_YDifference(c,n,delta=0, x=x+1, y=y, x2=x+1, y2=y+1, w=1, h=1) \ + RT_YDifference(c,n,delta=0, x=x, y=y+1, x2=x+1, y2=y+1, w=1, h=1) } } count = W * H /4 } else { for (y=1,H-2,1) { for (x=1,W-2,1) { value=value \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x+1, y2=y, w=1, h=1) \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x, y2=y+1, w=1, h=1) } } value = value // now deal with the bottom right non-perimeter pixel \ + RT_YDifference(c,n,delta=0, x=W-1, y=H-1, x2=W-1, y2=H-2, w=1, h=1) \ + RT_YDifference(c,n,delta=0, x=W-1, y=H-1, x2=W-2, y2=H-1, w=1, h=1) count = (W-2) * (H-2) *2 } value = value / count """) return value } Last edited by Forensic; 22nd November 2013 at 07:40. |
22nd November 2013, 06:43 | #228 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Post #1 of 2
Forensic, think big G is correct, have implemented so. Code:
/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <windows.h> #include <stdio.h> // dprintf #include "Avisynth.h" #define DEFAULT_CURRENT_FRAME // comment out to default n to 0 //#define BUGPRINT // uncomment to print something to debugview #ifdef BUGPRINT // Perhaps useful for debug purposes int dprintf(char* fmt, ...) { char printString[2048]; char *p=printString; va_list argp; va_start(argp, fmt); vsprintf(p, fmt, argp); va_end(argp); for(;*p++;); --p; // @ null term if(printString == p || p[-1] != '\n') { p[0]='\n'; // append n/l if not there already p[1]='\0'; OutputDebugString(printString); } else { OutputDebugString(printString); } return p-printString; // strlen printString } #endif #ifdef DEFAULT_CURRENT_FRAME // helper function AVSValue GetVar(IScriptEnvironment* env, const char* name) { try {return env->GetVar(name);} catch (IScriptEnvironment::NotFound) {} return AVSValue(); } #endif // AvgLumaDif function AVSValue __cdecl AvgLumaDif(AVSValue args, void* user_data, IScriptEnvironment* env) { const char *myName="AvgLumaDif: "; // In case of error, we have pointer to our own name handy // args is an array of type AVSValue (variant) holding calling args // Below not necessary as clip is compulsory arg (ie avisynth already made sure clip was supplied) // if(!args[0].IsClip()) env->ThrowError("%sMust have a source clip",myName); PClip child = args[0].AsClip(); // Clip, compulsory arg, no default const bool slices = args[1].AsBool(false); // slices, default false int n; // Allows selection of default for n,current_frame or 0 #ifdef DEFAULT_CURRENT_FRAME if(args[2].IsInt()) {n = args[2].AsInt(); } // Frame n else { AVSValue cn = GetVar(env,"current_frame"); if (!cn.IsInt()) env->ThrowError("%s'current_frame' only available in runtime scripts",myName); n = cn.AsInt(); // current_frame } #else n = args[2].AsInt(0); // n, default 0 #endif // Get reference to VideoInfo const VideoInfo &vi = child->GetVideoInfo(); const int matrix = args[3].AsInt(vi.height<600?2:3); // matrix, default PC range, 601/709 dependent upon height // Matrix: REC601 : 1=REC709 : 2 = PC601 : 3 = PC709 #ifdef BUGPRINT // Output something interesting when debugging dprintf("%s slices=%s n=%d matrix=%d",myName,slices?"True":"False",n,matrix); #endif // width=0 means no video, most plugins dont bother with below check (I dont either usually, but probably should) if(vi.num_frames <= 0 || vi.width==0) env->ThrowError("%sClip must have video",myName); n = (n < 0) ? 0 : (n >= vi.num_frames) ? vi.num_frames - 1 : n; // range limit n to valid frames const int step = (slices) ? 4 : 1; // Ignore RHS odds and ends, FULL 4x4 pixel blocks only const int W = vi.width & (~0x03); // clear bits 0 and 1, ie make mod 4 const int H = vi.height & (~0x03); if(W<=0 || H <=0) env->ThrowError("%sIllegal Frame Size (at least 4x4)",myName); PVideoFrame src = child->GetFrame(n,env); // pointer to video frame const int pitch = src->GetPitch(PLANAR_Y); // PLANAR_Y no effect on non-Planar (equates to 0) const BYTE *srcp = src->GetReadPtr(PLANAR_Y); const int ystride = pitch*step; // how much to step data pointer for each y iteration int dif = 0; // init, dif sum as int (not double) const int x_end=W-3, y_end=H-3; // end limits int x,y; if(vi.IsPlanar()) { srcp += pitch; // y=1 if(slices) { for(y=1; y <= y_end; y += 4) { for(x=1; x <= x_end; x += 4) { // x step appropriate for slices const int tl=srcp[x]; // x , y const int tr=srcp[x+1]; // x+1, y const int bl=srcp[x+pitch]; // x , y+1 const int br=srcp[x+1+pitch]; // x+1, y+1 dif += abs(tl-tr); // x,y <-> x+1,y dif += abs(tl-bl); // x,y <-> x,y+1 dif += abs(tr-br); // x+1,y <-> x+1,y+1 dif += abs(bl-br); // x,y+1 <-> x+1,y+1 } srcp += ystride; // y step appropriate for slices } } else { for(y=1; y <= y_end; ++y) { for(x=1; x <= x_end; ++x) { // x step appropriate for slices const int tl=srcp[x]; // x , y const int tr=srcp[x+1]; // x+1, y const int bl=srcp[x+pitch]; // x , y+1 dif += abs(tl-tr); // x,y <-> x+1,y dif += abs(tl-bl); // x,y <-> x,y+1 } // rhs column, x = W - 2 const int tl=srcp[x]; // x = W - 2, y const int bl=srcp[x+pitch]; // x = W - 2, y+1 dif += abs(tl-bl); srcp += ystride; // y step appropriate for slices } // y = H - 2 for(x=1; x <= x_end; ++x) { // bottom row const int tl=srcp[x]; // x , y = H - 2 const int tr=srcp[x+1]; // x+1, y = H - 2 dif += abs(tl-tr); } } } else if(vi.IsYUY2()) { srcp += pitch; // y=1 const int x_lim = x_end * 2; // luma samples 2 apart for YUY2 if(slices) { for(y=1; y <= y_end; y += 4) { for(x=2; x <= x_lim; x += (4*2)) { // x=2 is offset to YUY2(1).Y const int tl=srcp[x]; // x , y const int tr=srcp[x+2]; // x+1, y const int bl=srcp[x+pitch]; // x , y+1 const int br=srcp[x+2+pitch]; // x+1, y+1 dif += abs(tl-tr); // x,y <-> x+1,y dif += abs(tl-bl); // x,y <-> x,y+1 dif += abs(tr-br); // x+1,y <-> x+1,y+1 dif += abs(bl-br); // x,y+1 <-> x+1,y+1 } srcp += ystride; // y step appropriate for slices } } else { for(y=1; y <= y_end; ++y) { for(x=2; x <= x_lim; x += 2 ) { // x=2 is offset to YUY2(1).Y const int tl=srcp[x]; // x , y const int tr=srcp[x+2]; // x+1, y const int bl=srcp[x+pitch]; // x , y+1 dif += abs(tl-tr); // x,y <-> x+1,y dif += abs(tl-bl); // x,y <-> x,y+1 } // rhs column, x = W - 2 const int tl=srcp[x]; // x = W - 2, y const int bl=srcp[x+pitch]; // x = W - 2, y+1 dif += abs(tl-bl); srcp += ystride; // y step appropriate for slices } // y = H - 2 for(x=2; x <= x_lim; x+=2) { // bottom row const int tl=srcp[x]; // x , y = H - 2 const int tr=srcp[x+2]; // x+1, y = H - 2 dif += abs(tl-tr); } } } else if(vi.IsRGB()) { // only bother to check matrix if RGB if(matrix < 0 || matrix > 3) env->ThrowError("%sIllegal Matrix %d (0->3)",myName,matrix); // RGB to YUV-Y Conversion // Matrix: REC601 : 1=REC709 : 2 = PC601 : 3 = PC709 double Kr,Kb; int Sy,offset_y; if(matrix & 0x01) {Kr = 0.2126; Kb = 0.0722;} // 709 1 or 3 else {Kr = 0.2990; Kb = 0.1140;} // 601 0 or 2 if(matrix & 0x02) {Sy = 255 ; offset_y = 0;} // PC 2 or 3 else {Sy = 219 ; offset_y = 16;} // TV 0 or 1 const int shift = 15; const int half = 1 << (shift - 1); const double mulfac = double(1<<shift); double Kg = 1.0 - Kr - Kb; const int Srgb = 255; const int Yb = int(Sy * Kb * mulfac / Srgb + 0.5); //B const int Yg = int(Sy * Kg * mulfac / Srgb + 0.5); //G const int Yr = int(Sy * Kr * mulfac / Srgb + 0.5); //R const int OffyPlusHalf = (offset_y<<shift) + half; // // RGB is weird upside down frame srcp += ((vi.height-1) * pitch); // Upside down RGB, height-1 is top line (y=0) srcp -= pitch; // y=1, (could of course be combined with above, NOTE subtract) const int xstep = (vi.IsRGB24()) ? 3 : 4; const int xstride = step * xstep; // scale step for RGB24/32 const int x_lim = x_end * xstep; // scale x_end for RGB24/32 if(slices) { for(y=1; y <= y_end; y += step) { for(x=xstep; x <= x_lim;x += xstride) { // x stride appropriate for slices int tl = (srcp[x] * Yb + srcp[x+1] * Yg + srcp[x+2] * Yr + OffyPlusHalf) >> shift; // x ,y int x2= x + xstep; int tr = (srcp[x2] * Yb + srcp[x2+1] * Yg + srcp[x2+2] * Yr + OffyPlusHalf) >> shift; // x+1, y x2= x - pitch; // NOTE - pitch int bl = (srcp[x2] * Yb + srcp[x2+1] * Yg + srcp[x2+2] * Yr + OffyPlusHalf) >> shift; // x ,y+1 x2= x + xstep - pitch; // NOTE - pitch int br = (srcp[x2] * Yb + srcp[x2+1] * Yg + srcp[x2+2] * Yr + OffyPlusHalf) >> shift; // x+1,y+1 dif += abs(tl - tr); // x,y <-> x+1,y dif += abs(tl - bl); // x,y <-> x,y+1 dif += abs(tr - br); // x+1,y <-> x+1,y+1 dif += abs(bl - br); // x,y+1 <-> x+1,y+1 } srcp -= ystride; } } else { for(y=1; y <= y_end; y += step) { for(x=xstep; x <= x_lim;x += xstride) { // x stride appropriate for slices int tl = (srcp[x] * Yb + srcp[x+1] * Yg + srcp[x+2] * Yr + OffyPlusHalf) >> shift; // x ,y int x2= x + xstep; int tr = (srcp[x2] * Yb + srcp[x2+1] * Yg + srcp[x2+2] * Yr + OffyPlusHalf) >> shift; // x+1, y x2= x - pitch; // NOTE - pitch int bl = (srcp[x2] * Yb + srcp[x2+1] * Yg + srcp[x2+2] * Yr + OffyPlusHalf) >> shift; // x ,y+1 dif += abs(tl - tr); // x,y <-> x+1,y dif += abs(tl - bl); // x,y <-> x,y+1 } // rhs column, x = W - 2 const int tl = (srcp[x] * Yb + srcp[x+1] * Yg + srcp[x+2] * Yr + OffyPlusHalf) >> shift; // x = W - 2, y int x2= x - pitch; // NOTE - pitch const int bl = (srcp[x2] * Yb + srcp[x2+1] * Yg + srcp[x2+2] * Yr + OffyPlusHalf) >> shift; // x = W - 2, y+1 dif += abs(tl-bl); srcp -= ystride; // y step appropriate for slices, NOTE subtract } // y = H - 2 for(x=xstep; x <= x_lim; x+=xstride) { // bottom row const int tl = (srcp[x] * Yb + srcp[x+1] * Yg + srcp[x+2] * Yr + OffyPlusHalf) >> shift; // x , y = H - 2 int x2= x + xstep; const int tr = (srcp[x2] * Yb + srcp[x2+1] * Yg + srcp[x2+2] * Yr + OffyPlusHalf) >> shift; // x , y = H - 2 dif += abs(tl-tr); } } } else { env->ThrowError("%sUnknown Colorspace",myName); } int count = (slices) ? (W/4 * H/4) * 4 : 2*((W-3)*(H-3)) + (H-3) + (W-3); double value = double(dif) / count; // count will be coerced to double during division AVSValue ret = value; // create type variant AVSValue and init with double (converted to float for AVSValue) return ret; // return value; // This would also work, value is implicitly converted to type AVSValue } // Avisynth v2.5 plugin initializer, requires AVISYNTH_INTERFACE_VERSION 3 Avisynth.h extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) { // Tell Aviynth name and args and which function to call env->AddFunction("AvgLumaDif", "c[slices]b[n]i[matrix]i", AvgLumaDif, 0); return "`AvgLumaDif' AvgLumaDif plugin"; // A freeform name of the plugin. }
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? |
22nd November 2013, 06:44 | #229 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Post #2 of 2
Test script Code:
Function AvgLumaDif_1(Clip c, bool "slices", int "n",int "Matrix") { # count, Check version c slices = Default(slices,False) n = Default(n,0) # default current_frame = 0 Matrix = Default(Matrix, Height < 600 ? 2 : 3) # REC601 : 1=REC709 : 2 = PC601 : 3 = PC709 W = (Width / 4) * 4 # Ignore RHS odds and ends, FULL 4x4 pixel blocks only H = (Height / 4) * 4 # Assert(W>0 && H>0,"AvgLumaDif_MOD: Illegal Frame Size") value=0.0 count = 0 GScript(""" if(slices) { for (y=1,H-3,4) { for (x=1,W-3,4) { value=value \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x+1, y2=y, w=1, h=1,matrix=Matrix) \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x, y2=y+1, w=1, h=1,matrix=Matrix) \ + RT_YDifference(c,n,delta=0, x=x+1, y=y, x2=x+1, y2=y+1, w=1, h=1,matrix=Matrix) \ + RT_YDifference(c,n,delta=0, x=x, y=y+1, x2=x+1, y2=y+1, w=1, h=1,matrix=Matrix) count = count + 4 } } } else { for (y=1,H-3) { for (x=1,W-3) { value=value \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x+1, y2=y, w=1, h=1) \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x, y2=y+1, w=1, h=1) count = count + 2 } } for (y=1,H-3) { # do last column value=value + RT_YDifference(c,n,delta=0, x=W-2, y=y, x2=W-2, y2=y+1, w=1, h=1) count = count + 1 } for (x=1,W-3) { # do last row value=value + RT_YDifference(c,n,delta=0, x=x, y=H-2, x2=x+1, y2=H-2, w=1, h=1) count = count + 1 } } value = value / (count) """) return value } Function AvgLumaDif_MOD(Clip c, bool "slices", int "n",int "Matrix") { # dll check version c slices = Default(slices,False) n = Default(n,0) # default current_frame = 0 Matrix = Default(Matrix, Height < 600 ? 2 : 3) # REC601 : 1=REC709 : 2 = PC601 : 3 = PC709 W = (Width / 4) * 4 # Ignore RHS odds and ends, FULL 4x4 pixel blocks only H = (Height / 4) * 4 # Assert(W>0 && H>0,"AvgLumaDif_MOD: Illegal Frame Size") value=0.0 GScript(""" if(slices) { for (y=1,H-3,4) { for (x=1,W-3,4) { value=value \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x+1, y2=y, w=1, h=1,matrix=Matrix) \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x, y2=y+1, w=1, h=1,matrix=Matrix) \ + RT_YDifference(c,n,delta=0, x=x+1, y=y, x2=x+1, y2=y+1, w=1, h=1,matrix=Matrix) \ + RT_YDifference(c,n,delta=0, x=x, y=y+1, x2=x+1, y2=y+1, w=1, h=1,matrix=Matrix) } } count = (W/4 * H/4) * 4 } else { for (y=1,H-3) { for (x=1,W-3) { value=value \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x+1, y2=y, w=1, h=1) \ + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x, y2=y+1, w=1, h=1) } value=value + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x, y2=y+1, w=1, h=1) # x = W - 2, Last column } for (x=1,W-3) { value=value + RT_YDifference(c,n,delta=0, x=x, y=y, x2=x+1, y2=y, w=1, h=1) # y = H - 2, Last row } count = 2*((W-3)*(H-3)) + (H-3) + (W-3) } value = value / count """) return value } W=512 H=64 T=True Avisource("D:\avs\test.avi").ConvertToYUY2().BilinearResize(W,H) A=AvgLumaDif_1(T) B=AvgLumaDif_MOD(T) C=AvgLumaDif(T,n=0) # dll defaults to current_frame rather than 0, can change in source. RT_DebugF ("%f %f %f",A,B,C) RT_SubTitle("%f %f %f",A,B,C) return last EDIT: Slices=False: Have used value of for() loop variable on exit from loop, ie end condition value + 1
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 22nd November 2013 at 07:10. |
22nd November 2013, 07:06 | #230 | Link |
Registered User
Join Date: Apr 2008
Location: California, USA
Posts: 127
|
Gavino & StainlessS are you sure that "for (y=1,H-3) { # do last column" and "for (x=1,W-3) { # do last row" shouldn't use "2" instead of "3" to actually work on the last row/column (ignoring the perimeter)?
Last edited by Forensic; 22nd November 2013 at 09:06. |
22nd November 2013, 07:14 | #231 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Yep, W-1 is last pixel, W-2 leaves 1 pixel perimeter untouched (same as at start).
EDIT: On say the bottom row, it starts column 1 to 2 dif, goes on to column W-3 to W-2 dif, leaving untouched W-1 pixel (W pixel not exist, ie range 0 -> W-1). W-3 end condition position, differences W-3 -> W-2.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 22nd November 2013 at 07:29. |
22nd November 2013, 09:15 | #232 | Link |
Registered User
Join Date: Apr 2008
Location: California, USA
Posts: 127
|
Okay, so then it seems I am right that the "for (y=1,H-3) { # do last column" and "for (x=1,W-3) { # do last row" lines SHOULD both use "2" not "3" to get the last non-perimeter row and column for when slices=false. Thank you both for your help with this. StainlessS, now that mediafire.com/StainlessS is no longer valid, where/when is the new RT_Stats build with this function?
|
22nd November 2013, 10:42 | #233 | Link | ||
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
Quote:
Sure, the pixels of the last (relevant) column have x=W-2 and y running from 1 to H-2. However, there are only H-3 comparisons, with each pixel in the range y=1 to H-3 being compared with the one below it. Similarly, in the last row, the comparisons run from x=1 to W-3. |
||
22nd November 2013, 19:32 | #234 | Link |
Registered User
Join Date: Apr 2008
Location: California, USA
Posts: 127
|
Gavino, Thank you so much for your wisdom and correcting the errors of my way.
StainlessS, Please let me know where to find the compiled version once it is available. I do have the ability to compile it myself, but discovered that anything I compile using VC++ 2012 will only work on computers that have that installed. An unlikely scenario for my forensic peers. Besides, it seems you are building this into RT_Stats. |
23rd November 2013, 00:08 | #238 | Link | |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Quote:
Will add to RT when established to be as required.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? |
|
23rd November 2013, 07:02 | #239 | Link |
Registered User
Join Date: Apr 2008
Location: California, USA
Posts: 127
|
neuron2: THANK YOU!!!!!!
For others looking to do the same in VS Express 2012, you press Alt-F7 and choose "Configuration Properties" - "C/C++" - "Code Generation" and then change the "RunTime Library" to "Multi-threaded Debug (/MTd)". I tested this by compiling the source code of several existing valid AviSynth codes and they all work without needing any special pre-installed software (at least from my limited testing). The only caveat is that the builds are larger, but that may be as a result of the windows.h & stdio.h VS Express uses -or- the use of Debug option in the RunTime library (which appears to be required if you VS2012 is to build a valid DLL) . Now I just need to learn proper C++ coding. Last edited by Forensic; 23rd November 2013 at 08:12. |
23rd November 2013, 08:04 | #240 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Has 'static' built in library routines rather than external runtime dll.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 24th November 2013 at 16:39. Reason: changed build to built |
Tags |
averageluma, correlation, lumadifference, runtime |
Thread Tools | Search this Thread |
Display Modes | |
|
|