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);
}
posted @ 2020-03-29 22:11  cyssmile  阅读(333)  评论(0编辑  收藏  举报