In this tutorial, you will learn how to use OpenCV to detect edges, lines, and circles. For an application, you will learn how to find straight lanes using Canny edge detection and Hough transformation algorithms.
C++: void Canny(InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize=3, bool L2gradient=false )
· image – single-channel 8-bit input image.· edges – output edge map; it has the same size and type as image .· threshold1 – first threshold for the hysteresis procedure.· threshold2 – second threshold for the hysteresis procedure.· apertureSize – aperture size for the Sobel() operator.· L2gradient – a flag, indicating whether a more accurate L2 norm should be used to calculate the image gradient magnitude ( L2gradient=true ), or whether the default L1 norm is enough ( L2gradient=false ).
Declare and define variables:
Mat src, src_gray; Mat dst, detected_edges;int edgeThresh =1;int lowThreshold;intconst max_lowThreshold =100;int ratio =3; // a ratio of lower:upperint kernel_size =3; //Sobel OperationString window_name ="Edge Map";
2) The Probabilistic Hough Line Transform ( HoughLinesP() )
A more efficient implementation of the Hough Line Transform. It gives as output of extremes(end) points of the detected lines (x0, y0, x1, y1)\
void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=0, double stn=0 )
void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0 )
/*· 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 2 or 3 element vector (ρ,θ) or (ρ,θ,votes) ρ is the distance from the coordinate origin (0,0) (top-left corner of the image) θ is the line rotation angle in radians ( 0∼vertical line,π/2∼horizontal line ) votes is the value of accumulator. lines (HoughLinesP) 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.
· lines – Output vector of lines. Each line is represented by a 4-element vector , where and 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 ( ).· minLineLength – Minimum line length. Line segments shorter than that are rejected.· maxLineGap – Maximum allowed gap between points on the same line to link them.*/
Load an image
// Loads an imageconstchar* filename ="../images/Lane_test.jpg"; Mat src =imread(filename, IMREAD_GRAYSCALE); // Check if image is loaded fineif (src.empty()) {printf(" Error opening image\n");return-1; }imshow("Source", src);
Detect the edges using Canny detector
// Edge detectionCanny(src, dst,50,200,3);
Copy edges to the images that will display the results in BGR
// Copy edge results to the images that will display the results in BGRcvtColor(dst, cdst, COLOR_GRAY2BGR); cdstP =cdst.clone();
(Option 1) Standard Hough Line Transform
First, apply the Hough Transform. Then display the results by drawing the lines.
Output vector of lines. Each line is represented by a 2 or 3 element vector (ρ,θ) or (ρ,θ,votes) . ρ is the distance from the coordinate origin (0,0) (top-left corner of the image). θ is the line rotation angle in radians ( 0∼vertical line,π/2∼horizontal line ). votes is the value of accumulator.\
// (Option 1) Standard Hough Line Transform vector<Vec2f> lines; HoughLines(dst, lines,1, CV_PI /180,150,0,0); // Draw the detected linesfor (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));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); }imshow("Detected Lines (in red) - Standard Hough Line Transform", cdst);
(Option 2) Probabilistic Hough Line Transform
Lines (HoughLinesP) 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.
vector<Vec4i> linesP; HoughLinesP(dst, linesP,1, CV_PI /180,50,50,10); // Draw the linesfor (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); }imshow("Detected Lines (in red) - Probabilistic Line Transform", cdstP);
Show results
// Show resultsimshow("Source", src);imshow("Detected Lines (in red) - Standard Hough Line Transform", cdst);imshow("Detected Lines (in red) - Probabilistic Line Transform", cdstP);
Usually, the function detects the centers of circles well but the radius may not be accurate. It helps if you can specify the radius ranges ( minRadius and maxRadius ), if available. Or, you may set maxRadius to a negative number to return centers only without radius search, and find the correct radius using an additional procedure.
void cv::HoughCircles(InputArray image, OutputArray circles, int method, double dp, double minDist, double param1 = 100, double param2 = 100, int minRadius = 0, int maxRadius = 0 )
/*image: 8-bit, single-channel, grayscale input image.Circles: Output vector of found circles. Each vector is encoded as 3 or 4 element floating-point vector (x,y,radius) or (x,y,radius,votes) .
method Detection method, see HoughModes. Currently, the only implemented method is HOUGH_GRADIENTdp Inverse ratio of the accumulator resolution to the image resolution. For example, if dp=1 , the accumulator has the same resolution as the input image. If dp=2 , the accumulator has half as big width and height.
minDist Minimum distance between the centers of the detected circles. If the parameter is too small, multiple neighbor circles may be falsely detected in addition to a true one. If it is too large, some circles may be missed.
param1 First method-specific parameter. In case of HOUGH_GRADIENT , it is the higher threshold of the two passed to the Canny edge detector (the lower one is twice smaller).
param2 Second method-specific parameter. In case of HOUGH_GRADIENT , it is the accumulator threshold for the circle centers at the detection stage. The smaller it is, the more false circles may be detected. Circles, corresponding to the larger accumulator values, will be returned first.
minRadius Minimum circle radius.maxRadius Maximum circle radius. If <= 0, uses the maximum image dimension. If < 0, returns centers without finding the radius.
*/
Example code
vector<Vec3f> circles;HoughCircles(gray, circles,3,2,gray.rows /4,200,100);for (size_t i =0; i <circles.size(); i++){ Point center(cvRound(circles[i][0]),cvRound(circles[i][1]));int radius =cvRound(circles[i][2]); // draw the circle centercircle(src, center,3,Scalar(0,255,0),-1,8,0); // draw the circle outlinecircle(src, center, radius,Scalar(0,0,255),3,8,0); }namedWindow("circles",1);imshow("circles", src);
Exercise
Exercise 1
Download the following tutorial codes for Edge and Line Detection. Fill in the blanks.
Try to fill in the codes without referring to the demo source files