利用Opencv中Houghline方法实现直线检测

yipeiwu_com5年前Python基础

利用Opencv中的Houghline方法进行直线检测—python语言

这是给Python部落翻译的文章,请在这里看原文

在图像处理中,霍夫变换用来检测任意能够用数学公式表达的形状,即使这个形状被破坏或者有点扭曲。

下面我们将看到利用HoughLine算法来阐述霍夫变化进行直线检测的原理,把此算法应用到特点图像的边缘检测是可取的。边缘检测方法请参考这篇文章–边缘检测

Houghline算法基础

直线可以表示为y=mx+c,或者以极坐标形式表示为r=xcosθ+ysinθ,其中r是原点到直线的垂直距离,θ是水平轴顺时针方向到垂直线的夹角(这个方向取决于坐标的形式,在OpenCV就是采用这种极坐标形式)。

因此任意的曲线都可以用两个参数(r,θ)表示。

HoughLine算法原理:

  • 首先建立一个二维的数组或者累加器(用来保存这两个参数),并初始化为零;
  • 这个二维数组的行代表不同的r,而列代表角度θ;
  • 数组的大小取决于算法的精度。假设所需角度的精度精确到1∘,那么就需要180列(直线的最大角度是180)。
  • 对于r,最大的可能距离是图像的对角长度,因此若需要一个像素的精度,那么需要把行数设为图像对角线的长度。

例子:

假设一幅100x100的图像,在图像中间有一条水平直线。设直线的第一个点的坐标为(x,y),在直线方程中,令参数θ=0,12,⋯,180,观查参数r变化。对每一个参数对(r,θ),在累加器中将(r,θ)对应的单元格中的值递增1,比如现在在累加器中,某个单元(50,90)的值等于1,其它的值也如此。

对于直线上的第二个点,重复上述操作。将得到的参数对(r,θ)的对应值继续递增,然后(50,90)对应的值等于2。实现上我们是对参数对(r,θ)进行投票,对直线上的每一个点重复上述操作,对每一个点,单元格(50,90)对应的值会递增,或者说投票给参数对(50,90),而会或者不会投票给其它参数对。以这种方式,最后单元格(50,90)的值将会是最大的值。然后搜索累加器的最大值,将会找到参数对(50,90)。也就是说,在图像中找到了到原点距离为50,角度为90的一条直线。

上述算法的过程被封装成OpenCV函数cv2.HoughLines(),函数返回(r,θ)的一个数组,其中r的单位为像素,θ的单位为弧度。

# 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('xyz.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]:

 # 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('houghlines3.jpg', img)

函数(cv2.HoughLines(edges, 1, np.pi/180,200))

  • 第一个参数是输入图像,且必须是二值图像,在进行霍夫变换之前需要采用阈值方法的边缘检测;
  • 第二和第三个参数分别是r,θ对应的精度;
  • 第四个参数是阈值,判定为直线投票数的最小值;
  • 注意,投票数取决于直线上点的个数,因此这个阈值代表了检测到的直线的最短长度。

总结

  • 在图像分析应用中,边缘分割点的坐标(即X,Y)是已知的,在直线的参数方程中作为输入,而r,θ是我们要找的未知变量;
  • 对每一个角度θ,求出r的值,也就是将笛卡尔图像空间的点映射到霍夫参数极坐标空间的曲线,这种点到曲线的变换就是直线的霍夫变换;
  • 这种变换是通过量化霍夫参数为有限的间隔或者累加器单元来实现的,随着算法的运行,每一个(X,Y)转换成离散的(r,θ)曲线,曲线上的点对应的累加器(二维数组)的值会递增;
  • 累加器中的峰值就代表了图像中有相应直线的存在。

霍夫变换的应用

  • 用于分离图像中特殊形状的特征;
  • 可以容忍特征边界描述的误差,并且不受噪声的干扰;
  • 广泛用于条形码扫描、验证和识别。

文章作者是Pratima Upadhyay,如果你喜欢GeeksforGeeks,并且愿意分享,可以利用contribute.geeksforgeeks.org写文章,然后发送到contribute@geeksforgeeks.org,在GeeksforGeeks中看到自己的文章,帮助更多的Geeks。

若发现错误欢迎指正,也欢迎评论。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持【听图阁-专注于Python设计】。

相关文章

Python处理RSS、ATOM模块FEEDPARSER介绍

由于Google reader的关闭,这段时间接触rss的东西相对多很多。试过qq的reader,不怎么样,阅读速度没有,是否阅读的标记也没有。其他网站的不想用,又要多注册账户。 找到p...

Python实现点云投影到平面显示

值得学习的地方: 1.选择合法索引的方式 2.数组转图像显示 import numpy as np from PIL import Image #input : shape(N,...

Django REST为文件属性输出完整URL的方法

前言 我的 App 项目的 API 部分是使用 Django REST Framework 来搭建的,它可以像搭积木一样非常方便地搭出 API,兼具方便和灵活。 django是一个神奇的...

python3中rank函数的用法

网上存在这么一个例子 obj = pd.Series([7,-5,7,4,2,0,4]) obj.rank() 输出为: 0 6.5 1 1.0 2 6.5 3 4....

Python 闭包的使用方法

Python 闭包的使用方法 嵌套函数中的非局部变量 在进入闭包之前,我们必须先了解一个嵌套函数和非局部变量。 在函数中定义另一个函数称为嵌套函数。嵌套函数可以访问包围范围内的变量。 在...