【blog算法原理】Opencv中直线的表示方法

 一、问题的提出:       

  在实际项目编写过程中,需要对直线(Line)进行特定的处理。在以前的项目设计实现中,直线(Line)多是用来绘图使用的,而不是用来进行分析的。

  经过较为仔细地研究Opencv提供的相关内容,感觉这个问题很有搞头,所以分离出来研究。先看refman

opencv条纹结构光 opencv 直线_Line

 

opencv条纹结构光 opencv 直线_编写代码_02

opencv条纹结构光 opencv 直线_编写代码_03

 

 

 

 

可以看到,opencv自己提供的3种直线寻找的函数,最后得到的表示line的数据结构和表示内容的表示都是不一样的。出现这个原因,可能是因为编写这几个函数的不是一个开发者;也可能是认为地选择了最适合特定函数使用的数据结构。那么这3个函数效果到底怎么样?如何灵活使用到自己的项目中?最后我将提出结合自己实际编写的函数。

 

二、函数测试

由于后2个函数都能够直接以图像(MAT)作为参数,所以用一副标准图像进行测试;而后针对Linefit能够以点集作为输入的情况单独测试(如果要使用同样的图像需要先细化再找边缘,比较麻烦),并且提出自己编写的方法。

测试图像为

opencv条纹结构光 opencv 直线_opencv条纹结构光_04

编写代码

# 
     include       "stdafx.h"      
#      include       <iostream      >      
#      include       "opencv2/core/core.hpp"      
#      include       "opencv2/highgui/highgui.hpp"      
#      include       "opencv2/imgproc/imgproc.hpp"      
      //【blog算法原理】Opencv中直线的表示方法      
      // jsxyhelu 2016年1月20日      
using       namespace std;      
using       namespace cv;      
void main()      
{      
    Mat    src;      
    Mat board;      //用于将识别出来直线绘制出来      
    Mat board2;      
    vector      <Vec4i      > lines;      
    vector      <Vec2f      > linesf;      
          ///主要流程///      
    src       = imread(      "PureLine.jpg",      0); 
     
    board       = Mat      :      :zeros(src.size(),src.type()); 
     
    board2       = Mat      :      :zeros(src.size(),src.type()); 
     
          HoughLineP测试      
    HoughLinesP(src, lines,       1, CV_PI      /      180,  
     50,  
     50,  
     10 ); 
     
          HoughLine测试      
    HoughLines(src, linesf,       1, CV_PI      /      180,  
     100,  
     0,  
     0 ); 
     
          ///显示结果///      
          for( size_t i       =       0; i       < lines.size(); i 
     ++ ){ 
     
        Vec4i l       = lines[i];      
        line( board, Point(l[      0], l[      1]), Point(l[      2], l[ 
     3]), Scalar( 
     255),  
     1, CV_AA); 
     
    }      
          for( size_t i       =       0; i       < linesf.size(); i 
     ++ ){ 
     
              float rho       = linesf[i][      0], theta       = lines[i][ 
     1]; 
     
        Point pt1, pt2;      
              double a       = cos(theta), b       = sin(theta);      
              double x0       = a      *rho, y0       = b 
     *rho; 
     
        pt1.x       = cvRound(x0       +       1000 
     *( 
     -b)); 
     
        pt1.y       = cvRound(y0       +       1000 
     *(a)); 
     
        pt2.x       = cvRound(x0       -       1000 
     *( 
     -b)); 
     
        pt2.y       = cvRound(y0       -       1000 
     *(a)); 
     
        line( board2, pt1, pt2, Scalar(      255),      1, CV_AA);      
    }      
    imshow(      "src",src);      
    waitKey();      
}

 

结果

opencv条纹结构光 opencv 直线_数据结构_05

(HoughLineP)

opencv条纹结构光 opencv 直线_opencv条纹结构光_06

 

(HoughLine)

从结果上来看,HoughlineP识别的要更准确。这两个函数一个是识别出来图形上的点,一个是识别出来角度和图像上的点。两个函数的结果都是自己编写代码打印出来的。

 

三、结合实际

实际上我需要的是识别出直线,并且对图像进行旋转。这部分的代码是这样的

        Point pt1;

    Point pt2;

float t      = (     float)(src.cols     +src.rows);     
    pt1.x      = cvRound(Line1[     2]      - Line1[     0] 
    *t); 
    
    pt1.y      =cvRound(Line1[     3]     -Line1[     1] 
    *t); 
    
    pt2.x      = cvRound(Line1[     2]     +Line1[     0] 
    *t); 
    
    pt2.y      = cvRound(Line1[     3]     +Line1[     1] 
    *t); 
    
    line( src, pt1, pt2, Scalar(     255),     1, CV_AA);     
         //对结果图像进行旋转     
    Point center      = Point( src.cols     /     2, src.rows     / 
    2 ); 
    //以图像中心为中心 
    
         double angle      =atan(Line1[     1]     /Line1[     0]); 
    
    angle       = Rad2Deg(angle);     //由弧度转换为角度     
         /// 通过上面的旋转细节信息求得旋转矩阵     
    Mat rot_mat      = getRotationMatrix2D( center, angle,      1 );     
         /// 旋转已扭曲图像     
    warpAffine( src, dst, rot_mat, src.size() );