直线加权拟合改进版
来源:互联网 发布:电子商务软件提供商 编辑:程序博客网 时间:2024/04/28 20:10
直线拟合算法
假设已知一系列点P(xi, yi) (i = 1...N),进行拟合,求出参数a,b
直接拟合公式
y = a*x + b
误差公式:ε = y - a*x - b
目标: J = ∑ (y - a*x -b)^2最小
极值条件:
dJ/da = ∑-2x(y - a*x - b) = 0;
dJ/db = ∑-2(y - ax - b) = 0;
化简:
∑y - a∑x - Nb = 0;
∑xy - a∑x^2 - b*∑x = 0;
代入∑x ∑y ∑xy ∑x^2,求出a b的值即可
加权拟合
未完待续
源码实现:
fitline.h
#ifndef FITLINE_H#define FITLINE_H#include"type.h"#include<cmath>int FitLine2D( Point2D32f * points, int _count, float *weights, float *line );double CalcDist2D( Point2D32f * points, int count, float *_line, float *dist );int FitLine2D(Point2D32f * points, int count, float *line);void WeightL1( float *d, int count, float *w );void WeightL12( float *d, int count, float *w );void WeightHuber( float *d, int count, float *w, float _c );void WeightFair( float *d, int count, float *w, float _c );void WeightWelsch( float *d, int count, float *w, float _c );double max(double a, double b);#endif
fitline.cpp
#include"fitline.h"const double eps = 1e-6;int FitLine2D( Point2D32f * points, int _count, float *weights, float *line ){ double x = 0, y = 0, x2 = 0, y2 = 0, xy = 0, w = 0; double dx2, dy2, dxy; int i; int count = _count; float t; /* Calculating the average of x and y... */ if( weights == 0 ) { for( i = 0; i < count; i += 1 ) { x += points[i].x; y += points[i].y; x2 += points[i].x * points[i].x; y2 += points[i].y * points[i].y; xy += points[i].x * points[i].y; } w = (float) count; } else { for( i = 0; i < count; i += 1 ) { x += weights[i] * points[i].x; y += weights[i] * points[i].y; x2 += weights[i] * points[i].x * points[i].x; y2 += weights[i] * points[i].y * points[i].y; xy += weights[i] * points[i].x * points[i].y; w += weights[i]; } } x /= w; y /= w; x2 /= w; y2 /= w; xy /= w; dx2 = x2 - x * x; dy2 = y2 - y * y; dxy = xy - x * y; t = (float) atan2( 2 * dxy, dx2 - dy2 ) / 2; line[0] = (float) cos( t ); line[1] = (float) sin( t ); line[2] = (float) x; line[3] = (float) y; return 0;}double CalcDist2D( Point2D32f * points, int count, float *_line, float *dist ){ int j; float px = _line[2], py = _line[3]; float nx = _line[1], ny = -_line[0]; double sum_dist = 0.; for( j = 0; j < count; j++ ) { float x, y; x = points[j].x - px; y = points[j].y - py; dist[j] = (float) fabs( nx * x + ny * y ); sum_dist += dist[j]; } return sum_dist;}int FitLine2D(Point2D32f * points, int count, float *line){//进行一遍拟合,获取直线参数FitLine2D(points, count, NULL, line);//计算权值,再进行一次拟合float *dist = new float[count];float *W = new float[count];//迭代进行加权拟合,迭代次数不小于三次for(int i = 0; i < 5; i++){CalcDist2D(points, count, line, dist); WeightL1( dist, count, W);FitLine2D(points, count, W, line);}delete [] dist;}void WeightL1( float *d, int count, float *w ){ int i; for( i = 0; i < count; i++ ) { double t = fabs( (double) d[i] ); w[i] = (float)(1. / max(t, eps)); }}void WeightL12( float *d, int count, float *w ){ int i; for( i = 0; i < count; i++ ) { w[i] = 1.0f / (float) sqrt( 1 + (double) (d[i] * d[i] * 0.5) ); }}void WeightHuber( float *d, int count, float *w, float _c ){ int i; const float c = _c <= 0 ? 1.345f : _c; for( i = 0; i < count; i++ ) { if( d[i] < c ) w[i] = 1.0f; else w[i] = c/d[i]; }}void WeightFair( float *d, int count, float *w, float _c ){ int i; const float c = _c == 0 ? 1 / 1.3998f : 1 / _c; for( i = 0; i < count; i++ ) { w[i] = 1 / (1 + d[i] * c); }}void WeightWelsch( float *d, int count, float *w, float _c ){ int i; const float c = _c == 0 ? 1 / 2.9846f : 1 / _c; for( i = 0; i < count; i++ ) { w[i] = (float) exp( -d[i] * d[i] * c * c ); }}double max(double a, double b){return a > b ? a : b;}
main.cpp
#include"fitline.h"#include<cstdlib>#include<cstdio>#include<ctime>const int COUNT = 50;Point2D32f points[COUNT];float line[4] = {0.0};//存储直线的参数int main(){//产生随机数 srand((unsigned int)time(NULL)); for(int i = 0 ; i < COUNT ; i++) { points[i].x = i; points[i].y = i * 2.3 + 45 + rand()%1000/1024.0; points[COUNT/2].x = 10; points[COUNT/3].y = 200; } //直接拟合 FitLine2D(points, COUNT, NULL, line); float a = line[1]/line[0];float b = line[3] - a*line[2];printf("a: %f b%f\n", a, b); //加权拟合FitLine2D(points, COUNT, line);a = line[1]/line[0];b = line[3] - a*line[2];printf("a: %f b%f\n", a, b);return 0;}
type.h
#include<cstdlib>typedef struct{float x;float y;}Point2D32f;
- 直线加权拟合改进版
- 直线拟合
- 直线拟合
- 直线拟合
- 加权拟合算法
- RANSAC介绍(Matlab版直线拟合+平面拟合)
- 最小二乘法直线拟合、圆拟合
- 最小二乘法直线拟合
- 最小二乘法直线拟合
- 最小二乘法直线拟合
- OpenCV 直线拟合
- 最小二乘法直线拟合
- 最小二乘法直线拟合
- FitLine+直线拟合+C++
- 最小二乘法 直线拟合
- 最小二乘法拟合直线
- OpenCV 直线拟合
- 最小二乘法直线拟合
- C++追加单个字符
- C#条码打印
- 对编程一些新的认识
- MySQL 索引详解
- java jxl解析excel
- 直线加权拟合改进版
- 使用httpclient4上传文件
- The GNU configure and build system
- 黑马程序员_多线程
- ExtJs表单几种验证与扩展
- java如何实现字符串的反转及替换
- 黑马程序员------关于异常
- 0-1背包问题、旅行推销员问题TSP
- note : OD操作整理-修改常量字符串;保存PE文件