一 霍夫变换原理
注意: 进行霍夫变换的前提是首先完成了边缘检测任务
1. 霍夫变换概述
霍夫变换是一种特征检测(feature extraction),被广泛应用在图像分析(image analysis)、计算机视觉(computer vision)以及数位影像处理(digital image processing)。霍夫变换是用来辨别找出物件中的特征.如直线 圆等物体特征:
先直观的看看它的作用:
检测直线:
检测圆:
2. 霍夫变换原理
极座标系和直角座标系之间什么关系:
1.在直角座标系下,点P的座标表示为(x, y)
2.在极座标系下,点的座标表示为
某一点由极座标转换为直角座标:
所以由图可得:
所以:
由极座标与直角座标之间的关系可得:
得到极座标方程:
所以这样将笛卡尔座标系下函数转变成了关于参数的函数空间,也叫极座标系。可以直观的看到,只需要知道一点就可以在笛卡尔座标中确定一条直线。
在平面座标空间中过一点有无数条直线,那么平面座标空间中的每一条直线到霍夫空间中都对应一点。
3. 霍夫检测原理
在笛卡尔座标系中,过这两点的直线都有不同的,那么将这些点反应在极座标系中如图2所示:
图1
图2
那么图2中的交点表示,在笛卡尔座标系中有一条直线同时经过了两点。那么这条直线为:将点带入极座标可得到直线:
由:
可得:
所以这样就找到了直线 。
具体可以参考这篇博客:https://blog.csdn.net/shenziheng1/article/details/75307410
二 霍夫变换实现
# coding: utf-8
import numpy as np
import matplotlib.pyplot as plt
from skimage.transform import hough_line
from skimage.draw import line
img = np.zeros((100, 150), dtype=bool)
img[30, :] = 1
img[:, 65] = 1
img[35:45, 35:50] = 1
rr, cc = line(60, 130, 80, 10)
img[rr, cc] = 1
img += np.random.random(img.shape) > 0.95
out, angles, d = hough_line(img)
fix, axes = plt.subplots(1, 2, figsize=(7, 4))
axes[0].imshow(img, cmap=plt.cm.gray)
axes[0].set_title('Input image')
axes[1].imshow(
out, cmap=plt.cm.bone,
extent=(np.rad2deg(angles[-1]), np.rad2deg(angles[0]), d[-1], d[0]))
axes[1].set_title('Hough transform')
axes[1].set_xlabel('Angle (degree)')
axes[1].set_ylabel('Distance (pixel)')
plt.tight_layout()
plt.show()
三 霍夫变换应用
1. 直线检测
import cv2
import numpy as np
image = cv2.imread("27.jpg")
cv2.imshow("image_original", image)
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(image_gray, 100, 150)
lines = cv2.HoughLines(edges, 1, np.pi / 180, 100)
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(image, (x1, y1), (x2, y2), (0, 0, 255), 2)
cv2.imshow("image_lines", image)
cv2.imwrite("6.jpg",image)
cv2.waitKey(0)
2. 圆检测
import cv2
import numpy as np
image = cv2.imread("29.jpg")
cv2.imshow("image_original", image)
dst = cv2.cvtColor(image, cv2.COLOR_BGRA2GRAY)
circle = cv2.HoughCircles(dst, cv2.HOUGH_GRADIENT, 1, 80, param1=40, param2=20, minRadius=20, maxRadius=300)
if not circle is None:
circle = np.uint16(np.around(circle))
for i in circle[0, :]:
cv2.circle(image, (i[0], i[1]), i[2], (0, 0, 255), 2)
cv2.imshow("circle", image)
cv2.waitKey(0)