Log in

View Full Version : need a slightly different "reduceby2"


10L23r
29th May 2009, 02:55
the wikiarticle on "reduceby2" claims that its uses a (1/4,1/2,1/4) kernel in place of a (1/2,1/2) to avoid aliasing.

is there a different version of reduceby2 that uses a (1/2,1/2) kernel?

Shouldn't a (1/2,1/2) kernel be better for the downsize portion of an antialiasing script (upsize, nnedi/sangnom, downsize)?

*.mp4 guy
29th May 2009, 05:16
Yes, you are correct, 1/2, 1/2 is better for reducing following supersampling (atleast in my experience). I have a function just for this purpose, it requires the average plugin. One thing to take note of is that such interpolation will always introduce a 1/4 pixel shift in the output image.

function Box(clip c)
{
out0 = c.pointresize(round(c.width/2), round(c.height/2), 0, 0, round(c.width), round(c.height))
out1 = c.pointresize(round(c.width/2), round(c.height/2), 1, 0, round(c.width), round(c.height))
out2 = c.pointresize(round(c.width/2), round(c.height/2), 0, 1, round(c.width), round(c.height))
out3 = c.pointresize(round(c.width/2), round(c.height/2), 1, 1, round(c.width), round(c.height))

average(out0, 0.25, out1, 0.25, out2, 0.25, out3, 0.25)
}

10L23r
29th May 2009, 05:43
k thx.

actually, i don't think that the shift would occur if you considered each pixel to be a square rather than a point.

Fizick
29th May 2009, 19:46
bilinearresize

Gavino
29th May 2009, 19:58
Doesn't BilinearResize also use a (1/4,1/2,1/4) kernel when downsizing by two? The OP wants a (1/2,1/2) kernel.

IanB
30th May 2009, 00:40
No the resizer core adjusts the origin such that it maintains the centre of the image, and (1/2,1/2) kernel will be what is required for this x0.5 scaling case.

Play with this script to see the effect.BlankClip(1, 96, 96)

Addborders(2,2,2,2, $C040C0)
Addborders(2,2,2,2, $40C040)
Addborders(2,2,2,2, $C040C0)

Addborders(10,10,10,10) # Even pair aligned clip

A=BilinearResize(Width()/2, Height()/2) # Select Even pairs
B=BilinearResize(Width()/2, Height()/2, 1, 1) # Select Odd pairs

BlankClip(1, 94, 94)

Addborders(2,2,2,2, $C040C0)
Addborders(2,2,2,2, $40C040)
Addborders(2,2,2,2, $C040C0)

Addborders(11,11,11,11) # Odd pair aligned clip

C=BilinearResize(Width()/2, Height()/2) # Select Even pairs
D=BilinearResize(Width()/2, Height()/2, 1, 1) # Select Odd pairs

Interleave(A, B, C, D)

Gavino
30th May 2009, 01:37
No the resizer core adjusts the origin such that it maintains the centre of the image, and (1/2,1/2) kernel will be what is required for this x0.5 scaling case.
But what about the extended filter support you get for anti-aliasing when downsizing.
Isn't the BilinearResize kernel actually (1/8, 3/8, 3/8, 1/8) in this case?

10L23r
30th May 2009, 02:32
actually, i originally wanted a filter that averages the value of the four pixels it takes the place of... i think this the same as a .5,.5 kernel...

i was thinking about something like this:

average/merge even and odd fields; rotate; repeat average fields; rotateback

except i don't know if there is a filter that can extract even and odd lines.


the pointresize thing rly annoys me cus for whatever reason, it doesn't seem to do exactly what i want it to...

edit: would separatefields().selecteven() or selectodd work to extract even/odd fields? i think there should be something better

IanB
30th May 2009, 02:46
double scale = double(target_width) / subrange_width; 64 / 128 = 0.5
double filter_step = min(scale, 1.0); 0.5
double filter_support = func->support() / filter_step; 1 / 0.5 = 2.0
int fir_filter_size = int(ceil(filter_support*2)); 2.0 * 2 = 4
...
double pos_step = subrange_width / target_width; 128 / 64 = 2.0
Yes fir_filter_size = 4, so it will be (1/8, 3/8, 3/8, 1/8), ah well back to the drawing board. :(

10L23r
30th May 2009, 02:51
i fixed the problem with the pointresize script, but idk why this works...

function Box(clip c)
{
out0 = c.pointresize(round(c.width/2), round(c.height/2), 0, -1, round(c.width), round(c.height))
out1 = c.pointresize(round(c.width/2), round(c.height/2), 1, 0, round(c.width), round(c.height))
out2 = c.pointresize(round(c.width/2), round(c.height/2), 0, -1, round(c.width), round(c.height))
out3 = c.pointresize(round(c.width/2), round(c.height/2), 1, 0, round(c.width), round(c.height))

average(out0, 0.25, out1, 0.25, out2, 0.25, out3, 0.25)
}

*.mp4 guy
30th May 2009, 08:02
actually, i originally wanted a filter that averages the value of the four pixels it takes the place of... i think this the same as a .5,.5 kernel...
Thats exactly what the code i posted does.

i fixed the problem with the pointresize script, but idk why this works...

function Box(clip c)
{
out0 = c.pointresize(round(c.width/2), round(c.height/2), 0, -1, round(c.width), round(c.height))
out1 = c.pointresize(round(c.width/2), round(c.height/2), 1, 0, round(c.width), round(c.height))
out2 = c.pointresize(round(c.width/2), round(c.height/2), 0, -1, round(c.width), round(c.height))
out3 = c.pointresize(round(c.width/2), round(c.height/2), 1, 0, round(c.width), round(c.height))

average(out0, 0.25, out1, 0.25, out2, 0.25, out3, 0.25)
}

That averages two points, twice, IE
out0=a
out1=b
out2=a
out3=b

(a +b + a + b)/4

Gavino
30th May 2009, 09:31
If the clip is RGB, you need to use -1 instead of +1 for the vertical offset, because Avisynth processes RGB from the bottom up.
function Box(clip c) {
out0 = c.pointresize(round(c.width/2), round(c.height/2), 0, 0, round(c.width), round(c.height))
out1 = c.pointresize(round(c.width/2), round(c.height/2), 1, 0, round(c.width), round(c.height))
out2 = c.pointresize(round(c.width/2), round(c.height/2), 0, -1, round(c.width), round(c.height))
out3 = c.pointresize(round(c.width/2), round(c.height/2), 1, -1, round(c.width), round(c.height))

average(out0, 0.25, out1, 0.25, out2, 0.25, out3, 0.25)
}

@10L23r: I think your idea of using SelectOdd, etc, would also work. Something like:
SeparateFields().Merge(SelectEven(), SelectOdd())
TurnRight()
SeparateFields().Merge(SelectEven(), SelectOdd())
TurnLeft()

10L23r
30th May 2009, 19:57
That averages two points

oops, lol, that was rly stupid... i meant this:

function Box(clip c)
{
out0 = c.pointresize(round(c.width/2), round(c.height/2), 0, 0, round(c.width), round(c.height))
out1 = c.pointresize(round(c.width/2), round(c.height/2), 1, 0, round(c.width), round(c.height))
out2 = c.pointresize(round(c.width/2), round(c.height/2), 0, -1, round(c.width), round(c.height))
out3 = c.pointresize(round(c.width/2), round(c.height/2), 1, -1, round(c.width), round(c.height))

average(out0, 0.25, out1, 0.25, out2, 0.25, out3, 0.25)
}

Gavino
30th May 2009, 20:40
Yeah, that's what I said earlier, where I explained why it works.
(Is your clip RGB?)

10L23r
30th May 2009, 22:15
oh... i didn't notice that you posted the same thing earlier

yes, my clip is rgb. does the second method work regardless of colorspace?

Gavino
31st May 2009, 00:41
does the second method work regardless of colorspace?
You mean the SeparateFields, etc, method?
I believe it should work for both RGB and YV12, but not for YUY2 (because TurnRight/Left are lossy in that case).

IanB
31st May 2009, 01:11
@Gavino,

You should not be spec'ing the -1 offset differently for RGB, the code already deals with it....
if (vi.IsRGB())
subrange_top = vi.height - subrange_top - subrange_height;

10L23r
31st May 2009, 01:27
i know that the -1 offset shouldn't be used... but it isn't used, the output image is shifted 0.5 pixels upward, causing blur.

quick question: when converting to yv12, what resampler is used for the chroma?

Gavino
31st May 2009, 09:49
You should not be spec'ing the -1 offset differently for RGB, the code already deals with it....
if (vi.IsRGB())
subrange_top = vi.height - subrange_top - subrange_height;
The point is that for RGB, PointResize(width/2, height/2) selects the odd pixels because it starts at the bottom. To select all the even pixels, you need to use an offset of -1 to start at the line above the bottom (subrange_top=+1). Using an offset of +1 (subrange_top=-1) selects even pixels, but is shifted down a line, missing the pixel at line 0 and adding a new one at the bottom.

The proof is that 10L23r had to change the Box function to get the result he wanted.

Gavino
1st June 2009, 17:07
quick question: when converting to yv12, what resampler is used for the chroma?
See http://avisynth.org/mediawiki/Sampling#Subsampling