Goal
In this tutorial you will learn how to:
- Use the OpenCV functions HoughLines() and HoughLinesP() to detect lines in an image.
- 使用OpenCV库函数HoughLines() and HoughLinesP() 检测图像中的直线。
Theory
- Note
-
The explanation below belongs to the book Learning OpenCV by Bradski and Kaehler.
-
理论来源于《
Learning OpenCV》这本书。
Hough Line Transform
- The Hough Line Transform is a transform used to detect straight lines.
- 霍夫线变换用于检测直线
- To apply the Transform, first an edge detection pre-processing is desirable.
- 在进行霍夫变换之前,首先需要进行边缘检测预处理。
How does it work?
As you know, a line in the image space can be expressed with two variables. For example:
- In the Cartesian coordinate system: Parameters: (m,b).。笛卡尔坐标下,直线的两个参数。
- In the Polar coordinate system: Parameters:(r,θ)极坐标笛卡尔坐标下,直线的二个参数。。极坐标下,直线的两个参数。
For Hough Transforms, we will express lines in the Polar system. Hence, a line equation can be written as:
Arranging the terms: r=xcosθ+ysinθ
对上个方程进行整理为: r=xcosθ+ysinθ
1.In general for each point (x0,y0), we can define the family of lines that goes through that point as:
2.If for a given (x0,y0) we plot the family of lines that goes through it, we get a sinusoid. For instance, for x0=8 and y0=6 we get the following plot (in a plane θ - r):
对于给定点,它的线条族其实是一个正弦曲线。
We consider only points such that r>0 and 0<θ<2π.(只考虑这个情况)
3.We can do the same operation above for all the points in an image. If the curves of two different points intersect in the plane θ - r, that means that both points belong to a same line. For instance, following with the example above and drawing the plot for two more points: x1=4, y1=9 and x2=12, y2=3, we get:
对于图像上的所有点进行相同的操作,如果不同点的曲线在平面相交,那也叫意味着这两个点属于同一条直线。例如,这三个点交于一点。
上面的材料意味着什么呢?意味着,一条直线可以通过检测交点的数量检测处理啊。越多的曲线相交,则就以为这条直线有很多的点。通过可以设置一个最小的阀值作为检测点的数量来检测直线。
5.This is what the Hough Line Transform does. It keeps track of the intersection between curves of every point in the image. If the number of intersections is above some threshold, then it declares it as a line with the parameters (θ,rθ) of the intersection point.
Standard and Probabilistic Hough Line Transform
OpenCV implements two kind of Hough Line Transforms:
a. The Standard Hough Transform(标准变换)
- It consists in pretty much what we just explained in the previous section. It gives you as result a vector of couples(包含了前面所讲的内容,最后给出结果(θ,rθ))()
- In OpenCV it is implemented with the function HoughLines()(使用这个函数)
b. The Probabilistic Hough Line Transform(概率霍夫变换)
- A more efficient implementation of the Hough Line Transform. It gives as output the extremes of the detected lines (更有效的方法,并给出结果)(x0,y0,x1,y1)()
- In OpenCV it is implemented with the function HoughLinesP()(使用这个函数)
What does this program do?
- Loads an image(加载图像)
- Applies a Standard Hough Line Transform and a Probabilistic Line Transform.(进行两种变换)
- Display the original image and the detected line in three windows.(展示原图像和结果)
Code
#include "opencv2/imgcodecs.hpp"#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
// Declare the output variables
Mat dst, cdst, cdstP;
const char* default_file = "lena.jpg";
const char* filename = argc >=2 ? argv[1] : default_file;
// Loads an image
Mat src = imread( filename, IMREAD_GRAYSCALE );
// Check if image is loaded fine
if(src.empty()){
printf(" Error opening image\n");
printf(" Program Arguments: [image_name -- default %s] \n", default_file);
return -1;
}
// Edge detection
Canny(src, dst, 50, 200, 3); //输入,输出,小,大,大小
// Copy edges to the images that will display the results in BGR
cvtColor(dst, cdst, COLOR_GRAY2BGR); //灰度图
cdstP = cdst.clone();
// Standard Hough Line Transform
vector<Vec2f> lines; // will hold the results of the detection,两个浮点数
HoughLines(dst, lines, 1, CV_PI/180, 150, 0, 0 ); // runs the actual detection
//输入,输出,搜索直线时的步长,同上一个弧度,阀值,默认参数均为零
// Draw the lines
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)); //4舍5入
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, LINE_AA); //图像,第一点,第二点,颜色,厚度,线型
}
// Probabilistic Line Transform
vector<Vec4i> linesP; // will hold the results of the detection,4个整数
HoughLinesP(dst, linesP, 1, CV_PI/180, 50, 50, 10 ); // runs the actual detection
//输入,结果,分辨率,分辨率,阀值,显示一条直线的最短距离,允许两个点相连接的最大距离。
// Draw the lines
for( size_t i = 0; i < linesP.size(); i++ )
{
Vec4i l = linesP[i];
line( cdstP, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA);
}
// Show results
imshow("Source", src);
imshow("Detected Lines (in red) - Standard Hough Line Transform", cdst);
imshow("Detected Lines (in red) - Probabilistic Line Transform", cdstP);
// Wait and Exit
waitKey();
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project( DisplayImage )
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable( DisplayImage main.cpp )
target_link_libraries( DisplayImage ${OpenCV_LIBS} )
install(TARGETS DisplayImage RUNTIME DESTINATION bin