hough变换_Hough直线变换

一条直线可以由y=ax+c或者ρ=xcosθ+ysinθ表示。给出极坐标系中的一个点(ρ,θ),可以唯一确定直角坐标系中的一条直线,其中ρ表示直角坐标系下直线到原点O的距离,θ表示直角坐标系下直线和原点间的垂线与x轴正向的夹角。或者说,直角坐标系中的直线在极坐标系下表示为一个点。这即是极坐标系和直角坐标系的点-线对偶性

利用Hough变换检测直线

直角坐标系中的一条直线对应于极坐标系下的一个点。这里的直角坐标系对应于原始图像空间,极坐标系对应于参数空间(也叫Hough空间)。

· 给定一幅图像,如下所示,图像中有一条直线

f21634fea7e864308ce73b6b2d6cede0.png

首先进行边缘检测,找出边缘点,如下图所示,红色的点表示边缘点

59b1eceee141b6e402f98409de46b25e.png

对于任何一个边缘点,找到所有可能经过该点的直线,这些直线都各自对应着参数空间中的一个点,而该边缘点的无穷多条直线对应于参数空间中的点将形成一条参数空间中的曲线。如下左边两图所示,原始图像空间中绿色的直线在参数空间中对应的点是(r2,θ2),原始图像空间中蓝色的直线在参数空间中对应的点是(r1,θ1)。如下右边两图所示,找出经过该边缘点的所有直线,列出各直线在参数空间中的点,这些点可以连接成一条曲线。

25bbf58bbaf697733741dc4afa5b6785.png

6c69e04954ac1ad51a644bf7ce21469d.png

曲线如下图所示,最终我们可以用这条曲线来表示所有可能经过第1个边缘点的直线

8852ab4ce7646a61410b2388fcfd5600.png

重复上述过程,画出所有边缘点的曲线,每个边缘点都对应着参数空间中的一条曲线。那么,参数空间中所有这些曲线的交点一定是原始图像空间中所有边缘点的共同直线。或者说某个交点经过的曲线最多(此处涉及到表决,如何判断这个交点经过的曲线最多),那么这个交点很有可能表示原始图像中的直线。得到这个交点的坐标(ρ,θ)之后,根据方程ρ=xcosθ+ysinθ,可以计算出直角坐标系下的直线,然后在原始图像中标出直线,达到检测直线的目的。

4b83f2cf4dbc17f71074565db0342fd3.png

在使用霍夫线变换之前,首先要对图像进行边缘检测的处理,即霍夫线变换的直接输入只能是边缘二值图像。

void HoughLines(inputArray,outputArray,double rho,double theta,int threshold,double srn=0,double stn=0)

使用函数cv2.HoughLines(),返回(ρ,θ),ρ的单位是像素,θ是弧度

line[0]存储的是点到直线的极径和极角,其中极角是弧度表示的

*第一个参数,输入图像,需为8位的单通道二进制图像。

*第二个参数,存储了霍夫线变换检测到线条的输出矢量,每一条线由具有两个元素的矢量(r,θθ)表示。

*第三个参数,以像素为单位的距离精度,也就是直线搜索时的进步尺寸的单位半径。一般为1

*第四个参数,以弧度为单位的角度精度,也就是直线搜索时的进步尺寸的单位角度。一般为CV_PI/180

*第五个参数,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。一般为150

*第六个参数,对于多尺度的霍夫变换,这是第三个参数进步尺寸rho的除数距离,粗略的累加器进步尺寸秩解释第三个参数rho,而精确的累加器进步尺寸为rho/srn。

*第七个参数,对于多尺度霍夫变换,stn表示第四个参数进步尺寸的单位角度theta的除数距离。

def line_detection(image):

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

edges = cv2.Canny(gray, 50, 150, apertureSize=3) # apertureSize参数默认其实就是3

cv2.imshow("edges", edges)

# houghlines函数是将点连成线,输出一个结构体,结构体包含每条直线的端点,长度,theta和rho值。第二个参数为直线的半径,建议选1,第三个参数为步长为π/180的角来搜索所以可能的直线。第四个参数是阈值,只有当累加器中的值高于阈值时才被当成是直线。也可以把它看成能检测到的直线的最短长度(以像素点为单位)

lines = cv2.HoughLines(edges, 1, np.pi/180, 150)

for line in lines:

rho, theta = line[0] # line[0]存储的是点到直线的极径和极角,其中极角是弧度表示的

a = np.cos(theta) # theta是弧度

b = np.sin(theta)

x0 = a*rho # 代表x=r*cos(theta)

y0 = b*rho # 代表y=r*sin(theta)

x1 = int(x0 + 1000*(-b)) # 计算直线起点的横坐标

y1 = int(y0 + 1000*a) # 计算起始点的纵坐标

x2 = int(x0 - 100*(-b)) # 计算直线终点横坐标

y2 = int(y0 - 1000*a) # 计算直线终点纵坐标

# 注:这里的数值1000给出了画出的线段长度范围大小,数值越小,画出的线段越短,数值越大,画出的线段越长

cv2.line(image, (x1, y1), (x2, y2), (0, 0, 255), 2)

cv2.imshow("image-line", image)

# 统计概率霍夫线变换:这是执行起来效率更高的霍夫线变换. 它输出检测到的直线的端点 (x0, y0, x1, y1)

def line_detect_possible_demo(image):

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

edges = cv2.Canny(gray, 50, 150, apertureSize=3)

'''

HoughLinesP函数参数,第四个表示检测一条直线所需最少的曲线交点

minLineLength参数表示能组成一条直线的最少点的数量,点数量不足的直线将被抛弃。

maxLineGap参数表示能被认为在一条直线上的亮点的最大距离。

'''

lines = cv2.HoughLinesP(edges, 1, np.pi/180, 60, minLineLength=60, maxLineGap=5)

for line in lines:

x1, y1, x2, y2 = line[0]

cv2.line(image, (x1, y1), (x2, y2), (0, 0, 255), 2)

cv2.imshow("line_detect_possible_demo", image)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值