opencv 霍夫变换检测直线

来源:互联网 发布:安卓刷机软件哪个最好 编辑:程序博客网 时间:2024/05/01 02:31
[cpp] view plaincopy
  1. #include <iostream>  
  2. #include <cv.h>  
  3. #include <cxcore.h>  
  4. #include <highgui.h>  
  5.   
  6.   
  7.   
  8.   
  9. using namespace std;  
  10.   
  11.   
  12. int main()  
  13. {  
  14.     IplImage *srcRGB = cvLoadImage("f:\\images\\chess1.jpg");  
  15.     IplImage *src = cvCreateImage(cvSize(srcRGB->width,srcRGB->height),IPL_DEPTH_8U,1);  
  16.       
  17.     cvCvtColor(srcRGB,src,CV_RGB2GRAY);  
  18.     IplImage *dst = cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,src->nChannels);  
  19.     IplImage *color_dst = cvCloneImage(srcRGB);cvSetZero(color_dst);  
  20.     CvMemStorage *storage = cvCreateMemStorage();  
  21.     CvSeq *lines = 0;  
  22.   
  23.   
  24.     cvCanny(src,dst,40,90);  
  25.     cvCvtColor(dst,color_dst,CV_GRAY2RGB);  
  26.   
  27.   
  28.       
  29.   
  30.   
  31. #if 1  
  32.     lines = cvHoughLines2(dst  
  33.         ,storage  
  34.         ,CV_HOUGH_STANDARD  
  35.         ,1  
  36.         ,CV_PI/180  
  37.         ,150  
  38.         ,0  
  39.         ,0);  
  40.     for(int i = 0;i<MIN(lines->total,100);i++){  
  41.         float *line = (float*)cvGetSeqElem(lines,i);  
  42.         float rho = line[0];  
  43.         float threta = line[1];  
  44.         CvPoint pt1, pt2; // 这个地方的计算公式,在文章下面介绍。  
  45.         double a = cos(threta),b = sin(threta);  
  46.         double x0 = a*rho, y0 = b * rho;  
  47.         pt1.x = cvRound(x0 + 1000*(-b));  
  48.         pt1.y = cvRound(y0 + 1000*(a));  
  49.         pt2.x = cvRound(x0 - 1000*(-b));  
  50.         pt2.y = cvRound(y0 - 1000*(a));  
  51.         cvLine(color_dst,pt1,pt2,CV_RGB(255,0,0),1,8);  
  52.     }  
  53. #else  
  54.     lines = cvHoughLines2(dst,  
  55.         storage,  
  56.         CV_HOUGH_PROBABILISTIC,  
  57.         1,  
  58.         CV_PI/180,  
  59.         100,  
  60.         50,  
  61.         10);  
  62.     for(int i = 0;i<lines->total; ++i){  
  63.         CvPoint *line = (CvPoint*)cvGetSeqElem(lines,i);  
  64.         cvLine(color_dst,line[0],line[1],CV_RGB(255,0,0),1,8);  
  65.     }  
  66. #endif  
  67.   
  68.   
  69.     cvShowImage("source",src);  
  70.     cvShowImage("Hough",color_dst);  
  71.     cvShowImage("dst",dst);  
  72.     cvWaitKey(0);  
  73. }  

改变#if后的常量为1时,使用上面的代码编译,为0时,使用下面的代码编译

CVAPI(CvSeq*) cvHoughLines2( CvArr* image, void* line_storage, int method, double rho, double theta, int threshold, double param1 CV_DEFAULT(0), double param2 CV_DEFAULT(0)) //

image  The 8-bit, single-channel, binary source image.  In the case of a probabilistic method, the 

      image is modified by the function  //8bit 单通道二值图像


storage  The storage for the lines that are detected.  It can be a memory storage (in this case a 
      sequence of lines is created in the storage and returned by the function) or single row/single 
      column matrix (CvMat*) of a particular type (see below) to which the lines’ parameters are 
      written.  The matrix header is modified by the function so its  cols or  rows will contain the 
      number of lines detected.   If  storage is a matrix and the actual number of lines exceeds 
      the matrix size, the maximum possible number of lines is returned (in the case of standard 
      hough transform the lines are sorted by the accumulator value) 


method    The Hough transform variant, one of the following: 


      CV HOUGH  STANDARD  classical or standard Hough transform.  Every line is represented by 
           two floating-point numbers  , where  is a distance between (0,0) point and the line, 
           and  is the angle between x-axis and the normal to the line.  Thus, the matrix must be 
           (the created sequence will be) of CV  32FC2 type   //返回值ro ,theta


      CV HOUGH PROBABILISTIC         probabilistic Hough transform (more efficient in case if picture 
           contains a few long linear segments).    It returns line segments rather than the whole 
           line.  Each segment is represented by starting and ending points, and the matrix must 
           be (the created sequence will be) of CV  32SC4 type  //返回值为 直线的两个端点


      CV HOUGH MULTI  SCALE      multi-scale variant of the classical Hough transform. The lines are 
           encoded the same way as CV HOUGH  STANDARD 


rho   Distance resolution in pixel-related units   //rho 距离分辨率  ,理解直线的表达式 p = xcos(theta) + ysin(theta)的意思


theta   Angle resolution measured in radians  //theta的分辨率


threshold     Threshold parameter. A line is returned by the function if the corresponding accumu- 
      lator value is greater than threshold    //累积值的阈值


param1    The first method-dependent parameter: 


           For the classical Hough transform it is not used (0).  //未用 


           For the probabilistic Hough transform it is the minimum line length.  //最短直线长度


           For the multi-scale Hough transform it is the divisor for the distance resolution .  (The 
           coarse distance resolution will be  and the accurate resolution will be param1). 


param2    The second method-dependent parameter: 


           For the classical Hough transform it is not used (0).  //未用

           For  the  probabilistic  Hough  transform  it  is  the  maximum  gap  between  line  segments 
           lying on the same line to treat them as a single line segment (i.e. to join them).  //直线的最小间距


           For  the  multi-scale  Hough  transform  it  is  the  divisor  for  the  angle  resolution . (The 
           coarse angle resolution will be  and the accurate resolution will be param2). 






pt1与pt2点的计算方法 。 

这里已知下图中的rh0 和θ,现在只需要求图中“任意”两点, 就能用cvLine画出pt1 -> pt2的直线 。 

看看下图 就明白这里1000什么的是为什么了。


这里是取了点(x0,y0)在直线上上下1000的距离,那么用cvLine画出来的线段就是从pt1 -> pt2的了。

1.这个地方也许会出现检测出来的线段长度比pt1->pt2还大,即包含了我们画的线段 , 这是肯定的。

2. 还会出现本来线段没有pt1->pt2这么长,那么我们画的就会过长了。 也是肯定会出现的情况。

因为:CV_HOUGH_STANDARD方法 只能得出rh0 和 θ的值。  这两个值只能确定直线,而不能确定线段是从哪开始到哪结束。

此方法只能确定线段对应的直线。


如果你想检测出图中的线段是从哪到哪的话,请用CV_HOUGH_PROBABILISTIC . 

0 0
原创粉丝点击