What is the Hough transform

The Hough transform is a way of finding lines, circles, and other simple shapes in an image. Hough transform, which was first proposed by Paul Hough (Hough) in 1962, uses a method similar to voting to obtain the set of shapes in the current image.

The original Hough transform can only be used to detect straight lines. After development, hough transform can not only identify straight lines, but also identify other simple graphic structures, such as circles and ellipses.

HoughLines function

In OpenCV, it provides us with the cv2.houghlines () function to implement the Hough line transformation. This function requires that the original image of all operations is a binary image, so the image needs to be binarization before the Hough transformation. Or Canny edge detection.

Its full definition is as follows:

def HoughLines(image, rho, theta, threshold, lines=None, srn=None, stn=None, min_theta=None, max_theta=None) :
Copy the code

Image: raw graphics, must be 8-bit single-channel binary image

Rho: The precision of the distance r in pixels. In general, the accuracy used is 1

Theta: is the accuracy of Angle θ. In general, the precision used is π /180, which means that all possible angles are searched

Threshold: indicates the threshold. The smaller this value is, the more lines will be identified. To identify a line, determine how many points lie on it. When determining whether the line exists, the number of points that the line passes through is evaluated. If the number of points that the line passes through is less than the threshold value, it is considered that these points just constitute the line in the algorithm, but the line does not exist in the original image. If it is greater than the threshold, the line is considered to exist. So, the smaller the threshold, the more straight lines you get; The bigger the threshold, the fewer lines you get

Lines: Returns the value, each element of which is a pair of floating-point numbers representing the argument to the detected line, that is, (r,θ). It is of type NUMpy. Ndarray.

HoughLines of actual combat

After understanding the common parameters of the function. Now, let’s do the Hough transform with a chessboard. The code is as follows:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("35.jpg")
plt.subplot(121)
plt.imshow(img, cmap="gray")
plt.axis('off')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50.150, apertureSize=3)

lines = cv2.HoughLines(edges, 1, np.pi / 180.140)
for line in lines:
    rho, theta = line[0]
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a * rho
    y0 = b * rho
    x1 = int(x0 + 1000 * (-b))
    y1 = int(y0 + 1000 * (a))
    x2 = int(x0 - 1000 * (-b))
    y2 = int(y0 - 1000 * (a))
    cv2.line(img, (x1, y1), (x2, y2), (0.255.0), 2)
plt.subplot(122)
plt.imshow(img, cmap="gray")
plt.axis('off')
plt.show()
Copy the code

After running, the effect is as follows:

HoughLinesP of actual combat

Although HoughLines can be used to complete the Hough transform, it has serious error detection. To solve this problem, OpenCV adds the probability Hough transform function cv2.houghlinesp ().

Its full definition is as follows:

def HoughLinesP(image, rho, theta, threshold, lines=None, minLineLength=None, maxLineGap=None) : 
Copy the code

Image: the original image, such as an 8-bit single-channel binary image

Rho: same as above

Theta: same as above

Threshold: same as above

The above lines:

MinLineLength: Controls the minimum length of a line to accept. The default value is 0

MaxLineGap: To control the minimum interval between accepted collinear segments, that is, the maximum distance between two points in a line. If the distance between two points exceeds the value of the maxLineGap parameter, the two points are not considered to be in a straight line. The default value is 0

Take the above example and use HoughLinesP to improve the following:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("35.jpg")
plt.subplot(121)
plt.imshow(img, cmap="gray")
plt.axis('off')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50.150, apertureSize=3)

lines = cv2.HoughLinesP(edges, 1, np.pi / 180.10.10)
for line in lines:
    x1, y1, x2, y2 = line[0]
    cv2.line(img, (x1, y1), (x2, y2), (255.0.0), 5)
plt.subplot(122)
plt.imshow(img, cmap="gray")
plt.axis('off')
plt.show()
Copy the code

After running, the effect is as follows:

As you can see, here we’ve marked the board lines completely with the HoughLinesP function.

HoughCircles of actual combat

The Hough transform is used to detect lines, and we can use it to detect other geometric objects. In fact, any object that can be represented by an equation is suitable for detection by the Hough transform.

Where, we can use hough circle transform to detect the circle in the image. Here we only have to consider the center coordinates (x, y) and the radius r.

In OpenCV there are two steps:

  1. Find out where a circle might exist (center of a circle)
  2. Calculate the radius based on 1

In OpenCV, it provides us with the HoughCircle transformation function cv2.houghcircle (). The function is also a combination of Canny edge detection and Hough transform, the only difference is that we do not need to Canny edge detection, the function automatically first Canny edge detection.

Its full definition is as follows:

def HoughCircles(image, method, dp, minDist, circles=None, param1=None, param2=None, minRadius=None, maxRadius=None) : 
Copy the code

Image: original image, 8-bit single-channel grayscale image

Method: Indicates the detection method. HOUGH_GRADIENT is the only available parameter value. This parameter represents the method used for two rounds of detection in hough circle detection

Dp: Accumulator resolution, which is a segmentation ratio that specifies the ratio of the image resolution to the resolution of the center of the circle accumulator. For example, if DP =1, the input image and the accumulator have the same resolution

MinDist: minimum spacing between centers. This value is used as a threshold. If there are multiple circles with center spacing smaller than this value, only one will be detected. Therefore, if the value is too small, many adjacent circles will be detected; If the value is large, many circles may be missed during detection

Circles: return value of type numpy. Ndarray with center coordinates and radius.

Param1: The default value is 100. It corresponds to the high threshold of the Canny edge detector (the low threshold is one half of the high threshold)

Param2: indicates the number of votes that the center of the circle must receive. Only in the first selection process, the number of votes over the value of the circle is eligible for the second round of selection. Therefore, the larger the value, the fewer circles detected; The smaller the value, the more circles are detected. It’s also the default value, which is 100

MinRadius: The minimum radius of a circle. Circles less than this value are not detected. It’s also the default, which is 0. It doesn’t work

MaxRadius: indicates the maximum radius of a circle. Circles larger than this value will not be detected. It’s also the default, which is 0. It doesn’t work

Next, let’s take a photo of the Olympic rings and transform the Hoff circle. The code is as follows:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("35_1.jpg")
plt.subplot(121)
plt.imshow(img, cmap="gray")
plt.axis('off')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.300, param1=50, param2=20,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0, :]:
    cv2.circle(img, (i[0], i[1]), i[2], (255.0.0), 12)
    cv2.circle(img, (i[0], i[1]), 2, (255.0.0), 12)

plt.subplot(122)
plt.imshow(img, cmap="gray")
plt.axis('off')
plt.show()
Copy the code

After running, the effect is as follows: