Log in

View Full Version : What causes this discontinuity? A bug in bicubicresize?


wonkey_monkey
24th August 2018, 20:31
version
animate(0,100,"bicubicresize",\
16,16,1.0/3.0,1.0/3.0,32.0,32.0,16,16,\
16,16,1.0/3.0,1.0/3.0,30.0,30.0,16,16)


This script slowly shifts a static clip down and right by 2 pixels over 101 frames.

At frame 50 (and 0 and 100), there's a clear "jump" when the shift becomes an exact integer number of pixels. Is this a rouding error of some kind?

Here is a difference overlay of each frame and its immediate future neighbour:

https://i.imgur.com/JGJD61d.png

I submit that this is incorrect behaviour - according to the Wiki I've used the default values for b and c, and although the demonstration is an animation, I expect it would also cause artefacts in a static resize, but they'd be harder to see because it would just look like slightly greater sharpness on certain pixels. My understanding of bicubic is that it is everywhere continuous, so I don't think this should happen.

Bilinearresize and spline16resize do not exhibit this problem, and nor does my own pixel remapper which uses my own implementation of bicubic resampling.

Avisynth+ version is r2728.

Edit: New information: YV12 does not seem to be affected. YUY2 is affected to a lesser degree. RGB24/RGB32 are both affected as shown above, as are YV24 and Y8.

pinterf
27th August 2018, 14:05
Thanks for the observation, spent quite a bit of time on it.

So when specific conditions are met, resize can fallback to a single Crop:
https://github.com/pinterf/AviSynthPlus/blob/MT/avs_core/filters/resample.cpp#L2082
and
https://github.com/pinterf/AviSynthPlus/blob/MT/avs_core/filters/resample.cpp#L2112

Now the question is that this is good or not. Seems that it was a planned behaviour.

wonkey_monkey
27th August 2018, 14:39
It should be fine to fall back to a crop, because an integral (sub)pixel shift would mean all coefficients will be zero, except for one of them which will be 1, making it the same as a crop.

But the other frames shouldn't be this blurry.

I assume spline16resize similarly reduces to a crop when possible, but it doesn't exhibit this problem.

pinterf
27th August 2018, 15:41
For 32bit float format I can see the same difference by looking at the Histogram so it's not a rounding issue. The exact peaks of histogram are smeared a bit for non-integer shifts giving the image a blurry look.

wonkey_monkey
27th August 2018, 15:47
I took the code from MitchellNetravaliFilter (which is what bicubicresize uses) to make a graph and it peaks, when x=0, at only 0.888888. When x=-1 or x=1, it has a value of 0.055555.

That makes it a blurrer. I'm pretty sure a bicubic filter shouldn't do this - it should peak at 1 when x=0, and be at 0 at all other integers.

If nothing else, there is the problem with falling back to cropping, and the fact that different colourspaces give different results (presumably because some don't fall back to cropping).

Edit: I guess a bicubic filter can blur if it wants, but what I mean is that I don't think this (blurring) should be the expected behaviour of a resizer. If nothing else, it should tend towards the original image smoothly as it tends towards integer offsets. I think it would be better for it to default to b=0.0 c=0.5 which I think gives a Catmull Rom filter, which is what GIMP uses for bicubic.

I think I'll use spline16 instead from now on!

The exact peaks of histogram are smeared a bit for non-integer shifts giving the image a blurry look.

The pixels are smeared for integer shifts as well; it just gets hidden because it falls back on crop.

pinterf
27th August 2018, 18:19
Yes, disabled the crop, at least it became consistently blurry. I don't think that this edge case speed gain is worth vs. consistent behaviour.

wonkey_monkey
27th August 2018, 20:33
Probably the least disruptive solution, if not my preferred one :)

wonkey_monkey
15th August 2025, 21:29
It seems there's still a bypass of BicubicResize going on somewhere, e.g.

ColorbarsHD
BicubicResize(1288,720)

should be identical to:

ColorbarsHD
BicubicResize(1288,720,src_left=0.00000001)

since the shift is too small to actually affect pixel values.

But the default b and c values should result in a blur - the blur is missing in the first one because the resize is bypassed (also evident from benchmarking; src_left=0.00000001 runs at 370fps, but omitting src_left results in "too short for meaningful measurements".