三次样条插值

Posted guliangt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了三次样条插值相关的知识,希望对你有一定的参考价值。

1.三次样条插值函数

%%三次样条插值
%%bc为boundary conditions(边界条件),当已知两端点的一阶导数值时为-1,当已知两端的二阶导数时为0,当函数为周期函数时为1
%%X为节点值,Y为函数表达式(attribute=0)或者具体值(attribute=1)
function CSI = Cubic_spline_interpolation(X,Y,precision,attribute,bc)
[m,n] = size(X);a = min(X);b = max(X);n = n-1;
X = sort(X);

%%画已知函数或已知点图像
if attribute == 0
    F = subs(Y,X);
    t = a:(b-a)/precision:b;
    Y_real = subs(Y,t);
    pic = figure;
    set(pic,‘color‘,‘w‘);
    plot(X,F,‘r*‘,t,Y_real,‘b‘);
    grid on
    xlabel(‘x shaft‘);ylabel(‘y shaft‘);
    title(‘三次样条插值‘);
    hold on
elseif attribute ==1
    F = Y;
    pic = figure;
    set(pic,‘color‘,‘w‘);
    plot(X,F,‘r*‘);
    grid on
    xlabel(‘x shaft‘);ylabel(‘y shaft‘);
    title(‘三次样条插值‘);
    hold on
end

if bc == -1
    left_endpoint = input(‘输入左端点的一阶导数值:‘);
    right_endpoint = input(‘输入右端点的一阶导数值:‘);
    for i = 1:n
        X_one_interval{i} = [X(i),X(i+1)];%%节点构造区间
        F_one_interval{i} = [F(i),F(i+1)];%%构造节点值区间
        F_all_bad(i) = The_first_order_All_bad(F_one_interval{i},X_one_interval{i},attribute);%%节点区间的一阶均差
        h(i) = X(i+1)-X(i);
    end
    %%样条插值算法
    for i = 1:n-1
        mu(i) = h(i)/(h(i)+h(i+1));
    end
    mu(n) = 1;
    lambda(1) = 1;
    for i = 2:n
        lambda(i) = h(i)/(h(i-1)+h(i));
    end
    d(1)=6*(F_all_bad(1)-left_endpoint)/h(1);
    for i = 2:n
        d(i) = 6*(F_all_bad(i)-F_all_bad(i-1))/(h(i-1)+h(i));
    end
    d(n+1) = 6*(right_endpoint-F_all_bad(n))/h(n);
    A = zeros(n+1,n+1);
    for i = 1:n+1
        for j = 1:n+1
            if i == j
                A(i,j) = 2;
            elseif (i-j) == 1
                A(i,j) = mu(j);
            elseif (j-i) == 1
                A(i,j) = lambda(i);
            end
        end
    end
    %%解样条算法中的线性方程组得出解
    disp(‘样条函数初始系数:‘);
    M = vpa((Ad‘)‘,6)
    %%输出节点区间及对应的样条函数
    syms x;
    for i = 1:n
        CSI{1,i} = X_one_interval{i};
        CSI{2,i} = vpa((X(i+1)-x)^3*M(i)/(6*h(i))+(x-X(i))^3*M(i+1)/(6*h(i))+(F(i)-M(i)*h(i)^2/6)*(X(i+1)-x)/h(i)+(F(i+1)-M(i+1)*h(i)^2/6)*(x-X(i))/h(i),5);
    end
    %%画样条函数的图像
    for i = 1:n
        t_pic{i} = X(i):(X(i+1)-X(i))/precision:X(i+1);
        T_pic{i} = subs(CSI{2,i},t_pic{i});
    end
    for i = 1:n
        t_Pic(1+(precision+1)*(i-1):(precision+1)*i) = t_pic{i};
        T_Pic(1+(precision+1)*(i-1):(precision+1)*i) = T_pic{i};
    end
    plot(t_Pic,T_Pic,‘g‘);
    
    if attribute ==0
        legend(‘F:数据点‘,‘Y_real:真实图像‘,‘T_Pic:样条插值拟合函数‘);
    elseif attribute == 1
        legend(‘F:数据点‘,‘T_Pic:样条插值拟合函数‘);
    end
elseif bc == 0
    left_endpoint = input(‘输入左端点的二阶导数值:‘);
    right_endpoint = input(‘输入右端点的二阶导数值:‘);
    for i = 1:n
        X_one_interval{i} = [X(i),X(i+1)];
        F_one_interval{i} = [F(i),F(i+1)];
        F_all_bad(i) = The_first_order_All_bad(F_one_interval{i},X_one_interval{i},attribute);
        h(i) = X(i+1)-X(i);
    end
    for i = 1:n-1
        mu(i) = h(i)/(h(i)+h(i+1));
    end
    mu(n) = 0;
    lambda(1) = 0;
    for i = 2:n
        lambda(i) = h(i)/(h(i-1)+h(i));
    end
    d(1)=2*left_endpoint;
    for i = 2:n
        d(i) = 6*(F_all_bad(i)-F_all_bad(i-1))/(h(i-1)+h(i));
    end
    d(n+1) = 2*right_endpoint;
    A = zeros(n+1,n+1);
    for i = 1:n+1
        for j = 1:n+1
            if i == j
                A(i,j) = 2;
            elseif (i-j) == 1
                A(i,j) = mu(j);
            elseif (j-i) == 1
                A(i,j) = lambda(i);
            end
        end
    end
    disp(‘样条函数初始系数:‘);
    M = vpa((Ad‘)‘,6)
    syms x;
    for i = 1:n
        CSI{1,i} = X_one_interval{i};
        CSI{2,i} = vpa((X(i+1)-x)^3*M(i)/(6*h(i))+(x-X(i))^3*M(i+1)/(6*h(i))+(F(i)-M(i)*h(i)^2/6)*(X(i+1)-x)/h(i)+(F(i+1)-M(i+1)*h(i)^2/6)*(x-X(i))/h(i),5);
    end
    for i = 1:n
        t_pic{i} = X(i):(X(i+1)-X(i))/precision:X(i+1);
        T_pic{i} = subs(CSI{2,i},t_pic{i});
    end
    for i = 1:n
        t_Pic(1+(precision+1)*(i-1):(precision+1)*i) = t_pic{i};
        T_Pic(1+(precision+1)*(i-1):(precision+1)*i) = T_pic{i};
    end
    plot(t_Pic,T_Pic,‘g‘);
    if attribute ==0
        legend(‘F:数据点‘,‘Y_real:真实图像‘,‘T_Pic:样条插值拟合函数‘);
    elseif attribute == 1
        legend(‘F:数据点‘,‘T_Pic:样条插值拟合函数‘);
    end
end
end

  2.一阶均差函数

%%一阶均差
function FAb = The_first_order_All_bad(f,X,attribute)
[m,n] = size(X);
if attribute == 0
    F = subs(f,X);
    FAb = (F(n)-F(1))/(X(n)-X(1));
elseif attribute == 1
    FAb = (f(n)-f(1))/(X(n)-X(1));
end
end

  3.样条插值拟合值函数

%%三次样条插值拟合值
%%用法同三次样条函数
function CSIV = Cubic_spline_interpolation_value(X,Y,precision,attribute,bc,x_value)
[m,n] = size(X);a = min(X);b = max(X);n = n-1;
X = sort(X);
if attribute == 0
    F = subs(Y,X);
elseif attribute ==1
    F = Y;
end
if bc == -1
    left_endpoint = input(‘输入左端点的一阶导数值:‘);
    right_endpoint = input(‘输入右端点的一阶导数值:‘);
    for i = 1:n
        X_one_interval{i} = [X(i),X(i+1)];
        F_one_interval{i} = [F(i),F(i+1)];
        F_all_bad(i) = The_first_order_All_bad(F_one_interval{i},X_one_interval{i},attribute);
        h(i) = X(i+1)-X(i);
    end
    for i = 1:n-1
        mu(i) = h(i)/(h(i)+h(i+1));
    end
    mu(n) = 1;
    lambda(1) = 1;
    for i = 2:n
        lambda(i) = h(i)/(h(i-1)+h(i));
    end
    d(1)=6*(F_all_bad(1)-left_endpoint)/h(1);
    for i = 2:n
        d(i) = 6*(F_all_bad(i)-F_all_bad(i-1))/(h(i-1)+h(i));
    end
    d(n+1) = 6*(right_endpoint-F_all_bad(n))/h(n);
    A = zeros(n+1,n+1);
    for i = 1:n+1
        for j = 1:n+1
            if i == j
                A(i,j) = 2;
            elseif (i-j) == 1
                A(i,j) = mu(j);
            elseif (j-i) == 1
                A(i,j) = lambda(i);
            end
        end
    end
    M = (Ad‘)‘;
    syms x;
    for i = 1:n
        S{1,i} = X_one_interval{i};
        S{2,i} = vpa((X(i+1)-x)^3*M(i)/(6*h(i))+(x-X(i))^3*M(i+1)/(6*h(i))+(F(i)-M(i)*h(i)^2/6)*(X(i+1)-x)/h(i)+(F(i+1)-M(i+1)*h(i)^2/6)*(x-X(i))/h(i),5);
    end
    for i =1:n
        if x_value >= X(i) && x_value <= X(i+1);
            s = i;
        end
    end
    CSIV{1,1} = ‘拟合值‘;
    CSIV{2,1} = vpa(subs(S{2,s},x_value),4);
    CSIV{1,2} = ‘实际值‘;
    CSIV{2,2} = vpa(subs(Y,x_value),4);
    CSIV{1,3} = ‘误差‘;
    CSIV{2,3} = abs(CSIV{2,1}-CSIV{2,2});
    
elseif bc == 0
    left_endpoint = input(‘输入左端点的二阶导数值:‘);
    right_endpoint = input(‘输入右端点的二阶导数值:‘);
    for i = 1:n
        X_one_interval{i} = [X(i),X(i+1)];
        F_one_interval{i} = [F(i),F(i+1)];
        F_all_bad(i) = The_first_order_All_bad(F_one_interval{i},X_one_interval{i},attribute);
        h(i) = X(i+1)-X(i);
    end
    for i = 1:n-1
        mu(i) = h(i)/(h(i)+h(i+1));
    end
    mu(n) = 0;
    lambda(1) = 0;
    for i = 2:n
        lambda(i) = h(i)/(h(i-1)+h(i));
    end
    d(1)=2*left_endpoint;
    for i = 2:n
        d(i) = 6*(F_all_bad(i)-F_all_bad(i-1))/(h(i-1)+h(i));
    end
    d(n+1) = 2*right_endpoint;
    A = zeros(n+1,n+1);
    for i = 1:n+1
        for j = 1:n+1
            if i == j
                A(i,j) = 2;
            elseif (i-j) == 1
                A(i,j) = mu(j);
            elseif (j-i) == 1
                A(i,j) = lambda(i);
            end
        end
    end
    M = (Ad‘)‘;
    syms x;
    for i = 1:n
        S{1,i} = X_one_interval{i};
        S{2,i} = vpa((X(i+1)-x)^3*M(i)/(6*h(i))+(x-X(i))^3*M(i+1)/(6*h(i))+(F(i)-M(i)*h(i)^2/6)*(X(i+1)-x)/h(i)+(F(i+1)-M(i+1)*h(i)^2/6)*(x-X(i))/h(i),5);
    end
    CSIV{1,1} = ‘拟合值‘;
    CSIV{2,1} = vpa(subs(S{2,s},x_value),4);
end

  4.例子

clear all
clc
syms x;
Y=sin(x)/(1+x^2)+exp(-x^2);
X=-5:1:5;
precision=500;
attribute=0;
bc=-1;

%%三次样条插值
Cubic_spline_interpolation(X,Y,precision,attribute,bc)

  结果为

输入左端点的一阶导数值:subs(diff(Y),-5)
输入右端点的一阶导数值:subs(diff(Y),5)
样条函数初始系数:
M =
[ -0.0869325, 0.0232929, -0.00623918, 0.00166378, -0.000415945, 1.32899e-12, 0.000415945, -0.00166378, 0.00623918, -0.0232929, 0.0869325]
S =
  2×10 cell 数组
  列 1 至 4
    {1×2 double}    {1×2 double}    {1×2 double}    {1×2 double}
    {1×1 sym   }    {1×1 sym   }    {1×1 sym   }    {1×1 sym   }
  列 5 至 8
    {1×2 double}    {1×2 double}    {1×2 double}    {1×2 double}
    {1×1 sym   }    {1×1 sym   }    {1×1 sym   }    {1×1 sym   }
  列 9 至 10
    {1×2 double}    {1×2 double}
    {1×1 sym   }    {1×1 sym   }
>> S{2,:}
ans =
0.014489*(x + 4.0)^3 - 0.010735*x + 0.0038822*(x + 5.0)^3 - 0.0023031
ans =
- 0.053584*x - 0.0010399*(x + 4.0)^3 - 0.0038822*(x + 3.0)^3 - 0.1737
ans =
0.0010399*(x + 2.0)^3 - 0.15087*x + 0.0002773*(x + 3.0)^3 - 0.46557
ans =
0.11103*x - 0.0002773*(x + 1.0)^3 - 0.000069324*(x + 2.0)^3 + 0.058248
ans =
1.0528*x + 2.215e-13*(x + 1.0)^3 + 0.000069324*x^3 + 1.0
ans =
0.000069324*x^3 - 2.215e-13*(x - 1.0)^3 - 0.21145*x + 1.0
ans =
1.3766 - 0.0002773*(x - 1.0)^3 - 0.000069324*(x - 2.0)^3 - 0.58809*x
ans =
0.0010399*(x - 2.0)^3 - 0.18726*x + 0.0002773*(x - 3.0)^3 + 0.57497
ans =
0.17469 - 0.0010399*(x - 4.0)^3 - 0.0038822*(x - 3.0)^3 - 0.053831*x
ans =
0.014489*(x - 4.0)^3 - 0.010735*x + 0.0038822*(x - 5.0)^3 + 0.0023042
>> 

  函数图像为

技术图片

以上是关于三次样条插值的主要内容,如果未能解决你的问题,请参考以下文章

三次样条插值介绍

三次样条插值

如何使用 CuPy 在 python 上进行三次样条插值?

三次样条插值

如何通过python实现三次样条插值

Spline(三次样条插值)