OpenCV基础教学(二十二):霍夫变换技术详解
霍夫变换是图像处理中一种重要的特征检测技术,主要用于检测图像中的直线、圆等几何形状。本文将详细讲解霍夫变换的基本原理与实现方法,包括标准霍夫线检测、统计概率霍夫线检测和霍夫圆检测。
总流程图:

一、什么是霍夫变换?
1.1 霍夫变换的概念
霍夫变换是一种在图像中检测几何形状的特征提取技术,通过将图像空间中的点映射到参数空间,然后在参数空间中寻找峰值来检测特定形状。
1.2 霍夫变换的特点
- 抗噪声能力强:对图像噪声不敏感
- 鲁棒性好:能够检测部分被遮挡的形状
- 计算复杂度高:需要较大的计算资源
- 参数空间维度:不同形状需要不同维度的参数空间
二、霍夫直线检测
2.1 标准霍夫直线检测

python
# 导入OpenCV库
import cv2
import numpy as np
# 1. 读取图像
image_np = cv2.imread('./picture.png')
image_shape = image_np.shape
# 2. 灰度化
image_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)
# 3. Canny边缘检测 得到边缘点
image_canny = cv2.Canny(image_gray, 30, 70)
# 4. 标准的霍夫直线检测
lines = cv2.HoughLines(image_canny, 0.8, np.pi / 180, 120)
# 创建一个模板图,方便绘制检测结果
image_HoughLines = np.zeros(image_shape, dtype=np.uint8)
for line in lines:
rho, theta = line[0]
cos_theta = np.cos(theta)
sin_theta = np.sin(theta)
# rho = x * cos_theta + y * sin_theta
# y = (rho - x * cos_theta) / sin_theta
x1, x2 = 0, image_shape[1]
y1 = int((rho - x1 * cos_theta) / sin_theta)
y2 = int((rho - x2 * cos_theta) / sin_theta)
cv2.line(image_HoughLines, (x1, y1), (x2, y2), (0, 0, 255))
# 结果显示
cv2.imshow('image_np', image_np)
cv2.imshow('image_HoughLines', image_HoughLines)
cv2.waitKey(0)
2.2 cv2.HoughLines()函数解析
python
cv2.HoughLines(image, rho, theta, threshold)
功能:执行标准霍夫变换检测直线
参数说明:
image:输入图像,必须是8位单通道二值图像(推荐使用Canny边缘检测的结果)rho:累加器的距离分辨率(以像素为单位)- 较小的值:更高的精度,但需要更多的内存
- 常用值:0.8-1.0
theta:累加器的角度分辨率(以弧度为单位)np.pi/180:表示1度- 较小的值:更高的角度精度
threshold:累加器阈值- 只有获得足够投票的线才会被返回
- 值越大,检测到的直线越少
返回值:
- 一个数组,每个元素是
[rho, theta],表示检测到的直线 rho:原点到直线的垂直距离theta:直线的法线与x轴的夹角
2.3 直线参数转换
标准霍夫变换返回的是极坐标参数(rho, theta),需要转换为直角坐标才能在图像上绘制:
python
# 直线参数转换公式
# 从极坐标(rho, theta)转换为直角坐标
# 直线方程:x * cos(theta) + y * sin(theta) = rho
# 在图像边界上计算两个点
x1, x2 = 0, image_shape[1] # 图像的左右边界
y1 = int((rho - x1 * cos_theta) / sin_theta)
y2 = int((rho - x2 * cos_theta) / sin_theta)
# 绘制直线
cv2.line(image, (x1, y1), (x2, y2), color, thickness)
三、统计概率霍夫直线检测
3.1 统计概率霍夫线检测

python
# 导入OpenCV库
import cv2
import numpy as np
# 1. 读取图像
image_np = cv2.imread('./picture.png')
image_shape = image_np.shape
# 2. 灰度化
image_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)
# 3. Canny边缘检测 得到边缘点
image_canny = cv2.Canny(image_gray, 30, 70)
# 创建一个模板图,方便绘制检测结果
image_HoughLinesP = np.zeros(image_shape, dtype=np.uint8)
# 4. 统计概率霍夫直线检测
lines = cv2.HoughLinesP(image_canny, 0.8, np.pi / 180, 90, minLineLength=50, maxLineGap=10)
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(image_HoughLinesP, (x1, y1), (x2, y2), (0, 0, 255))
# 结果显示
cv2.imshow('image_np', image_np)
cv2.imshow('image_HoughLines', image_HoughLinesP)
cv2.waitKey(0)
3.2 cv2.HoughLinesP()函数解析
python
cv2.HoughLinesP(image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]])
功能:执行统计概率霍夫变换检测直线段
参数说明:
image:输入图像,8位单通道二值图像rho:累加器的距离分辨率theta:累加器的角度分辨率threshold:累加器阈值minLineLength:最小线段长度- 小于此值的线段会被拒绝
- 常用值:50-100像素
maxLineGap:最大线段间隙- 线段之间的最大允许间隙,以便将它们视为一条线
- 常用值:5-20像素
返回值:
- 一个数组,每个元素是
[x1, y1, x2, y2],表示线段的起点和终点 - 可以直接用于绘制直线段
3.3 两种直线检测方法对比
| 特性 | 标准霍夫变换 | 统计概率霍夫变换 |
|---|---|---|
| 输出格式 | 极坐标(rho, theta) | 直角坐标线段(x1,y1,x2,y2) |
| 检测结果 | 无限长的直线 | 有限长度的线段 |
| 计算速度 | 较慢 | 较快 |
| 内存使用 | 较多 | 较少 |
| 适用场景 | 检测完整的直线 | 检测直线段 |
| 函数 | cv2.HoughLines() |
cv2.HoughLinesP() |
四、霍夫圆检测
4.1 霍夫圆检测代码

python
import cv2
import numpy as np
# 1. 读取图像(建议加存在性判断)
image_np = cv2.imread('./picture.png')
if image_np is None:
print("错误:未找到picture.png,请检查文件路径!")
exit()
image_shape = image_np.shape
# 2. 灰度化
image_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)
# 3. 霍夫圆检测(HOUGH_GRADIENT_ALT是新版高精度算法)
circles = cv2.HoughCircles(
image_gray,
method=cv2.HOUGH_GRADIENT_ALT,
dp=1.5, # 累加器分辨率与图像分辨率的比值
minDist=20, # 圆之间的最小距离
param1=300, # 边缘检测的高阈值(仅HOUGH_GRADIENT_ALT有效)
param2=0.9 # 圆心检测阈值(越小检测越多,0.9是高精度推荐值)
)
# 4. 处理检测结果(核心修正)
image_Circle = np.zeros(image_shape, dtype=np.uint8)
if circles is not None: # 先判断是否检测到圆
# 替换废弃的np.int0 → 用np.intp(兼容原逻辑)或np.int32(更通用)
circles = np.intp(np.around(circles))
# 遍历circles[0](取所有圆的维度),而非直接遍历circles
for circle in circles[0]:
x, y, radius = circle # 每个圆的x/y/radius
cv2.circle(image_Circle, (x, y), radius, (0, 0, 255), 2)
# 5. 结果显示
cv2.imshow('Original Image', image_np)
cv2.imshow('Detected Circles', image_Circle)
cv2.waitKey(0)
cv2.destroyAllWindows() # 释放窗口资源(好习惯)
4.2 cv2.HoughCircles()函数解析
python
cv2.HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]])
功能:在灰度图像中使用霍夫变换检测圆
参数说明:
image:输入图像,8位单通道灰度图像method:检测方法cv2.HOUGH_GRADIENT:标准霍夫梯度法cv2.HOUGH_GRADIENT_ALT:替代梯度法,精度更高
dp:累加器分辨率与图像分辨率的比值- 1.0:与图像相同的分辨率
- 2.0:累加器分辨率是图像分辨率的一半
- 常用值:1.0-2.0
minDist:检测到的圆心之间的最小距离- 太小:相邻圆可能被误认为同一个
- 太大:可能漏检一些圆
param1:边缘检测的高阈值- 对于
HOUGH_GRADIENT:Canny边缘检测的高阈值 - 对于
HOUGH_GRADIENT_ALT:边缘检测的高阈值
- 对于
param2:圆心检测阈值- 较小的值:检测到更多的假圆
- 较大的值:只检测更明显的圆
- 对于
HOUGH_GRADIENT_ALT:推荐0.9
minRadius:最小圆半径(可选)maxRadius:最大圆半径(可选)
返回值:
- 一个数组,包含检测到的圆的参数
[x, y, radius] x, y:圆心坐标radius:圆的半径
4.3 数据类型转换
python
# 新版本OpenCV的数据类型转换
circles = np.intp(np.around(circles))
# 或者
circles = np.int32(np.around(circles))
# 旧版本使用的是np.int0,现已弃用
# circles = np.int0(np.around(circles)) # 不推荐
np.around()函数:
- 功能:对数组元素进行四舍五入
- 参数:输入数组
- 返回值:四舍五入后的数组
np.intp/np.int32函数:
np.intp:用于索引的整数类型np.int32:32位整数类型- 都可以用于坐标转换
总结
霍夫变换是图像处理中重要的特征检测技术,能够有效检测图像中的直线和圆等几何形状。
主要知识点总结:
- 霍夫变换原理:将图像空间映射到参数空间进行形状检测
- 直线检测方法 :
- 标准霍夫变换:
cv2.HoughLines() - 统计概率霍夫变换:
cv2.HoughLinesP()
- 标准霍夫变换:
- 圆检测方法 :
cv2.HoughCircles() - 参数含义:理解各个参数对检测结果的影响
- 预处理重要性:边缘检测和降噪对结果的影响
霍夫变换在工业检测、自动驾驶、医学图像分析等领域有广泛应用,掌握其原理和使用方法对计算机视觉学习非常重要。