Tutorial Hough Lines

This commit is contained in:
tribta 2017-08-27 00:02:29 +01:00
parent d99ced6ec8
commit 9a2317e063
8 changed files with 417 additions and 157 deletions

View File

@ -1,12 +1,15 @@
Hough Line Transform {#tutorial_hough_lines} Hough Line Transform {#tutorial_hough_lines}
==================== ====================
@prev_tutorial{tutorial_canny_detector}
@next_tutorial{tutorial_hough_circle}
Goal Goal
---- ----
In this tutorial you will learn how to: 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. image.
Theory 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 - 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$ 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** b. **The Probabilistic Hough Line Transform**
- A more efficient implementation of the Hough Line Transform. It gives as output the extremes - 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$ 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 Code
---- ----
-# **What does this program do?** @add_toggle_cpp
- Loads an image The sample code that we will explain can be downloaded from
- Applies either a *Standard Hough Line Transform* or a *Probabilistic Line Transform*. [here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgTrans/houghlines.cpp).
- Display the original image and the detected line in two windows. 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
-# 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 @add_toggle_java
(which shows both Hough standard and probabilistic with trackbars for changing the threshold The sample code that we will explain can be downloaded from
values) can be found [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp). [here](https://raw.githubusercontent.com/opencv/opencv/master/samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java).
@include samples/cpp/houghlines.cpp @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 Explanation
----------- -----------
-# Load an image #### 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** @add_toggle_cpp
-# First, you apply the Transform: @snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp load
@code{.cpp} @end_toggle
vector<Vec2f> lines;
HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 ); @add_toggle_java
@endcode @snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java load
with the following arguments: @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 - *dst*: Output of the edge detector. It should be a grayscale image (although in fact it
is a binary one) is a binary one)
@ -137,28 +179,35 @@ Explanation
- *threshold*: The minimum number of intersections to "*detect*" a line - *threshold*: The minimum number of intersections to "*detect*" a line
- *srn* and *stn*: Default parameters to zero. Check OpenCV reference for more info. - *srn* and *stn*: Default parameters to zero. Check OpenCV reference for more info.
-# And then you display the result by drawing the lines. And then you display the result by drawing the lines.
@code{.cpp} @add_toggle_cpp
for( size_t i = 0; i < lines.size(); i++ ) @snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp draw_lines
{ @end_toggle
float rho = lines[i][0], theta = lines[i][1];
Point pt1, pt2; @add_toggle_java
double a = cos(theta), b = sin(theta); @snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java draw_lines
double x0 = a*rho, y0 = b*rho; @end_toggle
pt1.x = cvRound(x0 + 1000*(-b));
pt1.y = cvRound(y0 + 1000*(a)); @add_toggle_python
pt2.x = cvRound(x0 - 1000*(-b)); @snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py draw_lines
pt2.y = cvRound(y0 - 1000*(a)); @end_toggle
line( cdst, pt1, pt2, Scalar(0,0,255), 3, LINE_AA);
} #### Probabilistic Hough Line Transform
@endcode First you apply the transform:
-# **Probabilistic Hough Line Transform**
-# First you apply the transform: @add_toggle_cpp
@code{.cpp} @snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp hough_lines_p
vector<Vec4i> lines; @end_toggle
HoughLinesP(dst, lines, 1, CV_PI/180, 50, 50, 10 );
@endcode @add_toggle_java
with the arguments: @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 - *dst*: Output of the edge detector. It should be a grayscale image (although in fact it
is a binary one) is a binary one)
@ -172,23 +221,47 @@ Explanation
this number of points are disregarded. this number of points are disregarded.
- *maxLineGap*: The maximum gap between two points to be considered in the same line. - *maxLineGap*: The maximum gap between two points to be considered in the same line.
-# And then you display the result by drawing the lines. And then you display the result by drawing the lines.
@code{.cpp}
for( size_t i = 0; i < lines.size(); i++ ) @add_toggle_cpp
{ @snippet samples/cpp/tutorial_code/ImgTrans/houghlines.cpp draw_lines_p
Vec4i l = lines[i]; @end_toggle
line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA);
} @add_toggle_java
@endcode @snippet samples/java/tutorial_code/ImgTrans/HoughLine/HoughLines.java draw_lines_p
-# Display the original image and the detected lines: @end_toggle
@code{.cpp}
imshow("source", src); @add_toggle_python
imshow("detected lines", cdst); @snippet samples/python/tutorial_code/ImgTrans/HoughLine/hough_lines.py draw_lines_p
@endcode @end_toggle
-# Wait until the user exits the program
@code{.cpp} #### Display the original image and the detected lines:
waitKey();
@endcode @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 Result
------ ------
@ -198,13 +271,11 @@ Result
section. It still implements the same stuff as above, only adding the Trackbar for the section. It still implements the same stuff as above, only adding the Trackbar for the
Threshold. Threshold.
Using an input image such as: 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_Tutorial_Original_Image.jpg) ![](images/hough_lines_result1.png)
And by using the Probabilistic Hough Line Transform:
We get the following result by using the Probabilistic Hough Line Transform: ![](images/hough_lines_result2.png)
![](images/Hough_Lines_Tutorial_Result.jpg)
You may observe that the number of lines detected vary while you change the *threshold*. The 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 explanation is sort of evident: If you establish a higher threshold, fewer lines will be detected

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -125,6 +125,8 @@ In this section you will learn about the image processing (manipulation) functio
- @subpage tutorial_hough_lines - @subpage tutorial_hough_lines
*Languages:* C++, Java, Python
*Compatibility:* \> OpenCV 2.0 *Compatibility:* \> OpenCV 2.0
*Author:* Ana Huamán *Author:* Ana Huamán

View File

@ -1,77 +0,0 @@
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
static void help()
{
cout << "\nThis program demonstrates line finding with the Hough transform.\n"
"Usage:\n"
"./houghlines <image_name>, 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<string>("@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<Vec2f> 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<Vec4i> 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;
}

View File

@ -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<Vec2f> 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<Vec4i> 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]
}

View File

@ -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);
}
}

View File

@ -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:])