霍夫变换 (一) 检测直线

霍夫变换是图像处理中识别几何形状的一种方法, 主要用来检测直线和圆形。

 

1  平面坐标和极坐标

1)  平面坐标的 <=> 极坐标(平面化)的曲线

    所谓极坐标平面化是指, 将ρ-θ的关系像x-y那样在平面内展开。

    公式推导: x-y坐标中的点(x0, y0), 代入极坐标ρ-θ中得

   

    其中, 

    由上述公式可以明显的看出ρ与θ之间的函数关系。

霍夫变换 (一) 检测直线_第1张图片

2)  极坐标(平面化)的 <=> 平面坐标的直线

    公式推导: ρ-θ极坐标中的点(ρ0, θ0), 代入平面坐标x-y中得

   

   由此可知, 极坐标中的一个确定点(ρ0, θ0), 对应于平面坐标内的一条直线。若极坐标中有N条曲线相交于一点(如下左图), 则说明在平面坐标中, 该点对应的直线包含N条曲线对应的N个点, 也即这N个点组成了一条直线。

     霍夫变换 (一) 检测直线_第2张图片          霍夫变换 (一) 检测直线_第3张图片

    上面左图中, 是平面坐标中的三个点 (8,6), (4, 9), (12,3) 分别对应的三条曲线。

    因此, 霍夫变换的原理就是将平面坐标内的直线检测, 转换为极坐标内的交点检测, 显然寻找一个交点要比寻找直线(实际上是寻找许多点)容易得多了。

    霍夫变换的具体算法, 就属于学术范畴了, 本人就不求甚解了, 感兴趣的可以去看相关的论文或者OpenCV的源码。

   

 2  OpenCV中的函数

    摘自OpenCV 3.1.0中HoughLines和HoughLinesP两个函数的介绍。

    http://docs.opencv.org/3.1.0/d9/db0/tutorial_hough_lines.html#gsc.tab=0

1)  HoughLines

void cv::HoughLines ( InputArray  image,
    OutputArray  lines,
    double  rho,
    double  theta,
    int  threshold,
    double  srn = 0,
    double  stn = 0,
    double  min_theta = 0,
    double  max_theta = CV_PI 
  )  
Parameters
image 8-bit, single-channel binary source image. The image may be modified by the function.
lines Output vector of lines. Each line is represented by a two-element vector (ρ,θ). ρ is the distance from the cordinate origin(0,0)(top-left corner of the image). θ is the line rotation angle in radians(0 ~ vertical line, Π/2 ~ horizontal line)
rho Distance resolution of the accumulator in pixels.
theta Angle resolution of the accumulator in radians.
threshold Accumulator threshold parameter. Only those lines are returned that get enough votes(>threshold).
srn For the multi-scale Hough transform, it is a divisor for the distance resolution rho. The coarse accumulator distance resolution is rho and the accurate accumulator resolution is rho/srn. If both srn=0 and stn=0, the classical Hough transform is used. Otherwise, both these parameters should be positive.
stn For the multi-scale Hough transform, it is a divisor for the distance resolution theta.
min_theta For standard and multi-scale Hough transform, minimum angle to check for lines. Must fall between 0 and max_theta.
max_theta For standard and multi-scale Hough transform, maximum angle to check for lines. Must fall between min_theta and CV_PI.

 

2)  HoughLinesP

void cv::HoughLinesP ( InputArray  image,
    OutputArray  lines,
    double  rho,
    double  theta,
    int  threshold,
    double  minLineLength = 0,
    double  maxLineGap = 0 
  )  

  Parameters

image 8-bit, single-channel binary source image. The image may be modified by the function.
lines Output vector of lines. Each line is represented by a 4-element vector x1, y1, x2,y2), where (x1, y1) and (x2, y2) are the ending points of each detected line segment.
rho Distance resolution of the accumulator in pixels.
theta Angle resolution of the accumulator in radians.
threshold Accumulator threshold parameter. Only those lines are returned that get enough votes(>threshold).
minLineLength Minimum line length. Line segments shorter than that are rejected.
MaxLineGap Maximum allowed gap between points on the same line to link them.

 

3  范例

1)  简单

 1 #include "opencv2/imgcodecs.hpp"
 2 #include "opencv2/highgui/highgui.hpp"
 3 #include "opencv2/imgproc/imgproc.hpp"
 4 
 5 #include <iostream>
 6 
 7 using namespace cv;
 8 using namespace std;
 9 
10 static void help()
11 {
12     cout << "\nThis program demonstrates line finding with the Hough transform.\n"
13             "Usage:\n"
14             "./houghlines <image_name>, Default is ../data/pic1.png\n" << endl;
15 }
16 
17 int main(int argc, char** argv)
18 {
19     cv::CommandLineParser parser(argc, argv,
20         "{help h||}{@image|../data/pic1.png|}"
21     );
22     if (parser.has("help"))
23     {
24         help();
25         return 0;
26     }
27     string filename = parser.get<string>("@image");
28     if (filename.empty())
29     {
30         help();
31         cout << "no image_name provided" << endl;
32         return -1;
33     }
34     Mat src = imread(filename, 0);
35     if(src.empty())
36     {
37         help();
38         cout << "can not open " << filename << endl;
39         return -1;
40     }
41 
42     Mat dst, cdst;
43     Canny(src, dst, 50, 200, 3);
44     cvtColor(dst, cdst, COLOR_GRAY2BGR);
45 
46 #if 0
47     vector<Vec2f> lines;
48     HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 );
49     for( size_t i = 0; i < lines.size(); i++ )
50     {
51         float rho = lines[i][0], theta = lines[i][1];
52         Point pt1, pt2;
53         double a = cos(theta), b = sin(theta);
54         double x0 = a*rho, y0 = b*rho;
55         pt1.x = cvRound(x0 + 1000*(-b));
56         pt1.y = cvRound(y0 + 1000*(a));
57         pt2.x = cvRound(x0 - 1000*(-b));
58         pt2.y = cvRound(y0 - 1000*(a));
59         line( cdst, pt1, pt2, Scalar(0,0,255), 3, CV_AA);
60     }
61 #else
62     vector<Vec4i> lines;
63     HoughLinesP(dst, lines, 1, CV_PI/180, 50, 50, 10 );
64     for( size_t i = 0; i < lines.size(); i++ )
65     {
66         Vec4i l = lines[i];
67         line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA);
68     }
69 #endif
70     imshow("source", src);
71     imshow("detected lines", cdst);
72 
73     waitKey();
74 
75     return 0;
76 }
houghlines

2)  复杂

   摘自 https://github.com/Itseez/opencv/blob/master/samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp

  1 /**
  2  * @file HoughLines_Demo.cpp
  3  * @brief Demo code for Hough Transform
  4  * @author OpenCV team
  5  */
  6 
  7 #include "opencv2/imgcodecs.hpp"
  8 #include "opencv2/highgui/highgui.hpp"
  9 #include "opencv2/imgproc/imgproc.hpp"
 10 #include <iostream>
 11 #include <stdio.h>
 12 
 13 using namespace cv;
 14 using namespace std;
 15 
 16 /// Global variables
 17 
 18 /** General variables */
 19 Mat src, edges;
 20 Mat src_gray;
 21 Mat standard_hough, probabilistic_hough;
 22 int min_threshold = 50;
 23 int max_trackbar = 150;
 24 
 25 const char* standard_name = "Standard Hough Lines Demo";
 26 const char* probabilistic_name = "Probabilistic Hough Lines Demo";
 27 
 28 int s_trackbar = max_trackbar;
 29 int p_trackbar = max_trackbar;
 30 
 31 /// Function Headers
 32 void help();
 33 void Standard_Hough( int, void* );
 34 void Probabilistic_Hough( int, void* );
 35 
 36 /**
 37  * @function main
 38  */
 39 int main( int, char** argv )
 40 {
 41    /// Read the image
 42    src = imread( argv[1], 1 );
 43 
 44    if( src.empty() )
 45      { help();
 46        return -1;
 47      }
 48 
 49    /// Pass the image to gray
 50    cvtColor( src, src_gray, COLOR_RGB2GRAY );
 51 
 52    /// Apply Canny edge detector
 53    Canny( src_gray, edges, 50, 200, 3 );
 54 
 55    /// Create Trackbars for Thresholds
 56    char thresh_label[50];
 57    sprintf( thresh_label, "Thres: %d + input", min_threshold );
 58 
 59    namedWindow( standard_name, WINDOW_AUTOSIZE );
 60    createTrackbar( thresh_label, standard_name, &s_trackbar, max_trackbar, Standard_Hough);
 61 
 62    namedWindow( probabilistic_name, WINDOW_AUTOSIZE );
 63    createTrackbar( thresh_label, probabilistic_name, &p_trackbar, max_trackbar, Probabilistic_Hough);
 64 
 65    /// Initialize
 66    Standard_Hough(0, 0);
 67    Probabilistic_Hough(0, 0);
 68    waitKey(0);
 69    return 0;
 70 }
 71 
 72 /**
 73  * @function help
 74  * @brief Indications of how to run this program and why is it for
 75  */
 76 void help()
 77 {
 78   printf("\t Hough Transform to detect lines \n ");
 79   printf("\t---------------------------------\n ");
 80   printf(" Usage: ./HoughLines_Demo <image_name> \n");
 81 }
 82 
 83 /**
 84  * @function Standard_Hough
 85  */
 86 void Standard_Hough( int, void* )
 87 {
 88   vector<Vec2f> s_lines;
 89   cvtColor( edges, standard_hough, COLOR_GRAY2BGR );
 90 
 91   /// 1. Use Standard Hough Transform
 92   HoughLines( edges, s_lines, 1, CV_PI/180, min_threshold + s_trackbar, 0, 0 );
 93 
 94   /// Show the result
 95   for( size_t i = 0; i < s_lines.size(); i++ )
 96      {
 97       float r = s_lines[i][0], t = s_lines[i][1];
 98       double cos_t = cos(t), sin_t = sin(t);
 99       double x0 = r*cos_t, y0 = r*sin_t;
100       double alpha = 1000;
101 
102        Point pt1( cvRound(x0 + alpha*(-sin_t)), cvRound(y0 + alpha*cos_t) );
103        Point pt2( cvRound(x0 - alpha*(-sin_t)), cvRound(y0 - alpha*cos_t) );
104        line( standard_hough, pt1, pt2, Scalar(255,0,0), 3, LINE_AA);
105      }
106 
107    imshow( standard_name, standard_hough );
108 }
109 
110 /**
111  * @function Probabilistic_Hough
112  */
113 void Probabilistic_Hough( int, void* )
114 {
115   vector<Vec4i> p_lines;
116   cvtColor( edges, probabilistic_hough, COLOR_GRAY2BGR );
117 
118   /// 2. Use Probabilistic Hough Transform
119   HoughLinesP( edges, p_lines, 1, CV_PI/180, min_threshold + p_trackbar, 30, 10 );
120 
121   /// Show the result
122   for( size_t i = 0; i < p_lines.size(); i++ )
123      {
124        Vec4i l = p_lines[i];
125        line( probabilistic_hough, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(255,0,0), 3, LINE_AA);
126      }
127 
128    imshow( probabilistic_name, probabilistic_hough );
129 }
HoughLines_Demo

 

你可能感兴趣的:(霍夫变换 (一) 检测直线)