我想了解最近邻插值在 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]
你能指导我吗?我在某个地方出错了吗?
我想了解最近邻插值在 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]
你能指导我吗?我在某个地方出错了吗?
如果您使用 应用常规插值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
更重要的是,以前观察到MATLAB和Octave之间的实现在某些情况下也有所不同。
正如您所指出的,在某些情况下,在使用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。
>> (0:0.1:1)' - linspace(0,1,11)'
ans =
0
0
0
5.5511e-17
0
0
0
0
0
0
0
NN 是最简单的插值形式。它有以下配方:使用最近的样本位置的值。MATLAB 中的 NN 插值计算效率很高,但如果您需要更高的精度,我建议您使用双线性或双三次插值。您也可以改为检查interp1()。
这里提供了一个例子的解释:http: //www.mathworks.com/help/vision/ug/interpolation-methods.html
我对此没有参考,因此我建议您使用其他示例对其进行测试,imresize
但我可以像这样恢复 Mat;ab 的值。
假设A
表示值和表示y
值中元素的位置。所以现在A
x
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
测试其他情况