霍夫线变换

这一节课将学到使用OpenCV的以下函数 HoughLinesHoughLinesP 来检测图像中的直线.和霍夫线变换的相关知识。


 什么是霍夫线变换?

  1.霍夫线变换是一种检测直线的算法。

  2.在进行霍夫线变换之前必须对图像进行边缘检测处理,所以霍夫线变换的直接输入必须是边缘二值图像。


 如何实现?

  1. 众所周知,一条直线在图像二维空间可由两个变量表示。例如:

      a.在笛卡尔坐标系:可由参数斜率和截距表示。

      b.在即坐标系:可由极径和极角表示。

  2.对于霍夫变换,我们将用极坐标系来表示直线,因此,直线的表达式可以是:

      y = \left ( -\dfrac{\cos \theta}{\sin \theta} \right ) x + \left ( \dfrac{r}{\sin \theta} \right )

      化简得: r = x \cos \theta + y \sin \theta

      一般来说对于点(x0,y0),我们可以将通过这个点得一族直线统一定义为:r_{\theta} = x_{0} \cdot \cos \theta  + y_{0} \cdot \sin \theta

     这就意味着对于每一对(rθ,θ)代表一条通过(x0,y0)的直线。

  3.如果对于一个给定点(x0,y0)我们在极坐标对极径角平面绘出所有通过它的直线,将得到一条正弦曲线。例如,对于给定点x0=θ and y0=6 我们可以绘出下图(在平面)。

       只绘制出满足下列条件的点r>0 and 0<θ<2∏

  4.我们可以对图像中所有的点进行上述操作,如果两个不同点进行上述操作后得到的曲线在平面 θ-r 相交,则表示他们通过同一条直线。

     

        三条曲线相交于(0.925,9.6),坐标表示的是参数对(θ,r),或者说是(x0,y0)和点(x1,y1)和点(x2,y2)。组成的平面内的直线。

  5.说了这么都到底是想表达些什么呢?首先二值图像上面的点我们可以根据其取值不同来进行不同的分类,然后将这些点转化为极坐标点,极坐标点在极径极角平面可以画出所有通过他的直线,  我们将得到一条正弦曲线,我们可以根据这一特性来确定

在二值图像上那些亮度相近的点是一条直线上的。

  6.这就是霍夫变换所做的。他追踪图像中每个点对应曲线间的交点,如果交与一点的曲线数量超过了某个阈值,那么就可以认为这个交点是图像中的一条直线。


OpenCV实现了两种霍夫变换:

  a.标准霍夫变换

    原理在上面的部分已经讲的差不多了,他能给我们提供一组参数对(θ,rθ)的集合来表示检测到的对象。早OpenCv中该变化使用HoughLines来实现

  b.统计概率霍夫线变换

    这是执行起来效率更高的霍夫线变换,他输出检测到的直线的端点(x0,y0,x1,y1)。在OpenCV中他通过函数HoughLinesP来实现。


代码

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <iostream>

using namespace cv;
using namespace std;


int main(int argc, char** argv)
{
     const char* filename = "pic1.jpg";

     Mat src = imread("res.jpg");
     if(src.empty())
     {
         cout << "can not open " << filename << endl;
         return -1;
     }

     Mat dst, cdst;
     Canny(src, dst, 50, 200, 3);
     cvtColor(dst, cdst, CV_GRAY2BGR);

     #if 0
      vector<Vec2f> lines;
      HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 );

      for( size_t i = 0; i < lines.size(); i++ )
      {
         float rho = lines[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( cdst, pt1, pt2, Scalar(0,0,255), 3, CV_AA);
      }
     #else
      vector<Vec4i> lines;
      HoughLinesP(dst, lines, 1, CV_PI/180, 50, 50, 10 );
      for( size_t i = 0; i < lines.size(); i++ )
      {
        Vec4i l = lines[i];
        line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, CV_AA);
      }
     #endif
     imshow("source", src);
     imshow("detected lines", cdst);

     waitKey();

     return 0;
}

 

 

  

  

  



posted @ 2016-11-30 17:14  X-POWER  阅读(859)  评论(0编辑  收藏  举报