python 累加器_OpenCV-Python:霍夫变换

霍夫变换常用来在图像中提取直线和圆等几何形状。如下图:

python 累加器_OpenCV-Python:霍夫变换_第1张图片

我们下面来看看如何使用霍夫变换来检测直线。一条直线可以用数学表达式 y = mx + 或者 ρ = xcosθ + y sinθ表示(极坐标)

简单说明一下:

2a25871c1415c1299fb1b80f8caab25d.png

ef006699551bd43395dc4b6f4efef06a.png

ρ 是从原点到直线的垂直距离,θ是直线的垂线与横轴顺时针方向的夹角,如下图所示:

python 累加器_OpenCV-Python:霍夫变换_第2张图片

首先创建一个2D数组(累加器),初始化累加器,所有的值都为0。行表示 ρ,列表示 θ。这个数组的大小决定了最后结果的准确性。如果你希望角度精确到1°,你就需要180列。对于 ρ,最大值为图片对角线距离。

想象一下我们有一个大小为100x100的直线位于图像中央。取直线上的第一个点,我们知道此处的(x,y)值,把x和y带入公式:ρ = xcosθ + y sinθ,然后遍历 θ 的取值0, 1, 2, 3,...,180.分别求出对应的 ρ 值,这样我们就得到了一系列(ρ,θ)的数值对,如果这个数值对在累加器中也存在相应的位置,就在这个位置上加 1。由于同一条直线上的点必然会有同样的(ρ,θ)。所以现在累加器中的(50,90)=1。现在取直线上的第二个点。重复上边的过程。更新累加器中的值。现在累加器中(50,90)的值为 2。你每次做的就是更新累加器中的值。对直线上的每个点都执行上边的操作,每次操作完成之后,累加器中的值就加 1,但其他地方有时会加 1, 有时不会。按照这种方式下去,到最后累加器中(50,90)的值肯定是最大的。如果你搜索累加器中的最大值,并找到其位置(50,90),这就说明图像中有一条直线,这条直线到原点的距离为 50,它的垂线与横轴的夹角为 90 度。

OpenCV中首先计算(r,θ) 累加数,累加数超过一定值后就认为在同一直线上(有一个阈值)。

霍夫直线变换

import cv2

import numpyasnp

#1.加载图片,转为二值图

img= cv2.imread('shapes.jpg')

drawing= np.zeros(img.shape[:], dtype=np.uint8)

gray=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

edges= cv2.Canny(gray, 50, 150)

#2.霍夫直线变换

lines= cv2.HoughLines(edges, 0.8, np.pi / 180, 90)

函数中:

参数1:要检测的二值图(一般是阈值分割或边缘检测后的图)

参数2:距离 ρ 的精度,值越大,考虑越多的线

参数3:角度 θ 的精度,值越小,考虑越多的线

参数4:累加数阈值,值越小,考虑越多的线

# 3.将检测的线画出来(注意是极坐标噢)for line inlines:

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(drawing, (x1, y1), (x2, y2), (0, 0, 255))

python 累加器_OpenCV-Python:霍夫变换_第3张图片

统计概率霍夫直线变换

前面的方法又称为标准霍夫变换,它会计算图像中的每一个点,计算量比较大,另外它得到的是整一条线,并不知道原图中直线的端点。所以提出了概率霍夫直线变换(Probabilistic Hough Transform),是一种改进的霍夫变换:

drawing = np.zeros(img.shape[:], dtype=np.uint8)

# 统计概率霍夫线变换

lines= cv2.HoughLinesP(edges, 0.8, np.pi / 180, 90, minLineLength=50, maxLineGap=10)

# 将检测的线画出来for line inlines:

x1, y1, x2, y2= line[0]

cv2.line(drawing, (x1, y1), (x2, y2), (0, 255, 0), 1, lineType =cv2.LINE_AA)

cv2.imwrite('houghlines4.jpg', drawing)

参数:

minLineLength:最短长度阈值,比这个长度短的线会被排除

maxLineGap:同一直线两点之间的最大距离

cv2.LINE_AA:抗锯齿线型

python 累加器_OpenCV-Python:霍夫变换_第4张图片

霍夫圆变换

霍夫圆变换跟直线变换类似,只不过线是用(r,θ),圆是用(x_center,y_center,r)来表示,从二维变成了三维,数据量变大了很多;所以一般使用霍夫梯度法去减少计算量

drawing = np.zeros(img.shape[:], dtype=np.uint8)

# 霍夫圆变换

circles= cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 20, param2=30)

circles=np.int0(np.around(circles))

# 将检测的圆画出来for i in circles[0, :]:

cv2.circle(drawing, (i[0], i[1]), i[2], (0, 255, 0), 2) # 画出外圆

cv2.circle(drawing, (i[0], i[1]), 2, (0, 0, 255), 3) # 画出圆心

cv2.imwrite('HoughCircles.jpg', drawing)

参数2:变换方法,一般使用霍夫梯度法,详情:HoughModes

参数3 dp=1:表示霍夫梯度法中累加器图像的分辨率与原图一致

参数4:两个不同圆圆心的最短距离

参数5:param2跟霍夫直线变换中的累加数阈值一样

python 累加器_OpenCV-Python:霍夫变换_第5张图片

你可能感兴趣的:(python,累加器)