From: tribta Date: Sat, 26 Aug 2017 23:02:29 +0000 (+0100) Subject: Tutorial Hough Lines X-Git-Tag: accepted/tizen/6.0/unified/20201030.111113~539^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9a2317e063bcdaf46e0f8a68c7b972338b825ac8;p=platform%2Fupstream%2Fopencv.git Tutorial Hough Lines --- diff --git a/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.markdown b/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.markdown index 584c3f8..8b24d87 100644 --- a/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.markdown +++ b/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.markdown @@ -1,12 +1,15 @@ Hough Line Transform {#tutorial_hough_lines} ==================== +@prev_tutorial{tutorial_canny_detector} +@next_tutorial{tutorial_hough_circle} + Goal ---- In this tutorial you will learn how to: -- Use the OpenCV functions @ref cv::HoughLines and @ref cv::HoughLinesP to detect lines in an +- Use the OpenCV functions **HoughLines()** and **HoughLinesP()** to detect lines in an image. Theory @@ -79,54 +82,93 @@ 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 \f$(\theta, r_{\theta})\f$ -- In OpenCV it is implemented with the function @ref cv::HoughLines +- 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 \f$(x_{0}, y_{0}, x_{1}, y_{1})\f$ -- In OpenCV it is implemented with the function @ref cv::HoughLinesP +- 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 ---- --# **What does this program do?** - - Loads an image - - Applies either a *Standard Hough Line Transform* or a *Probabilistic Line Transform*. - - Display the original image and the detected line in two windows. - --# The sample code that we will explain can be downloaded from [here](https://github.com/opencv/opencv/tree/master/samples/cpp/houghlines.cpp). A slightly fancier version - (which shows both Hough standard and probabilistic with trackbars for changing the threshold - values) can be found [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp). - @include samples/cpp/houghlines.cpp +@add_toggle_cpp +The sample code that we will explain can be downloaded from +[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgTrans/houghlines.cpp). +A slightly fancier version (which shows both Hough standard and probabilistic +with trackbars for changing the threshold values) can be found +[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp). +@include samples/cpp/tutorial_code/ImgTrans/houghlines.cpp +@end_toggle + +@add_toggle_java +The sample code that we will explain can be downloaded from +[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java). +@include samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java +@end_toggle + +@add_toggle_python +The sample code that we will explain can be downloaded from +[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py). +@include samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py +@end_toggle Explanation ----------- --# Load an image - @code{.cpp} - Mat src = imread(filename, 0); - if(src.empty()) - { - help(); - cout << "can not open " << filename << endl; - return -1; - } - @endcode --# Detect the edges of the image by using a Canny detector - @code{.cpp} - Canny(src, dst, 50, 200, 3); - @endcode - Now we will apply the Hough Line Transform. We will explain how to use both OpenCV functions - available for this purpose: - --# **Standard Hough Line Transform** - -# First, you apply the Transform: - @code{.cpp} - vector lines; - HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 ); - @endcode - with the following arguments: +#### Load an image: + +@add_toggle_cpp +@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp load +@end_toggle + +@add_toggle_java +@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java load +@end_toggle + +@add_toggle_python +@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py load +@end_toggle + +#### Detect the edges of the image by using a Canny detector: + +@add_toggle_cpp +@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp edge_detection +@end_toggle + +@add_toggle_java +@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java edge_detection +@end_toggle + +@add_toggle_python +@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py edge_detection +@end_toggle + +Now we will apply the Hough Line Transform. We will explain how to use both OpenCV functions +available for this purpose. + +#### Standard Hough Line Transform: +First, you apply the Transform: + +@add_toggle_cpp +@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp hough_lines +@end_toggle + +@add_toggle_java +@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java hough_lines +@end_toggle + +@add_toggle_python +@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py hough_lines +@end_toggle + +- with the following arguments: - *dst*: Output of the edge detector. It should be a grayscale image (although in fact it is a binary one) @@ -137,28 +179,35 @@ Explanation - *threshold*: The minimum number of intersections to "*detect*" a line - *srn* and *stn*: Default parameters to zero. Check OpenCV reference for more info. - -# And then you display the result by drawing the lines. - @code{.cpp} - 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)); - 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); - } - @endcode --# **Probabilistic Hough Line Transform** - -# First you apply the transform: - @code{.cpp} - vector lines; - HoughLinesP(dst, lines, 1, CV_PI/180, 50, 50, 10 ); - @endcode - with the arguments: +And then you display the result by drawing the lines. +@add_toggle_cpp +@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp draw_lines +@end_toggle + +@add_toggle_java +@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java draw_lines +@end_toggle + +@add_toggle_python +@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py draw_lines +@end_toggle + +#### Probabilistic Hough Line Transform +First you apply the transform: + +@add_toggle_cpp +@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp hough_lines_p +@end_toggle + +@add_toggle_java +@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java hough_lines_p +@end_toggle + +@add_toggle_python +@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py hough_lines_p +@end_toggle + +- with the arguments: - *dst*: Output of the edge detector. It should be a grayscale image (although in fact it is a binary one) @@ -172,23 +221,47 @@ Explanation this number of points are disregarded. - *maxLineGap*: The maximum gap between two points to be considered in the same line. - -# And then you display the result by drawing the lines. - @code{.cpp} - for( size_t i = 0; i < lines.size(); i++ ) - { - Vec4i l = lines[i]; - line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA); - } - @endcode --# Display the original image and the detected lines: - @code{.cpp} - imshow("source", src); - imshow("detected lines", cdst); - @endcode --# Wait until the user exits the program - @code{.cpp} - waitKey(); - @endcode +And then you display the result by drawing the lines. + +@add_toggle_cpp +@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp draw_lines_p +@end_toggle + +@add_toggle_java +@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java draw_lines_p +@end_toggle + +@add_toggle_python +@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py draw_lines_p +@end_toggle + +#### Display the original image and the detected lines: + +@add_toggle_cpp +@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp imshow +@end_toggle + +@add_toggle_java +@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java imshow +@end_toggle + +@add_toggle_python +@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py imshow +@end_toggle + +#### Wait until the user exits the program + +@add_toggle_cpp +@snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp exit +@end_toggle + +@add_toggle_java +@snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java exit +@end_toggle + +@add_toggle_python +@snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py exit +@end_toggle Result ------ @@ -198,13 +271,11 @@ Result section. It still implements the same stuff as above, only adding the Trackbar for the Threshold. -Using an input image such as: - -![](images/Hough_Lines_Tutorial_Original_Image.jpg) - -We get the following result by using the Probabilistic Hough Line Transform: - -![](images/Hough_Lines_Tutorial_Result.jpg) +Using an input image such as a [sudoku image](https://raw.githubusercontent.com/opencv/opencv/master/samples/data/sudoku.png). +We get the following result by using the Standard Hough Line Transform: +![](images/hough_lines_result1.png) +And by using the Probabilistic Hough Line Transform: +![](images/hough_lines_result2.png) You may observe that the number of lines detected vary while you change the *threshold*. The explanation is sort of evident: If you establish a higher threshold, fewer lines will be detected diff --git a/doc/tutorials/imgproc/imgtrans/hough_lines/images/hough_lines_result1.png b/doc/tutorials/imgproc/imgtrans/hough_lines/images/hough_lines_result1.png new file mode 100644 index 0000000..012cee5 Binary files /dev/null and b/doc/tutorials/imgproc/imgtrans/hough_lines/images/hough_lines_result1.png differ diff --git a/doc/tutorials/imgproc/imgtrans/hough_lines/images/hough_lines_result2.png b/doc/tutorials/imgproc/imgtrans/hough_lines/images/hough_lines_result2.png new file mode 100644 index 0000000..a4dda92 Binary files /dev/null and b/doc/tutorials/imgproc/imgtrans/hough_lines/images/hough_lines_result2.png differ diff --git a/doc/tutorials/imgproc/table_of_content_imgproc.markdown b/doc/tutorials/imgproc/table_of_content_imgproc.markdown index 4bfe9dc..6b339e3 100644 --- a/doc/tutorials/imgproc/table_of_content_imgproc.markdown +++ b/doc/tutorials/imgproc/table_of_content_imgproc.markdown @@ -125,6 +125,8 @@ In this section you will learn about the image processing (manipulation) functio - @subpage tutorial_hough_lines + *Languages:* C++, Java, Python + *Compatibility:* \> OpenCV 2.0 *Author:* Ana Huamán diff --git a/samples/cpp/houghlines.cpp b/samples/cpp/houghlines.cpp deleted file mode 100644 index 94eec86..0000000 --- a/samples/cpp/houghlines.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "opencv2/imgcodecs.hpp" -#include "opencv2/highgui.hpp" -#include "opencv2/imgproc.hpp" - -#include - -using namespace cv; -using namespace std; - -static void help() -{ - cout << "\nThis program demonstrates line finding with the Hough transform.\n" - "Usage:\n" - "./houghlines , Default is ../data/pic1.png\n" << endl; -} - -int main(int argc, char** argv) -{ - cv::CommandLineParser parser(argc, argv, - "{help h||}{@image|../data/pic1.png|}" - ); - if (parser.has("help")) - { - help(); - return 0; - } - string filename = parser.get("@image"); - if (filename.empty()) - { - help(); - cout << "no image_name provided" << endl; - return -1; - } - Mat src = imread(filename, 0); - if(src.empty()) - { - help(); - cout << "can not open " << filename << endl; - return -1; - } - - Mat dst, cdst; - Canny(src, dst, 50, 200, 3); - cvtColor(dst, cdst, COLOR_GRAY2BGR); - -#if 0 - vector lines; - HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 ); - - 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)); - 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, CV_AA); - } -#else - vector lines; - HoughLinesP(dst, lines, 1, CV_PI/180, 50, 50, 10 ); - for( size_t i = 0; i < lines.size(); i++ ) - { - Vec4i l = lines[i]; - line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA); - } -#endif - imshow("source", src); - imshow("detected lines", cdst); - - waitKey(); - - return 0; -} diff --git a/samples/cpp/tutorial_code/ImgTrans/houghlines.cpp b/samples/cpp/tutorial_code/ImgTrans/houghlines.cpp new file mode 100644 index 0000000..57f64c6 --- /dev/null +++ b/samples/cpp/tutorial_code/ImgTrans/houghlines.cpp @@ -0,0 +1,89 @@ +/** + * @file houghclines.cpp + * @brief This program demonstrates line finding with the Hough transform + */ + +#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; + + //![load] + const char* default_file = "../../../data/sudoku.png"; + 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; + } + //![load] + + //![edge_detection] + // Edge detection + Canny(src, dst, 50, 200, 3); + //![edge_detection] + + // Copy edges to the images that will display the results in BGR + cvtColor(dst, cdst, COLOR_GRAY2BGR); + cdstP = cdst.clone(); + + //![hough_lines] + // Standard Hough Line Transform + vector lines; // will hold the results of the detection + HoughLines(dst, lines, 1, CV_PI/180, 150, 0, 0 ); // runs the actual detection + //![hough_lines] + //![draw_lines] + // 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)); + 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, CV_AA); + } + //![draw_lines] + + //![hough_lines_p] + // Probabilistic Line Transform + vector linesP; // will hold the results of the detection + HoughLinesP(dst, linesP, 1, CV_PI/180, 50, 50, 10 ); // runs the actual detection + //![hough_lines_p] + //![draw_lines_p] + // 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); + } + //![draw_lines_p] + + //![imshow] + // Show results + imshow("Source", src); + imshow("Detected Lines (in red) - Standard Hough Line Transform", cdst); + imshow("Detected Lines (in red) - Probabilistic Line Transform", cdstP); + //![imshow] + + //![exit] + // Wait and Exit + waitKey(); + return 0; + //![exit] +} diff --git a/samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java b/samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java new file mode 100644 index 0000000..c968d32 --- /dev/null +++ b/samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java @@ -0,0 +1,96 @@ +/** + * @file HoughLines.java + * @brief This program demonstrates line finding with the Hough transform + */ + +import org.opencv.core.*; +import org.opencv.core.Point; +import org.opencv.highgui.HighGui; +import org.opencv.imgcodecs.Imgcodecs; +import org.opencv.imgproc.Imgproc; + +class HoughLinesRun { + + public void run(String[] args) { + // Declare the output variables + Mat dst = new Mat(), cdst = new Mat(), cdstP; + + //! [load] + String default_file = "../../../../data/sudoku.png"; + String filename = ((args.length > 0) ? args[0] : default_file); + + // Load an image + Mat src = Imgcodecs.imread(filename, Imgcodecs.IMREAD_GRAYSCALE); + + // Check if image is loaded fine + if( src.empty() ) { + System.out.println("Error opening image!"); + System.out.println("Program Arguments: [image_name -- default " + + default_file +"] \n"); + System.exit(-1); + } + //! [load] + + //! [edge_detection] + // Edge detection + Imgproc.Canny(src, dst, 50, 200, 3, false); + //! [edge_detection] + + // Copy edges to the images that will display the results in BGR + Imgproc.cvtColor(dst, cdst, Imgproc.COLOR_GRAY2BGR); + cdstP = cdst.clone(); + + //! [hough_lines] + // Standard Hough Line Transform + Mat lines = new Mat(); // will hold the results of the detection + Imgproc.HoughLines(dst, lines, 1, Math.PI/180, 150); // runs the actual detection + //! [hough_lines] + //! [draw_lines] + // Draw the lines + for (int x = 0; x < lines.rows(); x++) { + double rho = lines.get(x, 0)[0], + theta = lines.get(x, 0)[1]; + + double a = Math.cos(theta), b = Math.sin(theta); + double x0 = a*rho, y0 = b*rho; + Point pt1 = new Point(Math.round(x0 + 1000*(-b)), Math.round(y0 + 1000*(a))); + Point pt2 = new Point(Math.round(x0 - 1000*(-b)), Math.round(y0 - 1000*(a))); + Imgproc.line(cdst, pt1, pt2, new Scalar(0, 0, 255), 3, Imgproc.LINE_AA, 0); + } + //! [draw_lines] + + //! [hough_lines_p] + // Probabilistic Line Transform + Mat linesP = new Mat(); // will hold the results of the detection + Imgproc.HoughLinesP(dst, linesP, 1, Math.PI/180, 50, 50, 10); // runs the actual detection + //! [hough_lines_p] + //! [draw_lines_p] + // Draw the lines + for (int x = 0; x < linesP.rows(); x++) { + double[] l = linesP.get(x, 0); + Imgproc.line(cdstP, new Point(l[0], l[1]), new Point(l[2], l[3]), new Scalar(0, 0, 255), 3, Imgproc.LINE_AA, 0); + } + //! [draw_lines_p] + + //! [imshow] + // Show results + HighGui.imshow("Source", src); + HighGui.imshow("Detected Lines (in red) - Standard Hough Line Transform", cdst); + HighGui.imshow("Detected Lines (in red) - Probabilistic Line Transform", cdstP); + //! [imshow] + + //! [exit] + // Wait and Exit + HighGui.waitKey(); + System.exit(0); + //! [exit] + } +} + +public class HoughLines { + public static void main(String[] args) { + // Load the native library. + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + new HoughLinesRun().run(args); + } +} diff --git a/samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py b/samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py new file mode 100644 index 0000000..2907996 --- /dev/null +++ b/samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py @@ -0,0 +1,79 @@ +""" +@file hough_lines.py +@brief This program demonstrates line finding with the Hough transform +""" +import sys +import math +import cv2 +import numpy as np + + +def main(argv): + ## [load] + default_file = "../../../../data/sudoku.png" + filename = argv[0] if len(argv) > 0 else default_file + + # Loads an image + src = cv2.imread(filename, cv2.IMREAD_GRAYSCALE) + + # Check if image is loaded fine + if src is None: + print ('Error opening image!') + print ('Usage: hough_lines.py [image_name -- default ' + default_file + '] \n') + return -1 + ## [load] + + ## [edge_detection] + # Edge detection + dst = cv2.Canny(src, 50, 200, None, 3) + ## [edge_detection] + + # Copy edges to the images that will display the results in BGR + cdst = cv2.cvtColor(dst, cv2.COLOR_GRAY2BGR) + cdstP = np.copy(cdst) + + ## [hough_lines] + # Standard Hough Line Transform + lines = cv2.HoughLines(dst, 1, np.pi / 180, 150, None, 0, 0) + ## [hough_lines] + ## [draw_lines] + # Draw the lines + if lines is not None: + for i in range(0, len(lines)): + rho = lines[i][0][0] + theta = lines[i][0][1] + a = math.cos(theta) + b = math.sin(theta) + x0 = a * rho + y0 = b * rho + pt1 = (int(x0 + 1000*(-b)), int(y0 + 1000*(a))) + pt2 = (int(x0 - 1000*(-b)), int(y0 - 1000*(a))) + + cv2.line(cdst, pt1, pt2, (0,0,255), 3, cv2.LINE_AA) + ## [draw_lines] + + ## [hough_lines_p] + # Probabilistic Line Transform + linesP = cv2.HoughLinesP(dst, 1, np.pi / 180, 50, None, 50, 10) + ## [hough_lines_p] + ## [draw_lines_p] + # Draw the lines + if linesP is not None: + for i in range(0, len(linesP)): + l = linesP[i][0] + cv2.line(cdstP, (l[0], l[1]), (l[2], l[3]), (0,0,255), 3, cv2.LINE_AA) + ## [draw_lines_p] + ## [imshow] + # Show results + cv2.imshow("Source", src) + cv2.imshow("Detected Lines (in red) - Standard Hough Line Transform", cdst) + cv2.imshow("Detected Lines (in red) - Probabilistic Line Transform", cdstP) + ## [imshow] + ## [exit] + # Wait and Exit + cv2.waitKey() + return 0 + ## [exit] + +if __name__ == "__main__": + main(sys.argv[1:])