4

I am confused by Matlab's example on Bicubic interpolation at http://www.mathworks.com/help/vision/ug/interpolation-methods.html#f13689

I think I understand their Bilinear example. It seems like they took the averages of the adjacent translated values on either side. So, to get the 0.5 in their first row, first column, the average of 0 and 1 was taken.

For their Bicubic interpolation example, I am rather confused by their method. They say that they take the "weighted average of the two translated values on either side".

In their example, they have

1 2 3
4 5 6
7 8 9

and in their first step of Bicubic interpolation, they add zeros to the matrix and translate it by 0.5 pixel to the right to get the following:

0 0 0 1 1 2 2 3 3 0 0 0 0
0 0 0 4 4 5 5 6 6 0 0 0 0
0 0 0 7 7 8 8 9 9 0 0 0 0

Then, using weighted average, they get

0.375 1.500 3.000 1.625
1.875 4.875 6.375 3.125
3.375 8.250 9.750 4.625

However, I am not sure how they got those numbers. Instead of 0.375 in the first row, first column, I would have done instead (1 * 3/8 + 2 * 1/8) = 5/8 . This is because the format seems to be

0  _  0  1  1  _  2
3d    d     d     3d

where d is the distance.

So to take the weighted average of the translated values, we can note that the we can first do (3d + d + d + 3d) = 1 and so d = 1/8. That means we should put 3/8 weight on each of the closer translated values and 1/8 weight on each of the further translated values. That leads to (0 * 1/8 + 0 * 3/8 + 1 * 3/8 + 2 * 1/8), which is 5/8 and does not match their 3/8 result. I was wondering where I went wrong.

Thanks!

Daniel Heilper
  • 1,182
  • 2
  • 17
  • 34
ThinkFlow
  • 161
  • 1
  • 3
  • 16

3 Answers3

2

Bicubic interpolation uses negative weights (this sometimes results in overshoot when filtering).

In this example, the weights used are:

-1/8 5/8 5/8 -1/8

These weights sum to 1, but give larger weight to the middle samples and smaller (negative) weights to the outer samples.

Using these weights we get the observed values, e.g.

0.375 = 5/8*1 -1/8*2
1.5 = 5/8*1+5/8*2 -1/8*3
Peter de Rivaz
  • 33,126
  • 4
  • 46
  • 75
2

I found this topic imresize - trying to understand the bicubic interpolation could solve your confusion, especially for the comment with 7 upvotes. By the way, in that comment, the author states that alpha = -0.5 in Matlab, it's contrast to my experience. I wrote 2 functions to test, and I figured out Matlab set alpha = -0.9.

Here are the code I could provide:

Cubic:

function f = cubic(x)
    a = -0.9;
    absx = abs(x);
    absx2 = absx.^2;
    absx3 = absx.^3;
    f = ((a+2)*absx3 - (a+3)*absx2 + 1) .* (absx <= 1) + ...
        (a*absx3 -5*a*absx2 + 8*a*absx - 4*a) .* ((1 < absx) & (absx <= 2));
end

Interpolation with Bi-cubic:

function f = intpolcub(x1,x2,x3,x4,d)
    f = x1*cubic(-d-1) + x2*cubic(-d) + x3*cubic(-d+1) + x4*cubic(-d+2);
end

You could test with the following line of code:

intpolcub(0,0,1,2,0.5)

This reproduce the first number in the output matrix of Matlab example about bicubic interpolation you have mentioned above.

Community
  • 1
  • 1
nhnminh
  • 371
  • 3
  • 3
  • I forget to add a link to the topic: **[imresize-stackoverflow](http://stackoverflow.com/questions/26823140/imresize-trying-to-understand-the-bicubic-interpolation)** – nhnminh Oct 09 '16 at 22:00
  • I made a test with your code and found out that `a = -0.5` in MATLAB R2021a. Compare the center value of `imresize([0, 0, 1, 2], 3/4, 'bicubic', 'Antialiasing', false)` or `interp2(repmat([0, 0, 1, 2], 3, 1), 2.5, 1, 'cubic')` with `intpolcub(0,0,1,2,0.5)` with `a = -0.5`. – John Apr 01 '21 at 00:15
0

Matlab (R2017a) works with a=-1 so:

For cubic:

function f_c = cubic(x)
    a = -1;
    absx = abs(x);
    absx2 = absx.^2;
    absx3 = absx.^3;
    f_c = ((a+2)*absx3 - (a+3)*absx2 + 1) .* (absx <= 1) + ...
        (a*absx3 -5*a*absx2 + 8*a*absx - 4*a) .* ((1 < absx) & (absx <= 2));
end

And for Bicubic interpolation:

function f_bc = intpolcub(x1,x2,x3,x4,d)
    f_bc = x1*cubic(-d-1) + x2*cubic(-d) + x3*cubic(-d+1) + x4*cubic(-d+2);
end

Test:

intpolcub(0,0,1,2,0.5)

Explicitly it goes:

f_bc = 0*cubic(-0.5-1)+0*cubic(-0.5)+1*cubic(-0.5+1)+2*cubic(-0.5+2) = 1*cubic(0.5)+2*(cubic(1.5);

Now the calculation of cubic for 0.5 (f_c<1) and 1.5 (1<f_c<=2) is:

cubic(0.5) = (-1+2)*0.5^3-(-1+3)*0.5^2+1 = 5/8

cubic(1.5) = (-1)*1.5^3-5*(-1)*1.5^2+8*(-1)*1.5-4*(-1) = -1/8

So that f_bc is:

f_bc = 5/8+2*(-1/8) = 0.375
James
  • 11
  • 6