拉格朗日插值编程实现

拉格朗日插值原理:

拉格朗日插值的具体介绍网址:https://zh.wikipedia.org/wiki/%E6%8B%89%E6%A0%BC%E6%9C%97%E6%97%A5%E6%8F%92%E5%80%BC%E6%B3%95

翻译成人话就是,该曲线是由多个n次多项式的和构成的,n是参与插值的点的个数。每个n次多项式的计算方法如上图所示。转化成程序的话,就是要保存每个多项式中(x-xi)中的每一项xi。然后就是系数yi/(xj-x0)(xj-x1)...(xj-xk)

程序实现:

 

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;

template<class T>
struct Point
{
    T x;
    T y;
    
    Point()
    {x=0;y=0;}
    
    Point(T a,T b)
    {x=a;y=b;}
    
    Point operator+(Point p)
    {return Point(x+p.x,y+p.y);}
};
/*
 拉格朗日曲线,包含多个拉格朗日多项式和曲线的x坐标最大最小值
 */
struct LagrangeCurve
{
    vector<double>factor;
    vector<double>minuend;
    int minX;
    int maxX;
};

void calLagrangePolynomial(LagrangeCurve&curve,Point<int>*curvePoints,int pointNum)
{
    int i,j;
    curve.maxX=curvePoints[0].x;
    curve.minX=curvePoints[0].x;
    for(i=0;i<pointNum;++i)
    {
        curve.minuend.push_back(curvePoints[i].x);
        curve.factor.push_back(curvePoints[i].y);
        //获取曲线两端的x值
        if(curvePoints[i].x<curve.minX)
            curve.minX=curvePoints[i].x;
        if(curvePoints[i].x>curve.maxX)
            curve.maxX=curvePoints[i].x;
        //计算(xi-x0)*...(xi-x5),并且把x0...x5保存
        for(j=0;j<pointNum;++j)
        {
            if(j!=i)
            {curve.factor[i]/=(curvePoints[i].x-curvePoints[j].x+1e-8);}
        }
    }
}

double getInterpolation(int x,LagrangeCurve& lagrangeCurve)
{
    int i,j;
    double y=0;
    for(i=0;i<lagrangeCurve.minuend.size();++i)
    {
        double temp=lagrangeCurve.factor[i];
        for(j=0;j<lagrangeCurve.minuend.size();++j)
        {
            if(j!=i)
            {temp*=(x-lagrangeCurve.minuend[j]);}
        }
        y+=temp;
    }
    return y;
}


int main(int argc, const char * argv[])
{
    Mat img(256,256,CV_8UC3);
    img=Scalar::all(255);
    Point<int>*points=new Point<int>[3];
    points[0].x=10;points[0].y=30;
    points[1].x=100;points[1].y=70;;
    points[2].x=250;points[2].y=210;
    
    circle(img, cvPoint(points[0].x,points[0].y),5,Scalar::all(0),-1);
    circle(img, cvPoint(points[1].x,points[1].y),5,Scalar::all(0),-1);
    circle(img, cvPoint(points[2].x,points[2].y),5,Scalar::all(0),-1);
    
    LagrangeCurve lagrangeCurve;
    calLagrangePolynomial(lagrangeCurve,points,3);
    for(int i=lagrangeCurve.minX;i<lagrangeCurve.maxX;++i)
    {
        double y=getInterpolation(i,lagrangeCurve);
        img.at<Vec3b>(static_cast<int>(y+0.5),i)=Vec3b(0,0,0);
    }
    imshow("img", img);
    waitKey(-1);
    return 0;
}

 

上述代码使用到了opencv画图,运行结果图如下:

 

posted @ 2015-12-11 15:29  handspeaker  阅读(5283)  评论(0编辑  收藏  举报