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;
    SrcImage = imread("2.jpg");
    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;
    //求角度
     double  onefitlineradian =  atan(oneline[1]/oneline[0]);
     double  onefitlineangle = (onefitlineradian*180)/CV_PI;
     cout<<"直线拟合角度="<<onefitlineangle<<endl;

    //计算第二次拟合角度
    Vec4f twoline;
    fitLine(twofitlinepoints, twoline, CV_DIST_L1, 0, 0.01, 0.01);
    cout<<twoline[0]<<endl;
    cout<<twoline[1]<<endl;
    //求角度
    double  twofitlineradian =  atan(twoline[1]/twoline[0]);
    double  twofitlineangle = (twofitlineradian*180)/CV_PI;
    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 条评论
登录 后参与评论

相关文章

来自专栏CreateAMind

大量完整的强化学习内容

1105
来自专栏专知

【论文推荐】最新八篇网络节点表示相关论文—可扩展嵌入、对抗自编码器、图划分、异构信息、显式矩阵分解、深度高斯、图、随机游走

【导读】专知内容组整理了最近八篇网络节点表示(Network Embedding)相关文章,为大家进行介绍,欢迎查看! 1.SIGNet: Scalable E...

4306
来自专栏数据科学与人工智能

【Python环境】scikit-learn的线性回归模型

内容概要 如何使用pandas读入数据 如何使用seaborn进行数据的可视化 scikit-learn的线性回归模型和使用方法 线性回归模型的评估测度 特征选...

2078
来自专栏AIUAI

Caffe2 - (三十) Detectron 之 modeling - 模型_heads

3897
来自专栏专知

SIGIR 2018 信息检索领域顶级学术会议接受论文列表

3243
来自专栏贾志刚-OpenCV学堂

OpenCV实现照片自动红眼去除

OpenCV实现照片自动红眼去除 使用闪光照相机拍照,在光线条件不足的情况,如果眼睛盯着相机镜头很容易造成拍出的照片中人眼球变成红色,虽然现在相机从系统和镜头上...

2626
来自专栏小鹏的专栏

kinect v2.0原理介绍之十一:录制视频

不小心误删了,再加上。 ~~有兴趣的小伙伴,加kinect算法交流群:462964980。 录制视频是结合openCV来做的。  代码如下: // 19...

1979
来自专栏数据魔术师

干货|迭代局部搜索算法(Iterated local search)探幽(附C++代码及注释)

2594
来自专栏新智元

ICLR 2017深度学习(提交)论文汇总:NLP、无监督学习、自动编码、RL、RNN(150论文下载)

【新智元导读】ICLR 2017 将于2017年4月24日至26日在法国土伦(toulon)举行,11月4日已经停止接收论文。本文汇总了本年度NLP、无监督学习...

39310
来自专栏机器学习算法与理论

基于landmark的疲劳检测

        经查阅相关文献,疲劳在人体面部表情中表现出大致三个类型:打哈欠(嘴巴张大且相对较长时间保持这一状态)、眨眼(或眼睛微闭,此时眨眼次数增多,且眨眼...

2875

扫码关注云+社区