How does nearest neighbor interpolation work in MATLAB?

I want to know how the closest neighbor interpolation works in MATLAB. I have input:

A = [1 4 7 4 3 6] % 6 digit vector 

I am using the following MATLAB code:

 B = imresize(A,[1 9],'nearest'); 

I get the following result:

 [1,4,4,7,4,4,3,6,6] 

Solving manually, I get this result:

 [1 4 4 7 4 4 3 3 6] 

Can you guide me? Am I mistaken somewhere?

+4
source share
3 answers

If you apply regular interpolation using interp1 , it will give you the result that you calculated manually:

 >> N = 9; >> B = interp1(linspace(0,1,numel(A)), A, linspace(0,1,N), 'nearest') B = 1 4 4 7 4 4 3 3 6 

Some time ago I looked at the source code of IMRESIZE, trying to understand how this works. See this post for a summary. At some point, the code will call a private MEX function (without the corresponding source code), but there are enough comments to understand the implementation.

For what it's worth, there is also the imresize_old function, which provides an older imresize implementation (used in R2006b and earlier). This gave another different result:

 >> B = imresize(A, [1 N], 'nearest') B = 1 4 4 7 4 4 3 6 6 >> B = imresize_old(A, [1 N], 'nearest') B = 1 4 4 7 7 4 3 6 6 

What was previously noted , the implementation between MATLAB and Octave was also different in some cases.


EDIT:

interpolation

As you noted, in some cases you should be aware of floating point restrictions when working with interp1 . Thus, we could interpolate by choosing x-numbers between the range [0,1] or a more stable range, for example [1,numel(A)] . Due to rounding errors in edge cases, this can give different results.

For example, compare the two codes below:

 % interpolation in [0,1] N = 11; y = [1 4 7 4 3 6]; x = linspace(0,1,numel(y)); xi = linspace(0,1,N); yi = interp1(x, y, xi, 'nearest'); % print numbers with extended precision fprintf('%.17f %g\n',[x;y]) fprintf('%.17f %g\n',[xi;yi]) 

vs

 % interpolation in [1,k] N = 11; y = [1 4 7 4 3 6]; x = 1:numel(y); xi = linspace(1,numel(y),N); yi = interp1(x, y, xi, 'nearest'); % print numbers with extended precision fprintf('%.17f %g\n',[x;y]) fprintf('%.17f %g\n',[xi;yi]) 

Here is a result that is well formatted:

 -------------------------------------------------------- [0,1] RANGE | [1,k] RANGE -------------------------------------------------------- xi yi | xi yi -------------------------------------------------------- 0.00000000000000000 1 | 1.00000000000000000 1 | 0.20000000000000001 4 | 2.00000000000000000 4 | 0.40000000000000002 7 | 3.00000000000000000 7 | 0.59999999999999998 4 | 4.00000000000000000 4 | INPUT 0.80000000000000004 3 | 5.00000000000000000 3 | 1.00000000000000000 6 | 6.00000000000000000 6 | -------------------------------------------------------- 0.00000000000000000 1 | 1.00000000000000000 1 | 0.10000000000000001 4 | 1.50000000000000000 4 | 0.20000000000000001 4 | 2.00000000000000000 4 | 0.29999999999999999 4 | 2.50000000000000000 7 | 0.40000000000000002 7 | 3.00000000000000000 7 | 0.50000000000000000 4 | 3.50000000000000000 4 | OUTPUT 0.59999999999999998 4 | 4.00000000000000000 4 | 0.69999999999999996 4 | 4.50000000000000000 3 | 0.80000000000000004 3 | 5.00000000000000000 3 | 0.90000000000000002 6 | 5.50000000000000000 6 | 1.00000000000000000 6 | 6.00000000000000000 6 | -------------------------------------------------------- 

So, you can see that some numbers are not accurately represented in double precision when working in the range [0,1]. Thus, 0.3, which is supposedly located in the middle [0.2, 0.4], is closer to the lower end 0.2 0.2 due to rounding error. While on the other side 2.5 is exactly in the middle of [2,3] (all numbers are accurately represented) and assigned to the upper end of 3 with the help of the nearest neighbor.

Also keep in mind that colon and linspace can sometimes produce different results:

 >> (0:0.1:1)' - linspace(0,1,11)' ans = 0 0 0 5.5511e-17 0 0 0 0 0 0 0 
+3
source

NN is the simplest form of interpolation. It has the following recipe: use the value at the closest sample location. MATLAB's NN interpolation is computationally efficient, but if you need higher accuracy, I recommend using bilinear or bicubic interpolation. You can also check interp1 () .

Here is an explanation with an example: http://www.mathworks.com/help/vision/ug/interpolation-methods.html

+1
source

I have no links for this, so I suggest you test it against other examples using imresize , but I can restore the Mat values; ab like this.

Suppose A represents y values ​​and the positions of elements in A represent x values. so now

 n = length(A); N = 9; x = 1:n %// ie 1:6 

Now we need to find the interpolation position, i.e. xi . I would do it like this:

 xi = round((1:N)/N)*n 

which gives

 xi = 1 1 2 3 3 4 5 5 6 

leading to a yi of

 yi = A(xi) yi = 1 1 4 7 7 4 3 3 6 

which is different from your and matlab answers (how did you get yours?)

So I tried:

 xi = round(((0:N-1)/N)*n)+1 yi = A(xi) 

which makes as much sense and gets matlab result

 yi = 1 4 4 7 4 4 3 6 6 

So, I guess they do it. But I don't have imresize to check for other cases

0
source

All Articles