直线拟合算法

在计算机视觉的应用中,经常会用到提取一条直线的精确位置这样的工作。这时就要用到直线的拟合算法了。

这里,我也贴一个利用最小二乘法计算最佳拟合直线的代码。

这个代码是我以前学习《机器视觉算法与应用(双语版)》[德] 斯蒂格(Steger C) 著;杨少荣 等 译 的书时写的。所有的公式推导都在书中 3.8.1 ,还算比较有用。

与一元线性回归算法的区别:一元线性回归算法假定 X 是无误差的,只有 Y 有误差。 而这个算法假设每个点的 X Y 坐标的误差都是符合 0 均值的正态分布的。 因此,在计算机视觉的应用中比普通的一元线性回归拟合的结果要好。

#include <QVector>
#include <QPoint>
#include <math.h>

/// 本代码用到了 Qt5 中的 QVector 和 QPoint。但是可以很容易的改为其他数组类型。

/**
  * 最小二乘法直线拟合(不是常见的一元线性回归算法)
  * 将离散点拟合为  a x + b y + c = 0 型直线
  * 假设每个点的 X Y 坐标的误差都是符合 0 均值的正态分布的。
  * 与一元线性回归算法的区别:一元线性回归算法假定 X 是无误差的,只有 Y 有误差。
  */
bool lineFit(const QVector<QPoint> &points, double &a, double &b, double &c)
{
     int size = points.size();
     if(size < 2)
     {
         a = 0;
         b = 0;
         c = 0;
         return false;
     }
     double x_mean = 0;
     double y_mean = 0;
     for(int i = 0; i < size; i++)
     {
         x_mean += points[i].x();
         y_mean += points[i].y();
     }
     x_mean /= size;
     y_mean /= size; //至此,计算出了 x y 的均值

     double Dxx = 0, Dxy = 0, Dyy = 0;

     for(int i = 0; i < size; i++)
     {
         Dxx += (points[i].x() - x_mean) * (points[i].x() - x_mean);
         Dxy += (points[i].x() - x_mean) * (points[i].y() - y_mean);
         Dyy += (points[i].y() - y_mean) * (points[i].y() - y_mean);
     }
     double lambda = ( (Dxx + Dyy) - sqrt( (Dxx - Dyy) * (Dxx - Dyy) + 4 * Dxy * Dxy) ) / 2.0;
     double den = sqrt( Dxy * Dxy + (lambda - Dxx) * (lambda - Dxx) );
     a = Dxy / den;
     b = (lambda - Dxx) / den;
     c = - a * x_mean - b * y_mean;
     return true;
} 
时间: 2024-08-24 14:53:04

直线拟合算法的相关文章

直线拟合算法(续)

直线拟合算法(续) 曾经写过一篇博客.介绍直线拟合算法. http://blog.csdn.net/liyuanbhu/article/details/50866802 给出的代码事实上有一点小问题,就是 den = 0 时会出现除以 0 的错误. 今天正好也有网友问起这个问题. 我就再写一篇短文来说说怎样解决问题. 首先我们知道: den=D2xy+(λ?Dxx)2??????????????√ 那么 den=0 意味着: Dxy=0λ=Dxx 我们还有关于 λ 的计算式: λ=Dxx+Dyy

ax+by+c=0 型直线拟合算法

所谓直线拟合,通常也叫做线性拟合.一元线性回归.指的是当我们有一批数据(xi,yi),这些数据在平面坐标系下落在一条直线上,或近似的落在一条直线上.我们就要求出这条直线的参数.如果这条直线可以写为: y=kx+b 那么 k=∑(xi?xˉ)(yi?yˉ)∑(xi?xˉ)2 b=yˉ?kxˉ 这个关系式许多教科书上都有详细的推导,无需多说. 今天要说的是另一种情况,当我们的数据有可能落在一条竖直的直线上,也就是k 有可能为∞ 时,应该如何做拟合.这时我们肯定就不能用y=kx+b 了,但是可以将这个

OpenCV 学习(直线拟合)

OpenCV 学习(直线拟合) Hough 变换可以提取图像中的直线.但是提取的直线的精度不高.而很多场合下,我们需要精确的估计直线的参数,这时就需要进行直线拟合. 直线拟合的方法很多,比如一元线性回归就是一种最简单的直线拟合方法.但是这种方法不适合用于提取图像中的直线.因为这种算法假设每个数据点的X 坐标是准确的,Y 坐标是带有高斯噪声的.可实际上,图像中的每个数据点的XY 坐标都是带有噪声的. 下面就来讲讲适用于提取图像中直线的直线拟合算法. 一个点 (xi,yi) 到直线的距离用 ri 来

OpenCV fitline直线拟合函数学习

下图是OpenCV官方文档中,对直线拟合函数的详细介绍: fitLine()函数用于,对二维或三维空间中的点集进行直线拟合.共有六个参数: param 1:输入的点集,可以是Mat或者vector<>,可以是二维点集或三维点集. 例如: vector<Point> points; param 2:拟合结果,即一条直线.在二维空间中,直线可以定义为 Vec4f line; 在二维平面中,(line[0],line[1])表示直线的方向向量,(line[2],line[3])表示直线上

清华版CG 实验2 直线生成算法实现

1.实验目的: 理解基本图形元素光栅化的基本原理,掌握一种基本图形元素光栅化算法,利用OpenGL实现直线光栅化的DDA算法. 2.实验内容: (1) 根据所给的直线光栅化的示范源程序,在计算机上编译运行,输出正确结果: (2) 指出示范程序采用的算法,以此为基础将其改造为中点线算法或Bresenham算法,写入实验报告: (3) 根据示范代码,将其改造为圆的光栅化算法,写入实验报告: (4) 了解和使用OpenGL的生成直线的命令,来验证程序运行结果. 3.实验原理: 示范代码原理参见教材直线

基于EM的多直线拟合实现及思考

作者:桂. 时间:2017-03-22  06:13:50 链接:http://www.cnblogs.com/xingshansi/p/6597796.html 声明:欢迎被转载,不过记得注明出处哦~ 前言 分布拟合与曲线拟合系列本想简单梳理,却啰嗦的没完没了.本文主要介绍:多直线的拟合,多曲线可以依次类推.全文主要包括: 1)背景介绍 2)理论推导 3)代码实现 4)关于拟合的思考 内容多有借鉴他人,最后一并附上链接. 一.背景介绍 对于单个直线,可以借助MLE或者最小二乘进行求参,对于多条

[计算机图形学] 基于C#窗口的Bresenham直线扫描算法、种子填充法、扫描线填充法模拟软件设计(一)

一.首先说明: 这是啥? —— 这是利用C#FORM写的一个用来演示计算机图形学中 ①Bresenham直线扫描算法(即:连点成线):②种子填充法(即:填充多边形):③扫描线填充法 有啥用? ——  无论是连点成线还是区域填充在高级编程中基本上都提供很高效的库函数来调用.这里拿出这些算法一方面有利于大家理解那些封装的函数底层是实现:另一方面是方便嵌入式TFT屏幕底层驱动开发时借鉴的. 是啥样? ——  如下面的操作,不言而喻. 二.进入正题: 2-1.直线的扫描转换 图形的扫描转换实质就是在光栅

霍夫直线检测算法进行树干提取

霍夫直线检测算法进行树干提取 霍夫直线检测是常用的直线检测算法,原理比较简单. 我叙述一下我对霍夫直线检测算法的理解:将像素点在图像中的二维坐标,通过坐标变换转化为极坐标,然后通过比较每个点在极坐标下的角度值,如果角度值相同,则判定为同直线. 该算法有几个可调参数: C++: void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLe

opengl实现直线扫描算法和区域填充算法

总体介绍 1.   使用线性扫描算法画一条线,线性离散点 2.   利用区域填充算法画多边形区域,区域离散的点 开发环境VS2012+OpenGL 开发平台 Intel core i5,Intel HD Graphics Family 设计思路 一.直线扫描算法 1.数值微分法(DDA) 已知过端点P0 (x0, y0), P1(x1, y1)的直线段L:y = kx + b,easy得知直线斜率为:k = (y1-y0)/(x1-x0).(如果x1≠x0). 我们如果|k|≤1,这样x每添加1