理解霍夫变换的概念
学习如何在一张图片中检测直线
学习函数: cv2.HoughLines(), cv2.HoughLinesP()
霍夫变换在检测各种形状的的技术中非常流行,如果你要检测的形状可以用数学表达式写出,你就可以是使用霍夫变换检测它。及时要检测的形状存在一点破坏或者扭曲也可以使用。我们下面就看看如何使用霍夫变换检测直线。
一条直线可以用数学表达式 y = mx + c 或者 ρ = x cos θ + y sin θ 表示。ρ 是从原点到直线的垂直距离, θ 是直线的垂线与横轴顺时针方向的夹角(如果你使用的坐标系不同方向也可能不同,我是按 OpenCV 使用的坐标系描述的)。如下图所示:
上面介绍的整个过程在 OpenCV 中都被封装进了一个函数:cv2.HoughLines()。返回值就是(ρ; θ)。 ρ 的单位是像素, θ 的单位是弧度。这个函数的第一个参数是一个二值化图像,所以在进行霍夫变换之前要首先进行二值化,或者进行Canny 边缘检测,第二和第三个值分别代表 ρ 和 θ 的精确度,第四个参数是阈值,只有累加其中的值高于阈值时才被认为是一条直线,也可以把它看成能检测到的直线的最短长度(以像素点为单位)。
import cv2
import numpy as np
img = cv2.imread('image/6.png',0)
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[0]:
rho = line[0]
theta = line[1]
print rho
print theta
if (theta < (np.pi/4.0)) or (theta > (3.0*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()
从上边的过程我们可以发现:仅仅是一条直线都需要两个参数,这需要大量的计算。 Probabilistic_Hough_Transform 是对霍夫变换的一种优化。它不会对每一个点都进行计算,而是从一幅图像中随机选取(是不是也可以使用图像金字塔呢?)一个点集进行计算,对于直线检测来说这已经足够了。但是使用这种变换我们必须要降低阈值(总的点数都少了,阈值肯定也要小呀!)。
下图是对两种方法的对比。(Image Courtesy : Franck Bettinger’s homepage)
import cv2
import numpy as np
img = cv2.imread('image/5.png')
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()
minLineLength = 200
maxLineGap = 15
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 80,minLineLength,maxLineGap)
for x1,y1,x2,y2 in lines[0]:
cv2.line(img, (x1,y1), (x2,y2), (0,255,0),2)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果图:
参考:Opencv官方教程中文版(For Python)
http://blog.csdn.net/sunny2038/article/details/9253823