跳转至

好的,遵照您的要求,这是一份极其详尽的 MATLAB 数据插值终极指南。本文档全面融合了数学原理与公式函数详细语法功能概括代码示例,并严格遵守了您提出的所有格式化要求。


MATLAB 数据插值详解

数据插值是一种通过已知的、离散的数据点,来构造新的数据点(即在已知点之间“插入”值)的数学方法。它在信号处理、图像缩放、数据重采样以及填补缺失数据等领域有着广泛的应用。

插值 vs. 拟合 vs. 外插

  • 插值 (Interpolation): 新构造的函数/曲线必须穿过所有原始数据点。
  • 拟合 (Fitting): 新构造的函数/曲线不必穿过所有原始数据点,而是捕捉数据的整体趋势,通常用于含噪数据。
  • 外插 (Extrapolation): 在原始数据点范围之外预测新的数据点,其结果通常不可靠,需谨慎使用。

一维插值 (1-D Interpolation)

interp1 - 通用一维数据插值

  • 功能 给定一组样本点 \((x_i, y_i)\) 和一组新的查询点 \(x_q\),返回在 \(x_q\) 处的插值 \(y_q\)。这是 MATLAB 中最常用、最灵活的一维插值函数。

  • 语法

    yq = interp1(x, y, xq)
    yq = interp1(x, y, xq, method)
    yq = interp1(x, y, xq, method, 'extrap')
    

  • 语法说明

    • interp1(x, y, xq): 使用默认的 'linear' 方法进行插值。
    • method: 指定插值方法的字符串,详见下文“插值方法原理”部分。
    • 'extrap': 允许函数在 x 的范围之外进行外插。
  • 示例

    % 1. 创建稀疏的原始数据点
    x = 0:pi/2:2*pi;
    y = sin(x);
    
    % 2. 创建密集的查询点
    xq = 0:pi/16:2*pi;
    
    % 3. 使用不同方法进行插值
    yq_linear = interp1(x, y, xq, 'linear');
    yq_spline = interp1(x, y, xq, 'spline');
    yq_pchip = interp1(x, y, xq, 'pchip');
    
    % 4. 绘图比较
    figure;
    plot(x, y, 'ro', 'MarkerSize', 10, 'DisplayName', '原始采样点');
    hold on;
    plot(xq, yq_linear, 'b- .', 'DisplayName', '线性 (linear)');
    plot(xq, yq_spline, 'g--', 'LineWidth', 2, 'DisplayName', '样条 (spline)');
    plot(xq, yq_pchip, 'm:', 'LineWidth', 2, 'DisplayName', '保形 (pchip)');
    legend;
    title('interp1 一维插值方法比较');
    

插值方法原理与公式

'linear' - 线性插值

  • 原理: 对于位于区间 \([x_i, x_{i+1}]\) 内的查询点 \(x_q\),其插值 \(y_q\) 位于连接 \((x_i, y_i)\)\((x_{i+1}, y_{i+1})\) 的直线上。

  • 公式:

    [ y_q = y_i + (y_{i+1} - y_i) \frac{x_q - x_i}{x_{i+1} - x_i} ] * 特点: 速度快,结果连续但不可导(不平滑),是很好的通用默认选项。

'nearest' - 最近邻插值

  • 原理: 查询点 \(x_q\) 的插值 \(y_q\) 等于距离它最近的原始数据点 \(x_i\) 的值 \(y_i\)

  • 公式:

    [ y_q = y_i \quad \text{where} \quad |x_q - x_i| \le |x_q - x_j| \quad \forall j ] * 特点: 速度最快,不连续,结果呈阶梯状。适用于快速查找或分类。

'spline' - 三次样条插值

  • 原理: 使用分段三次多项式 \(S_i(x)\) 来连接每对相邻的数据点 \((x_i, y_i)\)\((x_{i+1}, y_{i+1})\)。为了使整条曲线平滑,它强制要求在每个连接点 \(x_i\) 处,函数值、一阶导数和二阶导数都必须连续。

  • 公式: 在区间 \([x_i, x_{i+1}]\) 上,插值函数为:

    \[ S_i(x) = a_i (x-x_i)^3 + b_i (x-x_i)^2 + c_i (x-x_i) + d_i \]

    并通过求解一个线性方程组来确定所有系数,以满足以下条件: 1. \(S_i(x_i) = y_i\) and \(S_i(x_{i+1}) = y_{i+1}\) (穿过数据点) 2. \(S'_{i-1}(x_i) = S'_i(x_i)\) (一阶导数连续) 3. \(S''_{i-1}(x_i) = S''_i(x_i)\) (二阶导数连续) * 特点: 结果非常平滑(C2 连续),但如果原始数据有剧烈波动,可能会产生过冲 (overshoot)。适用于需要平滑导数的场合。

'pchip''makima' - 保形分段三次插值

  • 原理: 这两者都属于分段三次 Hermite 插值。它们同样使用分段三次多项式,但与样条不同,它们只要求函数值和一阶导数连续。其核心在于估算每个数据点上的一阶导数值 \(d_i\),使得多项式能够保持原始数据的单调性形状
    • 'pchip' 使用一种加权平均斜率的方法来估算导数。
    • 'makima' (改进的 Akima 方法) 使用一种更复杂的加权平均,考虑了更多邻近点斜率的变化,通常能产生更平滑且无过冲的曲线。
  • 特点: 不会产生过冲,能很好地保持原始数据的形状。适用于需要保持单调性的数据,如累积分布函数。'makima' 通常比 'pchip' 更平滑。

二维及多维插值

interp2, interp3, interpn - 网格数据插值

  • 功能 分别对二维、三维和 N 维的规则网格数据进行插值。
  • 数学原理 其原理是一维插值的扩展。例如,对于二维线性插值 ('linear'),首先在一个方向(如 x 轴)上进行两次一维线性插值,得到两个中间点,然后再在这两个中间点之间沿另一个方向(y 轴)进行一次一维线性插值,这个过程称为双线性插值
  • 语法
    Vq = interp2(X, Y, V, Xq, Yq, method) % 二维
    Vq = interp3(X, Y, Z, V, Xq, Yq, Zq, method) % 三维
    Vq = interpn(X1, X2,..., Xn, V, Xq1, Xq2,..., Xqn, method) % N维
    
  • 示例 (interp2)
    % 1. 创建粗糙的网格和数据
    [X, Y] = meshgrid(-3:1:3);
    Z = peaks(X, Y);
    
    % 2. 创建更精细的查询网格
    [Xq, Yq] = meshgrid(-3:0.2:3);
    
    % 3. 进行二维插值
    Zq = interp2(X, Y, Z, Xq, Yq, 'cubic'); % 使用三次卷积插值
    
    % 4. 绘图
    figure;
    subplot(1, 2, 1); surf(X, Y, Z); title('原始粗糙网格');
    subplot(1, 2, 2); surf(Xq, Yq, Zq); title('interp2 插值后的平滑曲面');
    

griddedInterpolant - 创建网格插值对象

  • 功能 当需要对同一组网格数据进行多次插值查询时,griddedInterpolant 是最高效的方法。它会预先计算并存储插值所需的系数,后续查询速度极快。
  • 语法
    F = griddedInterpolant(X, Y, V, method)
    Vq = F(Xq, Yq)
    
  • 示例
    [X, Y] = meshgrid(-3:1:3);
    V = peaks(X, Y);
    
    % 1. 创建插值对象
    F = griddedInterpolant(X, Y, V, 'makima');
    
    % 2. 多次查询
    [Xq, Yq] = meshgrid(-3:0.2:3);
    Vq = F(Xq, Yq); % 第一次查询
    V_point = F(0.5, 0.5); % 第二次查询 (查询单个点)
    
    disp(['在 (0.5, 0.5) 处的插值是: ', num2str(V_point)]);
    

scatteredInterpolant - 散乱数据插值

  • 功能 当数据点 (x, y, z, ...) 的位置是不规则的、没有特定网格结构时,使用此函数。
  • 数学原理 scatteredInterpolant 的核心是Delaunay 三角剖分
    1. 三角剖分: 对于二维数据,它首先将所有的散乱数据点连接起来,形成一个由互不重叠的三角形组成的网格。
    2. 插值: 当查询一个新点时,它首先找到包含该点的三角形。然后,根据指定的插值方法在三角形的顶点上进行插值。
      • 'linear': 在三角形定义的平面上进行线性插值。
      • 'nearest': 返回最近的顶点的值。
      • 'natural': 自然邻点插值,使用更广泛的邻域点进行加权平均,结果更平滑。
  • 语法
    F = scatteredInterpolant(x, y, v)
    F = scatteredInterpolant(x, y, v, method)
    vq = F(xq, yq)
    
  • 示例
    % 1. 创建随机分布的散乱数据点
    x = rand(50, 1) * 4 - 2;
    y = rand(50, 1) * 4 - 2;
    v = x .* exp(-x.^2 - y.^2);
    
    % 2. 创建插值对象
    F = scatteredInterpolant(x, y, v, 'natural');
    
    % 3. 定义查询网格
    [Xq, Yq] = meshgrid(-2:0.1:2);
    
    % 4. 使用插值对象进行查询
    Vq = F(Xq, Yq);
    
    % 5. 绘图
    figure;
    surf(Xq, Yq, Vq);
    hold on;
    plot3(x, y, v, 'ro', 'MarkerFaceColor', 'r'); % 叠加原始散乱点
    title('scatteredInterpolant 散乱数据插值');