霍夫变换是一种可以检测任何形状的流行技术,即使形状有缺失或变形,仍然可以检测出形状。
常用霍夫变换检测线
一条线可以表示为或以参数形式表示为,其中是从原点到该线的垂直距离,而是由该垂直线和水平轴所形成的角度以逆时针方向测量。
如图所示:
现在看一下霍夫变换如何处理线条。任何一条线都可以用这两个术语表示。因此,首先创建2D数组或累加器(以保存两个参数的值),并将其初始设置为0。让行表示,列表示。阵列的大小取决于所需的精度。
opencv中的霍夫线变换 -> cv2.Houghlines() 它只是返回一个:math:(rho,theta)值得数组。以像素为单位,以弧度为单位。
第一个参数,输入的是二进制图像,因此在应用霍夫变换之前,应用阈值或Canny边缘检测。
第二和第三参数分别是和的精度。
第四个参数是阈值,这意味着应将其视为行的最低投票。票数取决于线上的点数。因此,它表示检测到的最小线长。
看实际应用,选着棋盘格图案试一试
# 导包
import cv2 as cv
import numpy as np
img = cv.imread('D:/chess.png')
# 灰度图
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# Canny边缘检测
edges = cv.Canny(gray,50,150,apertureSize=3)
# 霍夫线检测
lines = cv.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))
# 画线
cv.line(img,(x1,y1),(x2,y2),(0,0,255),2)
# 保存
cv.imwrite('D:/houghlines.jpg',img)
输出效果:
常用霍夫变换检测圆
圆在数学上表示为,其中是圆的中心,是圆的半径。从公式上可以看到有3个参数,因此需要3D累加器进行霍夫变换,这将非常低效。因此opencv使用边缘的梯度信息的方法。
opencv中的霍夫圆变换 -> cv2.HoughCircles()
# 导包
import cv2 as cv
import numpy as np
# 导入图片,直接变灰度的
img = cv.imread('D:/hou/jingtou.png',0)
# 中值滤波
img = cv.medianBlur(img,5)
# cimg变回BGR图像
cimg = cv.cvtColor(img,cv.COLOR_GRAY2BGR)
# 霍夫圆变换
circles = cv.HoughCircles(img,cv.HOUGH_GRADIENT,1,20,
param1=50,param2=30,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
# 绘制外圆
cv.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
# 绘制圆心
cv.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
cv.imwrite('D:/houghcircle.jpg',cimg)
输出效果: