Skip to content

MATLAB - 二维数组插值

在 MATLAB 中,二维插值是在已知采样点的网格中估计新点的值的过程。它是一种关键技术,用于图像大小调整、数据上采样以实现更平滑的可视化以及填充缺失数据。其主要函数是 interp2。

Vq = interp2(X, Y, V, Xq, Yq, method)
  • X、Y、V: 这些定义了原始数据。V 是一个值矩阵,X 和 Y 是相应的坐标矩阵(通常使用 meshgrid 创建)。
  • Xq、Yq: 这些是您希望估计值的查询点的坐标。
  • Vq: 在查询点处插值结果的输出矩阵。
  • method: 指定插值算法的字符串。这是一个关键的选择,会影响结果的质量和速度。

方法的选择取决于您的数据和目标:

方法描述最佳用途
'linear' (默认)快速、分段线性插值。用直线连接点。通用,速度和平滑度之间的良好平衡。
'cubic'较慢、分段三次插值。生成更平滑的表面。用于可视化,当平滑度至关重要时。有时可能出现过冲。
'spline'平滑连续,基于三次样条。计算成本高。高质量、平滑的结果,没有 'cubic' 的过冲。
'nearest'非常快。分配最近已知点的值。创建块状外观。保留原始数据值、分类数据,或当速度最重要时。
'makima'改进的 Akima 三次 Hermite 方法。平滑如三次插值,但避免过冲。适用于具有急剧变化或平坦区域的数据,其中不希望出现过冲。

让我们创建一个粗糙的表面,并将其插值到更精细的网格上,以创建更平滑的绘图。

% 1. 创建一个粗糙网格并采样数据
[X, Y] = meshgrid(1:5);
V = peaks(X, Y);
% 2. 创建一个更精细的查询网格
[Xq, Yq] = meshgrid(1:0.25:5);
% 3. 使用不同方法执行插值
Vq_linear = interp2(X, Y, V, Xq, Yq, 'linear');
Vq_cubic = interp2(X, Y, V, Xq, Yq, 'cubic');
Vq_nearest = interp2(X, Y, V, Xq, Yq, 'nearest');
% 4. 可视化结果
figure;
tiledlayout(2, 2);
% 原始表面
nexttile;
surf(X, Y, V);
title('Original Coarse Surface');
% 线性插值
nexttile;
surf(Xq, Yq, Vq_linear);
title('Linear Interpolation');
% 三次插值
nexttile;
surf(Xq, Yq, Vq_cubic);
title('Cubic Interpolation');
% 最近邻插值
nexttile;
surf(Xq, Yq, Vq_nearest);
title('Nearest-Neighbor Interpolation');

示例 2:不使用显式网格坐标的重采样

Section titled “示例 2:不使用显式网格坐标的重采样”

如果您的数据 V 对应于默认网格(X = 1:size(V,2),Y = 1:size(V,1)),则可以在调用中省略 X 和 Y。interp2(V, k) 提供了一个方便的快捷方式,用于按整数因子 k 进行重采样。

% 1. 创建一个样本数据矩阵
V = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16];
% 2. 将数据精细化 4 倍(k=4)
% 这会在每个样本之间插值 3 个新点
k = 4;
Vq = interp2(V, k, 'cubic'); % 使用三次插值以获得平滑结果
% 3. 绘制结果
figure;
tiledlayout(1, 2);
nexttile;
imagesc(V);
axis equal tight;
title('Original 4x4 Grid');
nexttile;
imagesc(Vq);
axis equal tight;
title('Interpolated 17x17 Grid (k=4)');

当您需要在同一数据集上执行多次插值时,interp2 可能会效率低下,因为它每次都会重新计算三角剖分。对于这些情况,现代且强烈推荐的方法是使用 griddedInterpolant。

% 1. 创建插值器对象一次
[X, Y] = meshgrid(-3:0.2:3);
Z = peaks(X, Y);
F = griddedInterpolant(X, Y, Z, 'cubic');
% 2. 根据需要多次查询该对象
[Xq, Yq] = meshgrid(-3:0.05:3);
Zq = F(Xq, Yq);
% 这比在循环中重复调用 interp2 快得多。
  • 查询点超出网格范围:默认情况下,对于位于原始采样点 (X, Y) 域之外的任何查询点 (Xq, Yq),interp2 返回 NaN。如果需要,您可以指定一个外推值,例如 interp2(..., 'linear', 0),以便对网格外的点返回 0。
  • 单调网格向量:用于定义网格的坐标向量(meshgrid 中的 X 和 Y)必须是单调的(严格递增或递减)。
  • 选择错误的方法:在具有尖锐不连续性的数据上使用 'cubic' 或 'spline' 可能会导致不希望的振铃或振荡。在这种情况下,'linear' 或 'makima' 通常是更好的选择。

尝试加载一个标准的 MATLAB 演示图像(例如,I = imread('peppers.png');)。将其转换为灰度图并缩小。然后,使用 interp2 与 'nearest'、'linear' 和 'cubic' 方法将其缩放回原始大小。比较结果以查看每种插值算法的实际影响。