1. 介绍霍夫变换
霍夫变换是一种经典的计算机视觉算法,常用来识别图像中的直线和圆等基本几何形状。霍夫变换的基本思想是将原始图像中的每个像素进行变换,变换后的结果是一个参数空间(Hough Space),它与原始图像可以建立对应关系,霍夫变换就是通过在参数空间中对像素进行计数,然后根据像素点的最大值匹配出对应的几何形状。
1.1 表示一条直线
霍夫变换最常见的应用是检测直线,我们可以将一条直线表示为:
y = mx + b
其中m表示直线斜率,b表示直线截距。
在霍夫变换中,我们使用两个参数来表示一条直线,即:
参数r:表示直线距离原点的距离
参数theta:表示直线与x轴的夹角
对于每条直线,我们可以在参数空间中用一个点来表示。对于每一个在直线上的点(x,y),我们可以计算出对应的r和theta:
r = x * cos(theta) + y * sin(theta)
这个方程式在数学中被称作极坐标方程式,它将直线的表示从直角坐标系转换到了极坐标系。
1.2 表示一条圆
同样的,我们也可以使用霍夫变换来检测圆。以Cartesian坐标表示一个圆心为(c_x,c_y),半径为r的圆。则它可以被表示为:
(x-c_x)^2 + (y-c_y)^2 = r^2
我们可以将该公式转换成极坐标系下的形式:
x = c_x + r*cos(theta)
y = c_y + r*sin(theta)
将上述方程式转化成三个参数:
r:圆心到圆心的距离
theta_c:圆心在单位圆上的极角
theta_p:该圆上的一点在单位圆上的极角
在参数空间中,可以用一个三元组(r,theta_c,theta_p)来表示圆的所有可能。
2. 霍夫变换的实现
2.1 霍夫变换检测直线
在OpenCV中,计算霍夫变换可以使用函数cv2.HoughLines(),它有四个参数:
第一个参数是一个二值化图像,即只有非黑即白的图像。
第二个参数rho表示以像素为单位的距离精度,一般取1。
第三个参数theta表示以弧度为单位的角度精度,一般取pi/180。
第四个参数threshold表示直线的最短长度,超过threshold才被认为是直线。
下面是一个简单的例子,假设我们有一张图片,我们需要在图片中检测出直线:
import cv2
import numpy as np
img = cv2.imread('lines.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
cv2.imshow('edges',edges)
lines = cv2.HoughLines(edges,1,np.pi/180,200)
for line in lines:
rho,theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 1000*(-b))
y1 = int(y0 + 1000*(a))
x2 = int(x0 - 1000*(-b))
y2 = int(y0 - 1000*(a))
cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
上述程序一共有三个部分:
首先读入一个图片,将其转化为灰度图。
通过Canny边缘检测找到所有的边缘。
使用霍夫变换检测所有的直线,并在图片上画出。
运行后的图片如下所示:
2.2 霍夫变换检测圆
在OpenCV中,计算霍夫变换可以使用函数cv2.HoughCircles(),它有五个参数:
第一个参数是一个二值化图像,即只有非黑即白的图像。
第二个参数表示使用的检测方法,一般选默认值cv2.HOUGH_GRADIENT。
第三个参数表示两个圆中心之间的最小距离。
第四个参数表示Canny边缘检测的高阈值,低阈值将自动设为高阈值的一半。
第五个参数表示检测到圆的最小半径,一般设为0。
第六个参数表示检测到圆的最大半径,一般设为0。
下面是一个简单的例子,假设我们有一张图片,我们需要在图片中检测出圆:
import cv2
import numpy as np
img = cv2.imread('coins.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
gray_blur = cv2.medianBlur(gray, 5)
circles = cv2.HoughCircles(gray_blur,cv2.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0)
for i in circles[0,:]:
# draw the outer circle
cv2.circle(img,(i[0],i[1]),i[2],(255,0,0),2)
# draw the center of the circle
cv2.circle(img,(i[0],i[1]),2,(0,0,255),3)
cv2.imshow('output', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
上述程序一共有三个部分:
首先读入一张硬币图片,将其转化为灰度图。
通过中值模糊算法将图片平滑。
使用霍夫变换检测所有的圆,并在图片上画出。
运行后的图片如下所示:
3. 总结
霍夫变换是图像处理中非常重要的算法之一,它可以帮助我们检测出图像中的基本几何形状,如直线和圆等。在实际的图像处理中,我们经常需要使用霍夫变换来检测出图像中的某些关键信息,如识别出车道线等。在OpenCV中,实现霍夫变换非常简单,只需要使用cv2.HoughLines()和cv2.HoughCircles()等函数即可。