Skip to content

MATLAB - 插值

插值是一种估计已知数据点之间未知值的过程。它是数据分析、信号处理和计算机图形学中的基本工具,用于重采样、平滑和填充缺失数据等任务。MATLAB 提供了一套全面的函数,用于对一维、二维和三维数据集以及散乱数据执行插值。

本教程重点介绍现代推荐的函数:用于一维数据的 interp1,用于二维网格数据的 interp2,用于三维网格数据的 interp3,以及用于更高级、注重性能的工作流程的 griddedInterpolant / scatteredInterpolant。

interp1 函数是一维插值的主要工具。给定一组采样点 (x, v),interp1 在一组新的查询点 xq 处找到值 vq。

vq = interp1(x, v, xq)
vq = interp1(x, v, xq, method)
vq = interp1(..., 'extrap')

其中 method 可以是 'linear'(默认)、'nearest'、'next'、'previous'、'pchip'、'cubic'、'spline' 或 'makima'。方法的选择决定了已知数据点之间曲线的构建方式。

示例 1:基本线性插值和样条插值

Section titled “示例 1:基本线性插值和样条插值”
% 1. 定义原始的粗略采样数据
x = 0:pi/2:2*pi;
v = sin(x);
% 2. 定义更精细网格的查询点
xq = 0:pi/16:2*pi;
% 3. 执行插值
vq_linear = interp1(x, v, xq, 'linear'); % 线性插值
vq_spline = interp1(x, v, xq, 'spline'); % 更平滑的样条插值
% 4. 绘制结果以进行比较
figure;
plot(x, v, 'o', 'MarkerSize', 10); % 原始采样点
hold on;
plot(xq, vq_linear, '.-'); % 线性插值结果
plot(xq, vq_spline, '--'); % 样条插值结果
hold off;
title('1D Interpolation of sin(x)');
xlabel('X');
ylabel('Value');
legend('Original Samples', 'Linear Interpolation', 'Spline Interpolation', 'Location', 'southwest');

输出图表显示了原始的粗略采样点为大圆圈。带点的蓝线显示了线性插值的“连点成线”结果。橙色虚线显示了样条插值产生的更平滑的曲线,这通常提供了更具物理合理性的拟合效果。

对于在规则网格上定义的数据(如图像或三维体),使用 interp2 和 interp3。其语法与 interp1 类似。

示例 2:使用 interp2 对二维网格进行插值

Section titled “示例 2:使用 interp2 对二维网格进行插值”
% 1. 创建粗略的二维网格和数据
[X, Y] = meshgrid(-3:1:3); % Coarse grid
Z = peaks(X, Y); % Z-values from the 'peaks' function
% 2. 创建更精细的网格以进行查询
[Xq, Yq] = meshgrid(-3:0.25:3); % Fine grid
% 3. 使用 'cubic' 方法执行二维插值
Zq = interp2(X, Y, Z, Xq, Yq, 'cubic');
% 4. 可视化比较
figure;
subplot(1, 2, 1);
surf(X, Y, Z);
title('Original Coarse Surface');
subplot(1, 2, 2);
surf(Xq, Yq, Zq);
title('Interpolated Fine Surface');

输出显示了两个子图。左图显示了基于原始粗略数据的块状曲面。右图显示了通过将值插值到更精细网格上创建的更平滑、更高分辨率的曲面。“三次”方法(cubic method)确保了所得曲面是平滑的。

当数据点 (x, y, z) 不在规则网格上时,它们被称为散乱数据。此时使用 griddata 函数,或者为了更好的性能,使用 scatteredInterpolant 对象。

示例 3:使用 scatteredInterpolant 提高效率

Section titled “示例 3:使用 scatteredInterpolant 提高效率”

scatteredInterpolant 对象在您需要多次查询同一散乱数据集时是理想的选择,因为它只执行一次代价高昂的初始三角剖分。

% 1. 生成随机散乱数据点
x = rand(100, 1) * 4 - 2; % 在 [-2, 2] 范围内的 100 个随机点
y = rand(100, 1) * 4 - 2;
z = x .* exp(-x.^2 - y.^2);
% 2. 创建插值对象
F = scatteredInterpolant(x, y, z, 'natural');
% 3. 定义一个规则网格以查询插值器
[Xq, Yq] = meshgrid(-2:0.1:2);
Zq = F(Xq, Yq); % 在网格上评估插值器
% 4. 绘制结果
figure;
surf(Xq, Yq, Zq); % 绘制插值曲面
hold on;
plot3(x, y, z, 'o', 'MarkerFaceColor', 'r', 'MarkerEdgeColor', 'k'); % 叠加原始点
hold off;
title('Interpolating Scattered Data');
legend('Interpolated Surface', 'Original Scattered Points', 'Location', 'northwest');

生成的图表显示了一个由散乱数据构建的平滑曲面。原始的 100 个数据点以红色圆圈的形式叠加,展示了曲面如何穿过它们。

  • 线性插值(Linear): 快速简单。适用于密集采样数据或对速度有严格要求的情况。
  • 样条/Pchip/Makima: 生成平滑曲线。'pchip' 和 'makima' 是很好的通用选择,因为它们避免了 'spline' 有时可能产生的过冲。
  • 最近邻(Nearest): 适用于分类数据,或当您需要保留原始值而不创建新值时。
  • 性能: 对于同一数据集的重复插值,使用 griddedInterpolant 或 scatteredInterpolant 可以显著提高性能。