Reputation: 171
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!
Upvotes: 4
Views: 7846
Reputation: 21
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
Upvotes: 0
Reputation: 411
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.
Upvotes: 2
Reputation: 33509
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
Upvotes: 2