【图像处理】——Python霍夫变换之直线检测(主要是两个函数Houghlines&HoughlinesP)
目录
一、原理(摘自《数字图像处理冈萨雷斯》)
即在xy平面上一条直线上的点在ab平面上是无数条直线组成的,而这些直线都会经过一个点,这个点的a,b值就是对应xy平面直线的截距与斜率
2、Python函数
参数详解
dst: 输出图像. 它应该是个灰度图 (但事实上是个二值化图)
lines: 储存着检测到的直线的参数对 (x_{start}, y_{start}, x_{end}, y_{end}) 的容器,结构如[[[x1,y1,x2,y2]],[[...]]]
rho : 参数极径 r 以像素值为单位的分辨率. 我们使用 1 像素.
theta: 参数极角 theta 以弧度为单位的分辨率. 我们使用 1度 (即CV_PI/180)
threshold: 控制检测出线段的条件。设置阈值: 一条直线所需最少的的曲线在一点相交,超过设定阈值才被检测出线段,值越大,基本上意味着检出的线段越长,检出的线段个数越少。因为阈值越大,超过阈值的点越少,即xy平面的直线越少,但是因为阈值越大,说明检测出在同一条直线上的点越多,即直线越长。这个参数是针对参数空间而言的,在参数空间中一条曲线就代表在xy平面上的一个点
minLinLength: 能组成一条直线的最少点的数量. 点数量不足的直线将被抛弃,其实这个参数的意义跟上一个很类似,只是这个参数是针对xy平面而言的,即当组成直线的点达到一点数量的时候才被检测出为线段,否则过滤掉
maxLineGap: 控制检测出直线长短,在同一条直线上的点,能够被连接的最大距离,越大得到的线越长,如下图,点在直线上,若此时距离maxlineGap小于设定的值,则连接,否则就不连接
"""
cv2.HoughLines()
dst: 输出图像. 它应该是个灰度图 (但事实上是个二值化图)
lines: 储存着检测到的直线的参数对 (r,\theta) 的容器
rho : 参数极径 r 以像素值为单位的分辨率. 我们使用 1 像素.
theta: 参数极角 \theta 以弧度为单位的分辨率. 我们使用 1度 (即CV_PI/180)
threshold: 设置阈值: 一条直线所需最少的的曲线交点
srn and stn: 参数默认为0
return:返回的是一个包含rho和theta的数组,[rho,theta]
cv2.HoughLinesP(dst, lines, 1, CV_PI/180, 50, 50, 10 )
dst: 输出图像. 它应该是个灰度图 (但事实上是个二值化图)
lines: 储存着检测到的直线的参数对 (x_{start}, y_{start}, x_{end}, y_{end}) 的容器
rho : 参数极径 r 以像素值为单位的分辨率. 我们使用 1 像素.
theta: 参数极角 \theta 以弧度为单位的分辨率. 我们使用 1度 (即CV_PI/180)
threshold: 设置阈值: 一条直线所需最少的的曲线交点。超过设定阈值才被检测出线段,值越大,基本上意味着检出的线段越长,检出的线段个数越少。
minLinLength: 能组成一条直线的最少点的数量. 点数量不足的直线将被抛弃.
maxLineGap: 能被认为在一条直线上的两点的最大距离。
return:返回的是含有一条直线的起始点和终点坐标[x1,y1,x2,y2]
"""
import cv2
import numpy as np
original_img= cv2.imread("jianzhu.png", 0)
img = cv2.resize(original_img,None,fx=0.8, fy=0.8,
interpolation = cv2.INTER_CUBIC)
img = cv2.GaussianBlur(img,(3,3),0)
edges = cv2.Canny(img, 50, 150, apertureSize = 3)
lines = cv2.HoughLines(edges,1,np.pi/180,118) #这里对最后一个参数使用了经验型的值
result = img.copy()
for line in lines:
rho = line[0][0] #第一个元素是距离rho
theta= line[0][1] #第二个元素是角度theta
print (rho)
print (theta)
if (theta < (np.pi/4. )) or (theta > (3.*np.pi/4.0)): #垂直直线
pt1 = (int(rho/np.cos(theta)),0) #该直线与第一行的交点
#该直线与最后一行的焦点
pt2 = (int((rho-result.shape[0]*np.sin(theta))/np.cos(theta)),result.shape[0])
cv2.line( result, pt1, pt2, (255)) # 绘制一条白线
else: #水平直线
pt1 = (0,int(rho/np.sin(theta))) # 该直线与第一列的交点
#该直线与最后一列的交点
pt2 = (result.shape[1], int((rho-result.shape[1]*np.cos(theta))/np.sin(theta)))
cv2.line(result, pt1, pt2, (255), 1) # 绘制一条直线
cv2.imshow('Canny', edges )
cv2.imshow('Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
3、效果
4、实例
# -*- coding: utf-8 -*-
import cv2
import numpy as np
#两个回调函数
def HoughLinesP(minLineLength):
tempIamge = scr.copy()
lines = cv2.HoughLinesP( edges, 1, np.pi/180,threshold=minLineLength,minLineLength=180,maxLineGap=40)
for x1,y1,x2,y2 in lines[:,0]:
cv2.line(tempIamge,(x1,y1),(x2,y2),(0,255,0),2)
print(lines)
cv2.imshow(window_name,tempIamge)
#临时变量
minLineLength = 20
#全局变量
# minLINELENGTH = 20
window_name = "HoughLines Demo"
#读入图片,模式为灰度图,创建窗口
scr = cv2.imread("22.jpg")
gray = cv2.cvtColor(scr,cv2.COLOR_BGR2GRAY)
print(gray.shape)
img = cv2.GaussianBlur(gray,(3,3),0)
edges = cv2.Canny(img, 50, 150, apertureSize = 3)
cv2.namedWindow(window_name)
#初始化
HoughLinesP(minLineLength)
if cv2.waitKey(0) == 27:
cv2.destroyAllWindows()
maxLineGap = 10:
maxLineGap = 30:
maxLineGap = 40:
当maxLineGap = 40时,直线基本上被完整地检测出来了
5、Houghlines和HoughLinesP的区别
https://www.cnblogs.com/bjxqmy/p/12331656.html
6、参考文献
https://www.cnblogs.com/dyllove98/archive/2013/07/12/3186872.html
https://www.cnblogs.com/bjxqmy/p/12331656.html
https://blog.csdn.net/wsp_1138886114/article/details/82936218