4

我想了解最近邻插值在 MATLAB 中的工作原理。我有输入数据:

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

我使用以下 MATLAB 代码:

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

我得到以下结果:

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

手动求解,我得到了这个结果:

[1 4 4 7 4 4 3 3 6]

你能指导我吗?我在某个地方出错了吗?

4

3 回答 3

3

如果您使用 应用常规插值interp1,它将为您提供手动计算的结果:

>> 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

前段时间,我浏览了 IMRESIZE 的源代码,试图了解它是如何工作的。请参阅此帖子以获取摘要。在某些时候,代码将调用私有 MEX 函数(没有相应的源代码可用),但注释足以理解实现。

值得一提的是,还有一个函数imresize_old提供了imresize(在 R2006b 及更早版本中使用)的较旧实现。它给出了另一个不同的结果:

>> 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

更重要的是,以前观察到MATLABOctave之间的实现在某些情况下也有所不同。


编辑:

插值

正如您所指出的,在某些情况下,在使用interp1. 所以我们可以通过将 x 数选择在[0,1]范围之间或更稳定的范围(如[1,numel(A)]. 由于边缘情况下的舍入误差,这可能会产生不同的结果。

例如比较下面的两个代码:

% 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])

反对:

% 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])

这是格式良好的输出:

--------------------------------------------------------
       [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 |
--------------------------------------------------------

因此,您可以看到在 [0,1] 范围内工作时,某些数字不能以双精度精确表示。因此,应该在中间 [0.2, 0.4] 的 0.3 由于舍入误差而变得比 0.4 更接近下端 0.2。而在另一边,2.5 正好在 [2,3] 的中间(所有数字都精确表示),并使用最近邻分配给上端 3。

另请注意,colon有时linspace会产生不同的输出:

>> (0:0.1:1)' - linspace(0,1,11)'
ans =
            0
            0
            0
   5.5511e-17
            0
            0
            0
            0
            0
            0
            0
于 2013-09-20T12:22:43.493 回答
1

NN 是最简单的插值形式。它有以下配方:使用最近的样本位置的值。MATLAB 中的 NN 插值计算效率很高,但如果您需要更高的精度,我建议您使用双线性或双三次插值。您也可以改为检查interp1()

这里提供了一个例子的解释:http: //www.mathworks.com/help/vision/ug/interpolation-methods.html

于 2013-09-20T03:31:42.717 回答
0

我对此没有参考,因此我建议您使用其他示例对其进行测试,imresize但我可以像这样恢复 Mat;ab 的值。

假设A表示值和表示y值中元素的位置。所以现在Ax

n = length(A);
N = 9;

x = 1:n %// i.e. 1:6

现在我们需要找到插值位置,即xi点。我会这样做:

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

这使

xi =

   1   1   2   3   3   4   5   5   6

yi这导致

yi = A(xi)

yi =

   1   1   4   7   7   4   3   3   6

这与你和 Matlab 的答案不同(你是怎么得到你的?)

所以我尝试了:

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

这同样有意义,让我得到 Matlab 的结果

yi =

   1   4   4   7   4   4   3   6   6

所以我猜他们就是这样做的。但我不必imresize测试其他情况

于 2013-09-20T06:55:03.627 回答