OpenCV(python)一键入门--十八篇(霍夫线和霍夫圆检测)
本系列OpenCV博客旨在以最简单的方式分享OpenCV知识,欢迎大家交流和提出指导意见
凡是有本文未详细介绍的函数,都可以在以往的博客找到介绍及其使用方法
本期介绍函数:
cv.HoughLines
cv.HoughLinesP
cv.HoughCircles
1:霍夫直线检测
import cv2 as cv
import numpy as np
def canny_demo(image):
t = 80
canny_output = cv.Canny(image, t, t * 2)
return canny_output
src = cv.imread("D:/sudoku.png")
cv.imshow("input", src)
binary = canny_demo(src)
cv.imshow("binary", binary)
lines = cv.HoughLines(binary, 1, np.pi / 180, 150, None, 0, 0)
if lines is not None:
for i in range(0, len(lines)):
rho = lines[i][0][0]
theta = lines[i][0][1]
a = np.cos(theta)
b = np.sin(theta)
x0 = a * rho
y0 = b * rho
pt1 = (int(x0 + 1000 * (-b)), int(y0 + 1000 * (a)))
pt2 = (int(x0 - 1000 * (-b)), int(y0 - 1000 * (a)))
cv.line(src, pt1, pt2, (0, 0, 255), 3, cv.LINE_AA)
cv.imshow("hough line demo", src)
cv.waitKey(0)
cv.destroyAllWindows()
图像霍夫变换是一种很有用的图像变换,通过把图像的坐标从平面坐标系变换极坐标,可以发现原来在平面坐标难以提取的几何特征信息(如:直线、圆等等)。
假设有如下的直线参数方程:
r = xcosθ + ysinθ
其中角度θ指r与X轴之间的夹角,r为到直线几何垂直距离。
如果有很多点在霍夫空间的曲线交于一点(如下图图四),便可以说明他们有相同的θ和r。
1):cv.HoughLines 霍夫线
函数原型:lines = cv.HoughLines(image, rho, theta, threshold[, lines[, srn[, stn[, min_theta[, max_theta]]]]])
- lines:线的输出向量。每行由2或3个元素向量组成
- rho:累加器的距离分辨率(以像素为单位)
- theta:以弧度为单位的累加器的角度分辨率
- threshold:累加器阈值。图像在霍夫空间每个像素点都是一条曲线。经过每个(r,θ)都+1,如果多个曲线都在同个(r,θ)相交且大于给定的阈值,说明可能存在一条直线在霍夫空间的该点处。
- lines:输出直线
- srn、stn:多尺度霍夫变换时候小的参数,经典的霍夫变换不需要此参数
- srn:对于多尺度霍夫变换,它是距离分辨率 rho 的除数。粗略累加器距离分辨率为 rho ,精确累加器分辨率为 rho/srn 。如果 srn=0 和 stn=0 ,则使用经典的霍夫变换。否则,这两个参数都应为正。
- stn:对于多尺度 Hough 变换,它是距离分辨率 theta 的除数。
- min_theta:最小尺度,必须介于 0 和 max_theta 之间。
- max_theta:最大尺度,必须介于 min_theta 和 CV_PI 之间。
效果如下:
照常贴上原图素材:
霍夫直线检测其实还有另一个api。也就是
2):cv.HoughLinesP 霍夫线
函数原型:lines = cv.HoughLinesP(image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]])
- image:输入的二值图像
- lines:返回的直线两个点
- rho :极坐标r得步长
- theta:角度步长
- threshold:累加器阈值
- minLineLength:最小线段长度
- maxLineGap:线段间隔
案例如下:
import cv2 as cv
import numpy as np
def canny_demo(image):
t = 80
canny_output = cv.Canny(image, t, t * 2)
return canny_output
src = cv.imread("D:/sudoku.png")
cv.imshow("input", src)
binary = canny_demo(src)
cv.imshow("binary", binary)
linesP = cv.HoughLinesP(binary, 1, np.pi / 180, 50, None, 50, 10)
if linesP is not None:
for i in range(0, len(linesP)):
l = linesP[i][0]
cv.line(src, (l[0], l[1]), (l[2], l[3]), (0, 0, 255), 1, cv.LINE_AA)
cv.imshow("hough line demo", src)
cv.waitKey(0)
cv.destroyAllWindows()
效果如下:
2:霍夫圆检测
import cv2 as cv
import numpy as np
src = cv.imread("D:/coin.png")
cv.imshow("input", src)
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
gray = cv.GaussianBlur(gray, (9, 9), 2, 2)
dp = 2
param1 = 100
param2 = 80
circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, dp, 10, None, param1, param2, 20, 100)
for c in circles[0,:]:
cx, cy, r = c
cv.circle(src, (cx, cy), 2, (0, 255, 0), 2, 8, 0)
cv.circle(src, (cx, cy), r, (0, 0, 255), 2, 8, 0)
cv.imshow("hough demo", src)
cv.waitKey(0)
cv.destroyAllWindows()
函数原型:circles=cv.HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]])
- image:单通道灰度图像
- cycles:检测到的圆的信息,如:圆形,半径
- method:检测方法。我们直接使用cv.HOUGH_GRADIENT霍夫梯度法即可
- dp:图像分辨率的变化。默认1的时候保持和原图一样的大小
- param1:边缘提取的高阈值
- param2:霍夫空间的累加阈值
- minRadius:最小圆半径
- maxRadius:最大圆半径。如果 <= 0,则使用最大图像尺寸。如果 < 0,则返回中心而不找到半径。
效果如下:
附上素材图像:
- 点赞
- 收藏
- 关注作者
评论(0)