# OpenCV 直线拟合及应用

OpenCV提供了7种（-1为用户定义）直线拟合方法，如下：

```CV_DIST_USER    =-1,  /* User defined distance */
CV_DIST_L1      =1,   /* distance = |x1-x2| + |y1-y2| */
CV_DIST_L2      =2,   /* the simple euclidean distance */
CV_DIST_C       =3,   /* distance = max(|x1-x2|,|y1-y2|) */
CV_DIST_L12     =4,   /* L1-L2 metric: distance = 2(sqrt(1+x*x/2) - 1)) */
CV_DIST_FAIR    =5,   /* distance = c^2(|x|/c-log(1+|x|/c)), c = 1.3998 */
CV_DIST_WELSCH  =6,   /* distance = c^2/2(1-exp(-(x/c)^2)), c = 2.9846 */
CV_DIST_HUBER   =7    /* distance = |x|<c ? x^2/2 : c(|x|-c/2), c=1.345 */```

OpenCV直线拟合函数：

```CV_EXPORTS_W void fitLine(
InputArray points,
OutputArray line,
int distType,
double param,
double reps,
double aeps );```

points为2D的点： distType即为上面提到的算法； param 是 上述公式中的常数C。如果取 0，则程序自动选取合适的值； reps 表示直线到原点距离的精度，建议取 0.01； aeps 表示直线角度的精度，建议取 0.01； 拟合结果即为函数的输出 line，为`Vec4f`类型，line[0]、line[1] 存放的是直线的方向向量。line[2]、line[3] 存放的是直线上一个点的坐标。 所以 ，直线的斜率即为：line[1]/line[0]。

```#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>

#define  PI 3.141592653

using namespace cv;
using namespace std;

int main()
{
Mat SrcImage, thresholdImage,grayImage;
cvtColor(SrcImage,grayImage,CV_BGR2GRAY);
threshold(grayImage,thresholdImage, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY);
imshow("threshold",thresholdImage);
vector<Point2f> onefitlinepoints,twofitlinepoints;
//从上自下选择点
for (int i =SrcImage.cols/2-SrcImage.cols/5;i<SrcImage.cols/2+SrcImage.cols/5;i++)
{ for (int j=0;j<SrcImage.rows-1;j++)
{if ((int)thresholdImage.at<uchar>(j,i)==255)
{  circle(thresholdImage,Point(i,j),2,Scalar(0,255,0));
onefitlinepoints.push_back(Point(i,j));
break;
}}}
//从下自上选择点
for (int k =SrcImage.cols/2-SrcImage.cols/5;k<SrcImage.cols/2+SrcImage.cols/5;k++)
{  for (int l=SrcImage.rows-1;l>0;l--)
{if ((int)thresholdImage.at<uchar>(l,k)==255)
{ circle(thresholdImage,Point(k,l),2,Scalar(0,255,0));
twofitlinepoints.push_back(Point(k,l));
break;
}}}
//计算第一次拟合角度
Vec4f oneline;
fitLine(onefitlinepoints, oneline, CV_DIST_L1, 0, 0.01, 0.01);
cout<<oneline[0]<<endl;
cout<<oneline[1]<<endl;
//求角度
cout<<"直线拟合角度="<<onefitlineangle<<endl;

//计算第二次拟合角度
Vec4f twoline;
fitLine(twofitlinepoints, twoline, CV_DIST_L1, 0, 0.01, 0.01);
cout<<twoline[0]<<endl;
cout<<twoline[1]<<endl;
//求角度
cout<<"直线拟合角度="<<twofitlineangle<<endl;

double averagefitlineangle = (onefitlineangle+twofitlineangle)/2;
cout<<"直线拟合平均角度="<<averagefitlineangle<<endl;

//画出直线
Point2f point1,point2,point3;
point2.x = oneline[2];
point2.y = oneline[3];

point1.x = 0;
point1.y = oneline[1]*(point1.x-oneline[2])/oneline[0]+oneline[3];

point3.x = SrcImage.cols;
point3.y = oneline[1]*(point3.x-oneline[2])/oneline[0]+oneline[3];

line(SrcImage,point1,point3,Scalar(0,0,255));

imshow("直线拟合",SrcImage);
waitKey(0);
getchar();
return 0;
}```

0 条评论

• ### 目标检测(object detection)系列（十） FPN：用特征金字塔引入多尺度

SSD算法证明了多层分支对于目标检测的有效性，在此之前two-stage的目标检测方法已经优化改进过很多代，但是一直没有加入多尺度的方法。终于在FPN中，two...

• ### 算法-斐波那契数列

题目： 写一个函数，输入为n，求斐波那契（Fibonacci）数列的第n项。斐波那契数列定义如下： ? 解题思路： 斐波那契问题是个非常经典的递归...

• ### Windows系统配置TensorFlow教程

我为什么选择Windows系统： 其实我们没有必要过多纠结与到底使用Linux系统还是Windows系统来学习TensorFlow，因为不管是那个系统我们关...

• ### vue-cli工程 中组件注册 ，父组件向子组件传值

<!-- 使用子组件 -->     <!-- 向子组件传值 需要在父组件中使用v-bind绑定一个名字 :outdata="arr" 其中outda...

• ### Vue学习笔记之Vue组件

vue的核心基础就是组件的使用，玩好了组件才能将前面学的基础更好的运用起来。组件的使用更使我们的项目解耦合。更加符合vue的设计思想MVVM。

• ### Oracle 12c数据库优化器统计信息收集的最佳实践（二）

原文链接 http://www.oracle.com/technetwork/database/bi-datawarehousing/twp-bp-for-st...

• ### cordova插件-Device Motion

添加插件 \$ cordova plugin addcordova-plugin-device-motion ? 图 12如上则插入成功 插件的使用 Me...

• ### [PHP] 读取大文件并显示

使用PHP读取日志文件，当文件比较大的时候，会报内存不足，因此应该部分读取，读取指定的行数的数据

• ### js数组去重五种方法

今天来聊一聊JS数组去重的一些方法，包括一些网上看到的和自己总结的，总共5种方法（ES5）。

• ### 程序员面试金典 - 面试题 17.14. 最小K个数（快排划分O(n)）

来源：力扣（LeetCode） 链接：https://leetcode-cn.com/problems/smallest-k-lcci 著作权归领扣网络所有...