Hough变换是一种在图像处理中用于检测任何形状的方法,前提是该形状可以用数学形式表示。即使形状有点破损或变形,它也能检测到。 我们将看到Hough变换如何使用HoughLine变换方法进行直线检测。为了应用Houghline方法,首先需要对特定图像进行边缘检测。对于边缘检测技术,请通读本文 边缘检测
Houghline方法基础
直线可以表示为y=mx+c或参数形式,如r=xcosθ+ysinθ,其中r是从原点到直线的垂直距离,θ是该垂直线与水平轴形成的角度,以逆时针方向测量(该方向随坐标系的表示方式而变化。此表示用于OpenCV)。
所以任何一条线都可以用这两项来表示,(r,θ)。 Houghline方法的工作原理:
- 首先,它创建一个二维数组或累加器(用于保存两个参数的值),并在初始设置为零。
- 让行表示r,列表示(θ)θ。
- 阵列的大小取决于所需的精度。假设希望角度的精度为1度,则需要180列(直线的最大角度为180)。
- 对于r,最大可能的距离是图像的对角线长度。因此,以一个像素的精度,行数可以是图像的对角线长度。
例子: 考虑一个100×100的图像,中间有一条水平线。以这条线的第一个点为例。你知道它的(x,y)值。现在在直线方程中,把θ(θ)=0,1,2,…。,180并检查你得到的r。对于每个(r,0)对,在累加器中相应的(r,0)单元格中增加一个值。现在在累加器中,电池(50,90)=1和其他一些电池。 现在再看第二点。如上所述。增加对应于(r,0)的单元格中的值。这一次,单元格(50,90)=2。我们实际上是在投票(r,0)值。您可以对线上的每个点继续此过程。在每一点上,单元格(50,90)都将递增或递增,而其他单元格可能会或可能不会递增。这样,到最后,单元格(50,90)将拥有最多的投票权。因此,如果你搜索累加器的最大投票数,你会得到一个值(50,90),这个值表示,在这张图像中,有一条线距离原点50,角度90度。
上面解释的所有内容都封装在OpenCV函数cv2中。HoughLines()。它只返回一个(r,0)值数组。r以像素为单位,0以弧度为单位。
python
# Python program to illustrate HoughLine # method for line detection import cv2 import numpy as np # Reading the required image in # which operations are to be done. # Make sure that the image is in the same # directory in which this python program is img = cv2.imread( 'image.jpg' ) # Convert the img to grayscale gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # Apply edge detection method on the image edges = cv2.Canny(gray, 50 , 150 ,apertureSize = 3 ) # This returns an array of r and theta values lines = cv2.HoughLines(edges, 1 ,np.pi / 180 , 200 ) # The below for loop runs till r and theta values # are in the range of the 2d array for r_theta in lines[ 0 ]: r,theta = r_theta[ 0 ] # Stores the value of cos(theta) in a a = np.cos(theta) # Stores the value of sin(theta) in b b = np.sin(theta) # x0 stores the value rcos(theta) x0 = a * r # y0 stores the value rsin(theta) y0 = b * r # x1 stores the rounded off value of (rcos(theta)-1000sin(theta)) x1 = int (x0 + 1000 * ( - b)) # y1 stores the rounded off value of (rsin(theta)+1000cos(theta)) y1 = int (y0 + 1000 * (a)) # x2 stores the rounded off value of (rcos(theta)+1000sin(theta)) x2 = int (x0 - 1000 * ( - b)) # y2 stores the rounded off value of (rsin(theta)-1000cos(theta)) y2 = int (y0 - 1000 * (a)) # cv2.line draws a line in img from the point(x1,y1) to (x2,y2). # (0,0,255) denotes the colour of the line to be #drawn. In this case, it is red. cv2.line(img,(x1,y1), (x2,y2), ( 0 , 0 , 255 ), 2 ) # All the changes made in the input image are finally # written on a new image houghlines.jpg cv2.imwrite( 'linesDetected.jpg' , img) |
功能细化(cv2.HoughLines(Edge,1,np.pi/180200)):
- 第一个参数,输入图像应该是一个二值图像,所以在应用hough变换查找之前应用阈值边缘检测。
- 第二和第三个参数分别是r和θ(θ)精度。
- 第四个参数是阈值,这意味着它应该获得的最低投票权,才能被视为一条线。
- 记住,投票数取决于线上的点数。所以它代表了应该被检测到的线的最小长度。
直接提取点的另一种更简单的方法:
Python3
import cv2 import numpy as np # Read image image = cv2.imread( 'path/to/image.png' ) # Convert image to grayscale gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) # Use canny edge detection edges = cv2.Canny(gray, 50 , 150 ,apertureSize = 3 ) # Apply HoughLinesP method to # to directly obtain line end points lines = cv2.HoughLinesP( edges, # Input edge image 1 , # Distance resolution in pixels np.pi / 180 , # Angle resolution in radians threshold = 100 , # Min number of votes for valid line minLineLength = 5 , # Min allowed length of line maxLineGap = 10 # Max allowed gap between line for joining them ) # Iterate over points for points in lines: # Extracted points nested in the list x1,y1,x2,y2 = points[ 0 ] # Draw the lines joing the points # On the original image cv2.line(image,(x1,y1),(x2,y2),( 0 , 255 , 0 ), 2 ) # Maintain a simples lookup list for points lines_list.append([(x1,y1),(x2,y2)]) # Save the result image cv2.imwrite( 'detectedLines.png' ,image) |
总结过程
- 在图像分析环境中,图像中边缘段(即X,Y)的点坐标是已知的,因此在参数线方程中用作常数,而R(rho)和θ(θ)是我们寻求的未知变量。
- 如果我们绘制每个(θ)定义的可能(r)值,笛卡尔图像空间中的点映射到极性霍夫参数空间中的曲线(即正弦曲线)。这种点到曲线的变换是直线的Hough变换。
- 该变换通过将Hough参数空间量化为有限区间或累加器单元来实现。当算法运行时,每个(X,Y)被转换成一条离散的(r,0)曲线,沿着该曲线的累加器(2D数组)单元递增。
- 累加器阵列中产生的峰值有力地证明了图像中存在相应的直线。
Hough变换的应用:
- 它用于隔离图像中特定形状的特征。
- 能够容忍特征边界描述中的间隙,并且相对不受图像噪声的影响。
- 广泛用于条形码扫描、验证和识别
本文由 普拉蒂玛·乌帕迪亚 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 写极客。组织 或者把你的文章寄去评论-team@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。