最小二乘法拟合直线——MATLAB和Qt-C++实现

本节Jungle用C++实现最小二乘法拟合平面直线

1.理论知识

平面直线的通用方程可以表示为
A+Bx-y=0
其中,A是直线的截距,B是直线的斜率。对于测量的二维坐标(x,y),x是精确分布的,而y是观测值。基于最小二乘的理论,我们要得到观测值的误差的平方和的最小值。我们设定目标函数为:
这里写图片描述
分别对A和B求偏导数,并命其为零,得到以下方程组:
最小二乘法拟合直线——MATLAB和Qt-C++实现_第1张图片
解此方程组,则可以得到A和B。

2.算法实现

2.1MATLAB实现

function [ p ] = Line_Fitting( XY )
N = size(XY,1);
x = XY(:,1);
y = XY(:,2);
X=0.00;
XX=0.00;
Y=0.00;
YY=0.00;
XY=0.00;
for i=1:N
    X=X+x(i);
    XX=XX+x(i)*x(i);
    Y=Y+y(i);
    YY=YY+y(i)*y(i);
    XY=XY+x(i)*y(i);
end

a = (XX*Y-X*XY)/(N*XX-X*X);
b = (N*XY-X*Y)/(N*XX-X*X);

p(1)=a;
p(2)=b;
end

2.2C++和Qt实现

首先定义一个结构体Data,用于存放二维坐标点。(实现时也可用数组、vector等)。因为工程上用到,所以Jungle还加了一点其他函数。

#ifndef DATA
#define DATA
class Data
{
public:
	Data();
	Data(double ix = 0, double iy = 0):x(ix),y(iy){}
	~Data();

	double x;
	double y;
};
#endif //DATA

将上述算法封装为一个类LineFitting:

#ifndef LINEFITTING_H
#define LINEFITTING_H

#include "CircleFitting.h"

class LineFitting
{
public:
	LineFitting(QList iList);
	~LineFitting();

	void fittingData();
	QList getResultList();
	///纵坐标平均值
	double getAve_X();
	double getAve_Y();

private:
	///截距
	double a;
	///斜率
	double b;
	///相关常数
	double r;
	///平均值
	double xa;
	double ya;
	///拟合结果列表
	QList resultList;
	///原始数据集合
	QList PrimiDataSet;
};

#endif //LINEFITTING_H
#include "LineFitting.h"

LineFitting::LineFitting(QList iList)
{
	PrimiDataSet.clear();
	resultList.clear();
	a = 0;
	b = 0;
	r = 0;
	xa = 0;
	ya = 0;
	for(int i=0;iPrimiDataSet<x;
		iy = PrimiDataSet[i]->y;

		X+=ix;
		XX+=ix*ix;
		Y+=iy;
		YY+=iy*iy;
		XY+=ix*iy;
	}
	a = (XX*Y-X*XY)/(N*XX-X*X);
	b = (N*XY-X*Y)/(N*XX-X*X);

	xa = X/N;
	ya = Y/N;
	resultList< LineFitting::getResultList()
{
	return this->resultList;
}

double LineFitting::getAve_Y()
{
	return ya;
}

double LineFitting::getAve_X()
{
	return xa;
}

欢迎关注知乎专栏:Jungle是一个用Qt的工业Robot
欢迎关注Jungle的微信公众号:Jungle笔记
最小二乘法拟合直线——MATLAB和Qt-C++实现_第2张图片

你可能感兴趣的:(数据结构与算法,C++应用)