openCV霍夫变换原理及其实现

一 霍夫变换原理

注意: 进行霍夫变换的前提是首先完成了边缘检测任务

1. 霍夫变换概述

霍夫变换是一种特征检测(feature extraction),被广泛应用在图像分析(image analysis)、计算机视觉(computer vision)以及数位影像处理(digital image processing)。霍夫变换是用来辨别找出物件中的特征.如直线 圆等物体特征:
先直观的看看它的作用:
检测直线:
在这里插入图片描述
检测圆:
在这里插入图片描述

2. 霍夫变换原理

极座标系和直角座标系之间什么关系:
1.在直角座标系下,点P的座标表示为(x, y)
在这里插入图片描述

2.在极座标系下,点的座标表示为(p,θ)(p,\theta)
在这里插入图片描述
某一点由极座标转换为直角座标:
y=γsin(θ)y = \gamma * \sin(\theta)
x=γcos(θ)x = \gamma * \cos(\theta)

在这里插入图片描述所以由图可得:

p=γcos(θβ)p = \gamma * \cos(\theta - \beta)
所以:
p=γcos(θ)cos(β)+γsin(θ)sin(β) p = \gamma*cos(\theta)*cos(\beta)+\gamma*sin(\theta)*sin(\beta)
=γcos(β)cos(θ)+γsin(β)sin(θ) = \gamma*cos(\beta)*cos(\theta)+\gamma*sin(\beta)*sin(\theta)
由极座标与直角座标之间的关系可得:
y=γsin(β)y = \gamma * \sin(\beta)
x=γcos(β)x = \gamma * \cos(\beta)

得到极座标方程:
p=xcos(θ)+ysin(θ)p = x*cos(\theta)+y*sin(\theta)

所以这样将笛卡尔座标系下函数转变成了关于参数(p,θ)(p,\theta)的函数空间,也叫极座标系。可以直观的看到,只需要知道一点就可以在笛卡尔座标中确定一条直线。
在平面座标空间中过一点有无数条直线,那么平面座标空间中的每一条直线到霍夫空间中都对应一点。

3. 霍夫检测原理

在笛卡尔座标系中,过这两点的直线都有不同的(p,θ)(p,\theta),那么将这些点反应在极座标系中如图2所示:

图1 图1
图2

在这里插入图片描述那么图2中的交点(p,θ)(p,\theta)表示,在笛卡尔座标系中有一条直线同时经过了两点。那么这条直线为:将点带入极座标可得到直线:
由:
p=xcos(θ)+ysin(θ)p = x*cos(\theta)+y*sin(\theta)

可得:
y=xcos(θ)/sin(θ)+p/sin(θ)y = x*cos(\theta) / sin(\theta)+ p / sin(\theta)
所以这样就找到了直线y=kx+b y = k * x +b

具体可以参考这篇博客: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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章