我想了解最近邻插值在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]
你能指导我吗?我在某个地方出错了吗?
答案 0 :(得分: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的源代码,试图了解它是如何工作的。 See this post摘要。在某些时候,代码将调用私有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
it was previously observed 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.2的下端而不是0.4。而在另一方面,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
答案 1 :(得分:1)
NN是最简单的插值形式。它具有以下配方:使用最近的样本位置处的值。 MATLAB中的NN插值具有计算效率,但如果您需要更高的精度,我建议您使用双线性或双三次插值。您也可以检查 interp1()。
此处提供了一个示例说明:http://www.mathworks.com/help/vision/ug/interpolation-methods.html
答案 2 :(得分:0)
我没有参考,所以我建议您使用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
来测试其他案例