霍夫变换(Hough Transform)

本文介绍了霍夫变换的概念及其在图像处理中的应用,特别是霍夫直线检测和霍夫圆检测。霍夫变换是一种特征提取技术,用于检测直线和曲线,尤其在OpenCV库中,通过HoughLines和HoughLinesP函数实现直线检测,而霍夫圆检测则通过HoughCircles函数完成。文章详细阐述了检测步骤、优缺点以及相关参数的设置,并提供了OpenCV实现的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 什么是霍夫变换

霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换结果。

霍夫变换于1962年由PaulHough首次提出,最初的Hough变换是设计用来检测直线和曲线,起初的方法要求知道物体边界线的解析方程,但不需要有关区域位置的先验知识。这种方法的一个突出优点是分割结果的Robustness,即对数据的不完全或噪声不是非常敏感。然而,要获得描述边界的解析表达常常是不可能的。后于1972年由Richard Duda & Peter Hart推广使用,经典霍夫变换用来检测图像中的直线,后来霍夫变换扩展到任意形状物体的识别,多为圆和椭圆。霍夫变换运用两个坐标空间之间的变换将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题。

霍夫变换在OpenCV中分为霍夫线变换和霍夫圆变换两种。

2. 霍夫直线检测

Hough直线检测的基本原理在于利用点与线的对偶性,在我们的直线检测任务中,即图像空间中的直线与参数空间中的点是一一对应的,参数空间中的直线与图像空间中的点也是一一对应的。这意味着我们可以得出两个非常有用的结论:

​ 1)图像空间中的每条直线在参数空间中都对应着单独一个点来表示;
​ 2)图像空间中的直线上任何一部分线段在参数空间对应的是同一个点。

因此Hough直线检测算法就是把在图像空间中的直线检测问题转换到参数空间中对点的检测问题,通过在参数空间里寻找峰值来完成直线检测任务。

2.1 霍夫直线检测的具体步骤

  1. 彩色图像->灰度图;
  2. 去噪(高斯核);
  3. 边缘提取(梯度算子、拉普拉斯算子、canny、sobel);
  4. 二值化(判断此处是否为边缘点,就看灰度值==255);
  5. 映射到霍夫空间(准备两个容器,一个用来展示hough-space概况,一个数组hough-space用来储存voting的值,因为投票过程往往有某个极大值超过阈值,多达几千,不能直接用灰度图来记录投票信息);
  6. 取局部极大值,设定阈值,过滤干扰直线;
  7. 绘制直线、标定角点。

2.2 霍夫直线检测的优缺点

优点:Hough直线检测的优点是抗干扰能力强,对图像中直线的残缺部分、噪声以及其它共存的非直线结构不敏感,能容忍特征边界描述中的间隙,并且相对不受图像噪声的影响。

缺点:Hough变换算法的特点导致其时间复杂度和空间复杂度都很高,并且在检测过程中只能确定直线方向,丢失了线段的长度信息。由于霍夫检测过程中进行了离散化,因此检测精度受参数离散间隔制约。

2.3 OpenCV中霍夫直线检测的应用

OpenCV的中用函数HoughLines(标准)和HoughLinesP(基于统计)来检测图像中的直线,函数原型如下:

2.3.1 标准霍夫检测

lines = cv.HoughLines( image, rho, theta, threshold[, lines[, srn[, stn[, min_theta[, max_theta]]]]] )

参数说明:
lines:返回值(ρ,θ),ρ以像素为单位,θ以弧度为单位;
rho:累加器的距离分辨率(以像素为单位);
theta:累加器的角度分辨率(弧度);
threshold:阈值,仅大于的才可以被返回;
srn:对于多尺度Hough变换,它是距离分辨率rho的除数。粗累加器距离分辨率为rho,精确累加器分辨率为rho/srn。如果srn=0和stn=0,则使用经典Hough变换。否则,这两个参数都应为正值;
stn:对于多尺度Hough变换,它是距离分辨率θ的除数;
min_theta:对于标准和多尺度Hough变换,检查直线的最小角度。必须介于0和最大θ之间;
max_theta:对于标准和多尺度Hough变换,检查直线的最大角度。必须介于min_theta和CV_PI之间。

2.3.2 概率霍夫检测

lines = cv.HoughLinesP( image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]] ) 

参数说明:
lines:返回两个端点的坐标;
rho:累加器的距离分辨率(以像素为单位);
theta:累加器的角度分辨率(弧度);
threshold:阈值,仅大于的才可以被返回;
minLineLength:最小行长度,小于该长度的线段将被拒绝;
maxLineGap:同一直线上连接点的最大允许间距。

测试代码如下:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

src = cv.imread("demo-line.jpg")
img = src.copy()
 
# 二值化图像(Canny边缘检测)
gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
dst_img = cv.Canny(gray_img, 50, 150)
 
# 霍夫线变换
lines = cv.HoughLines(dst_img, 0.5, np.pi / 180, 300)
 
# 将检测的线绘制在原图上(注意是极坐标)
for line in lines:
    rho, theta = line[0]
    a = np.cos(theta)
    b = np.sin(theta)
    # 找两个点
    x0 = rho * a
    y0 = rho * b
    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), (255, 0, 0), 3)
 
# 显示图像
plt.subplot(311), plt.imshow(src, 'gray'), plt.title('src_img'), plt.axis('off')
plt.subplot(312), plt.imshow(dst_img, 'gray'), plt.title('canny_img'), plt.axis('off')
plt.subplot(313), plt.imshow(img, 'gray'), plt.title('HoughLines_img'), plt.axis('off')
plt.show()

效果如下:

在这里插入图片描述

3. 霍夫圆检测

霍夫圆变换的基本思路是认为图像上每一个非零像素点都有可能是一个潜在的圆上的一点,跟霍夫线变换一样,也是通过投票,生成累积坐标平面,设置一个累积权重来定位圆。

OpenCV中使用cv2.HoughCircles函数来实现霍夫圆检测,其函数原型如下:

cv2.HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) → circles

参数说明:
image:8位单通道图像,如果使用彩色图像,需要先转换成灰度图像;
method:定义检测图像中圆的方法,目前唯一实现的方法是cv2.HOUGH_GRADIENT;
dp:图像像素分辨率与参数空间分辨率的比值(官方文档上写的是图像分辨率与累加器分辨率的比值,它把参数空间认为是一个累加器,毕竟里面存储的都是经过的像素点的数量),dp=1,则参数空间与图像像素空间(分辨率)一样大,dp=2,参数空间的分辨率只有像素空间的一半大;
minDist:检测到的圆的中心,(x,y)坐标之间的最小距离。如果minDist太小,则可能导致检测到多个相邻的圆。如果minDist太大,则可能导致很多圆检测不到;
param1:用于处理边缘检测的梯度值方法;
param2:cv2.HOUGH_GRADIENT方法的累加器阈值。阈值越小,检测到的圆越多;
minRadius:半径的最小大小(以像素为单位);
maxRadius:半径的最大大小(以像素为单位)。

测试代码如下:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('demo-circle.jpg',0)
img = cv2.medianBlur(img,5)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,200,param1=50,param2=30,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
    # draw the outer circle
    cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
    # draw the center of the circle
    cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)

plt.subplot(121), plt.imshow(img, 'gray'), plt.title('src_img'), plt.axis('off')
plt.subplot(122), plt.imshow(cimg, 'gray'), plt.title('HoughCircles_img'), plt.axis('off')
plt.show()

效果如下:

在这里插入图片描述

4. 源码仓库地址

🌼 图像处理、机器学习的常用算法汇总

<think>好的,用户现在想了解Hough变换在图像处理中的使用方法或原理。我需要结合用户提供的引用资料和他之前的Canny边缘检测问题来组织回答。首先,用户之前详细讨论了Canny算法,这可能意味着他现在关注的是边缘检测后的形状识别,比如直线检测,Hough变换在这里的应用是自然的延伸。 用户提供的引用中有四个关于Hough变换的资料,我需要从中提取关键点。引用1提到Hough变换用于检测直线、圆等形状,特别是直线。引用2和3讨论了标准Hough线变换、渐进概率Hough变换的原理和步骤,以及可能的缺点。引用4详细描述了Hough变换的算法步骤,包括参数空间的量化、交点累加器,以及如何确定直线参数。 用户的问题集中在Hough变换的原理和使用方法上,因此我需要将原理部分解释清楚,同时给出具体的实现步骤或代码示例。考虑到用户之前的问题中有Python代码示例,可能他希望看到类似的实现,但需要注意Hough变换在OpenCV中的函数调用,或者是否需要手动实现。 需要区分标准Hough变换和概率Hough变换,因为用户提供的引用中提到了两者的区别。此外,用户可能对参数设置(如rho和theta的分辨率)如何影响检测结果感兴趣,这在引用4中也有提到量化过粗或过细的问题。 另外,用户之前提到Canny边缘检测,可能需要将Hough变换作为后续步骤,比如先用Canny检测边缘,再用Hough检测直线。因此,在回答中可以结合这两者的流程,给出一个完整的示例。 还要注意数学表达式的格式,按照用户的要求,行内公式用$...$,独立公式用$$...$$。例如,极坐标方程ρ = x*cosθ + y*sinθ需要正确呈现。 最后,生成的相关问题需要与Hough变换的应用、优化、与其他方法的比较等相关,确保覆盖用户可能感兴趣的扩展方向。</think>### Hough变换原理与使用方法详解 --- #### **一、核心原理** Hough变换是一种**参数空间映射技术**,通过将图像空间中的几何形状映射到参数空间进行检测,特别擅长处理**不连续边缘**和**噪声干扰**下的形状识别[^1][^4]。其核心思想是:**图像空间中的共线/共形点在参数空间中会形成明显交点**。 --- #### **二、直线检测数学原理** 1. **极坐标表示** 图像空间中的直线可表示为: $$ \rho = x \cos\theta + y \sin\theta $$ - $\rho$:直线到原点的距离 - $\theta$:直线与x轴的夹角 2. **参数空间映射** 每个图像点$(x_i,y_i)$对应参数空间中的一条正弦曲线: $$ \rho = x_i \cos\theta + y_i \sin\theta $$ **共线点**在参数空间中会相交于同一点$(\rho_0, \theta_0)$,通过统计交点处的累加值即可检测直线[^4]。 --- #### **三、标准Hough变换(SHT)实现步骤** 1. **边缘检测预处理** 通常先使用Canny算法提取边缘: ```python edges = cv2.Canny(img, 50, 150) ``` 2. **参数空间量化** - $\rho$范围:$[0, \sqrt{w^2 + h^2}]$(图像对角线长度) - $\theta$范围:$[0, 180°)$ ```python rho_res = 1 # ρ分辨率(像素) theta_res = np.pi/180 # θ分辨率(1度) ``` 3. **累加器矩阵构建** 创建二维数组$A(\rho, \theta)$记录交点计数: ```python max_rho = int(np.hypot(img.shape[0], img.shape[1])) accumulator = np.zeros((max_rho, 180), dtype=np.uint64) ``` 4. **投票过程** 遍历所有边缘点,填充累加器: ```python for y in range(edges.shape[0]): for x in range(edges.shape[1]): if edges[y,x] > 0: for theta in range(0, 180): t = theta * theta_res rho = x * np.cos(t) + y * np.sin(t) r = int(round(rho)) accumulator[r, theta] += 1 ``` 5. **峰值检测** 提取累加器中值大于阈值的参数对: ```python threshold = 100 # 根据图像复杂度调整 lines = np.argwhere(accumulator > threshold) ``` --- #### **四、OpenCV实战代码** ```python import cv2 import numpy as np # 读取图像并提取边缘 img = cv2.imread('road.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray, 50, 150) # 标准Hough变换 lines = cv2.HoughLines(edges, rho=1, theta=np.pi/180, threshold=100) # 绘制检测结果 if lines is not None: for rho, theta in lines[:,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(img, (x1,y1), (x2,y2), (0,0,255), 2) cv2.imshow('Hough Lines', img) cv2.waitKey(0) ``` --- #### **五、优化方法** 1. **渐进概率Hough变换(PPHT)** - 动态停止条件:当检测到足够多直线时停止 - 返回线段端点而非无限直线 ```python lines = cv2.HoughLinesP(edges, rho=1, theta=np.pi/180, threshold=50, minLineLength=50, maxLineGap=10) ``` 2. **多尺度检测** - 粗检测:低分辨率参数空间快速定位 - 精确定位:局部区域使用高分辨率参数空间[^4] 3. **参数选择原则** | 参数 | 作用域 | 推荐值 | 影响分析 | |------------|----------------|-----------------------|------------------------------| | `rho` | 距离分辨率 | 1像素 | 值越小定位越精确,内存消耗越大 | | `theta` | 角度分辨率 | 1度 (π/180) | 同上 | | `threshold`| 累加器阈值 | 图像对角线长度的5%-10% | 值越高检测直线越少 | --- #### **六、数学特性分析** 1. **计算复杂度** $$ T = O(N \times M) $$ - $N$:边缘像素数量 - $M$:θ的离散化数量 2. **抗噪性来源** - 单点噪声在参数空间中产生微弱正弦曲线,难以形成显著交点 - 断线边缘仍能在参数空间中部分重叠[^4] --- #### **七、应用场景** 1. 文档扫描(检测纸张边缘) 2. 车道线检测(自动驾驶) 3. 工业零件尺寸测量 4. 卫星图像中的道路提取 --- ### **相关问题** 1. Hough变换检测圆形的参数空间如何设计? 2. 如何解决Hough变换在检测密集直线时的计算效率问题? 3. 概率Hough变换相比标准方法有哪些改进? 4. Hough变换在三维图像处理中有哪些扩展应用? 5. 如何结合深度学习和Hough变换提升形状检测精度? --- [^1]: MATLAB数字图像处理 Hough变换原理 [^2]: 渐进概率Hough变换实现细节 [^3]: Hough变换数学推导与参数分析 : 图像分割中的Hough变换优化策略
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值