Hough直线检测
实验原理:http://homepages.inf.ed.ac.uk/rbf/HIPR2/hough.htm
OPENCV 中主要有两个API
CV_EXPORTS_W void 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 );
/** @brief Finds lines in a binary image using the standard Hough transform.
The function implements the standard or standard multi-scale Hough transform algorithm for line
detection. See <http://homepages.inf.ed.ac.uk/rbf/HIPR2/hough.htm> for a good explanation of Hough
transform.
@param image 8-bit, single-channel binary source image. The image may be modified by the function.
@param lines Output vector of lines. Each line is represented by a 2 or 3 element vector
\f$(\rho, \theta)\f$ or \f$(\rho, \theta, \textrm{votes})\f$ . \f$\rho\f$ is the distance from the coordinate origin \f$(0,0)\f$ (top-left corner of
the image). \f$\theta\f$ is the line rotation angle in radians (
\f$0 \sim \textrm{vertical line}, \pi/2 \sim \textrm{horizontal line}\f$ ).
\f$\textrm{votes}\f$ is the value of accumulator.
@param rho Distance resolution of the accumulator in pixels.
@param theta Angle resolution of the accumulator in radians.
@param threshold Accumulator threshold parameter. Only those lines are returned that get enough
votes ( \f$>\texttt{threshold}\f$ ).
@param 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.
@param stn For the multi-scale Hough transform, it is a divisor for the distance resolution theta.
@param min_theta For standard and multi-scale Hough transform, minimum angle to check for lines.
Must fall between 0 and max_theta.
@param max_theta For standard and multi-scale Hough transform, maximum angle to check for lines.
Must fall between min_theta and CV_PI.
*/
CV_EXPORTS_W void HoughLinesP( InputArray image, OutputArray lines,
double rho, double theta, int threshold,
double minLineLength = 0, double maxLineGap = 0 );
rho 极坐标系下的长度
theta 极坐标下的角度
minLineLength 最小可认为是线段长度
maxLineGap 中断多长距离,还可认为是直线的长度
/** @brief Finds line segments in a binary image using the probabilistic Hough transform.
The function implements the probabilistic Hough transform algorithm for line detection, described
in @cite Matas00
See the line detection example below:
@include snippets/imgproc_HoughLinesP.cpp
This is a sample picture the function parameters have been tuned for:
![image](pics/building.jpg)
And this is the output of the above program in case of the probabilistic Hough transform:
![image](pics/houghp.png)
@param image 8-bit, single-channel binary source image. The image may be modified by the function.
@param lines Output vector of lines. Each line is represented by a 4-element vector
\f$(x_1, y_1, x_2, y_2)\f$ , where \f$(x_1,y_1)\f$ and \f$(x_2, y_2)\f$ are the ending points of each detected
line segment.
@param rho Distance resolution of the accumulator in pixels.
@param theta Angle resolution of the accumulator in radians.
@param threshold Accumulator threshold parameter. Only those lines are returned that get enough
votes ( \f$>\texttt{threshold}\f$ ).
@param minLineLength Minimum line length. Line segments shorter than that are rejected.
@param maxLineGap Maximum allowed gap between points on the same line to link them.
@sa LineSegmentDetector
*/
实验效果:
我的代码地址:https://github.com/cyssmile/openCV_learning_notes/blob/master/opencv_test/opencv_033/opencv_033.cpp
#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
using namespace std;
using namespace cv;
void drawRandomLine(Mat& canvas, Size size, int type, int NumberOfLine);
void toTwoValued(Mat& images,Mat& destination);
void HoughLines_Demo(Mat& images);
void HoughLinesP_Demo(Mat& images);
int main(int argc, char** arrgv)
{
Mat orignal = imread("D:/images/lines.jpg", -1);
imshow("orignal_demo", orignal);
/*
* 霍夫直线检测
* HoughLines_Demo(orignal);
*/
Mat randLines;
drawRandomLine(randLines,Size(512,512),CV_8UC3,6);
HoughLinesP_Demo(randLines);
waitKey(0);
destroyAllWindows();
return 0;
}
void drawRandomLine(Mat& canvas,Size size,int type,int NumberOfLine)
{
canvas = Mat::zeros(size,type);
RNG rng(12345);
for (int i = 0; i < NumberOfLine; i++)
{
line(canvas, Point(rng.uniform(0, size.width), rng.uniform(0, size.height)),
Point(rng.uniform(0, size.width), rng.uniform(0, size.height)),
Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)),
1, 8, 0);
}
}
void toTwoValued(Mat& images, Mat& destination)
{
cvtColor(images,destination,COLOR_BGR2GRAY);
threshold(destination, destination, 0, 255, THRESH_BINARY | THRESH_OTSU);
bitwise_not(destination, destination);
//imshow("two_valued", destination);
}
void HoughLines_Demo(Mat& images)
{
/*
Mat images;
drawRandomLine(images,Size(512,512),CV_8UC3,4);
*/
if (images.empty())
{
cout << "can`t open this ph" << endl;
return ;
}
Mat binary;
toTwoValued(images, binary);
//霍夫直线检测
vector<Vec3f> lines;
HoughLines(binary, lines, 1, CV_PI / 180.0, 100, 0, 0);
//将极坐标转换成笛卡尔坐标,绘制
Point pt1, pt2;
for (size_t t = 0; t < lines.size(); t++)
{
float rth = lines[t][0]; //距离
float theta = lines[t][1];//角度
float acc = lines[t][2];//累加值
cout << "r: " << rth << " theta:" << theta << " acc:" << acc << endl;
double b = sin(theta);
double a = cos(theta);
double x0 = a * rth;
double y0 = b * rth;
pt1.x = cvRound(x0 + 512 * (-b));
pt1.y = cvRound(y0 + 512 * (a));
pt2.x = cvRound(x0 - 512 * (-b));
pt2.y = cvRound(y0 - 512 * (a));
int angle = cvRound((theta/CV_PI)*180);
if (rth>0)
{
line(images, pt1, pt2, Scalar(255, 255, 0), 1, 8);
if (angle == 90)
{
line(images, pt1, pt2, Scalar(0,255, 255), 1, 8);
}
if (angle < 1)
{
line(images, pt1, pt2, Scalar(255, 0, 255), 1, 8);
}
}else
{
line(images, pt1, pt2, Scalar(255, 0, 0), 1, 8);
}
}
imshow("houghline", images);
}
void HoughLinesP_Demo(Mat& images)
{
Mat binary;
Canny(images,binary,50,100,3,false);
imshow("canny_demo",binary);
vector<Vec4i> lines;
Mat canvas = Mat::zeros(images.size(), images.type());
HoughLinesP(binary,lines,1,CV_PI/180.0,50,20,10);
cout << lines.size() << endl;
for (size_t t =0;t<lines.size();t++)
{
line(canvas,Point(lines[t][0],lines[t][1]), Point(lines[t][2], lines[t][3]),Scalar(0,0,255),2,8);
}
imshow("canvas", canvas);
}