如何在视频中实现霍夫圆变换?附HSV颜色检测代码解析
基于OpenCV的黄色物体检测+霍夫圆变换代码解析与完善
嘿,我来帮你把这段OpenCV代码补全并优化到位——咱们先拆解原代码的逻辑,再一步步补上霍夫圆变换的部分,顺便把黄色检测的阈值调得更靠谱些:
1. 原代码基础逻辑梳理
先给你理清楚现有代码的作用:
cv2.VideoCapture(0):调用电脑默认的摄像头设备- 循环读取每一帧画面,把BGR格式转成HSV是因为HSV颜色空间对亮度变化的鲁棒性更强,比原生BGR更适合做颜色分割
- 原代码里的黄色HSV阈值其实有问题:
lower_yellow的S(饱和度)和V(亮度)设为0,会把很多非黄色的暗区域也误判进来,咱们后面会优化这个部分
2. 优化黄色检测的HSV阈值
实际场景中,黄色的HSV范围需要给饱和度和亮度设合理下限,避免误检。这里给你一个通用的靠谱阈值,你可以根据实际光照微调:
# 优化后的黄色HSV阈值,适配大多数场景 lower_yellow = np.array([20, 100, 100]) upper_yellow = np.array([30, 255, 255])
如果你的场景光照特殊,比如偏暗或偏亮,可以用OpenCV的取色工具(比如写个鼠标回调函数)来获取目标黄色的准确HSV值
3. 位与操作提取黄色区域
原代码缺少位与操作,这一步能帮你从原画面中单独提取出黄色物体的区域:
# 位与操作:只保留mask中白色区域对应的原帧像素 res = cv2.bitwise_and(frame, frame, mask=mask)
简单说就是:mask里白色(255)的部分会保留原画面的颜色,黑色(0)的部分会被置黑,这样你就能单独看到黄色物体了。
4. 霍夫圆变换的实现
霍夫圆变换对噪声很敏感,所以需要先做预处理,再调用检测函数,最后把检测到的圆画到原画面上:
预处理步骤
先把提取出的黄色区域转灰度+高斯模糊,减少噪声干扰:
# 转灰度图 gray = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY) # 高斯模糊降噪 blur = cv2.GaussianBlur(gray, (5, 5), 0)
调用霍夫圆变换
circles = cv2.HoughCircles( blur, cv2.HOUGH_GRADIENT, # 目前唯一实现的霍夫圆变换方法 dp=1, # 累加器分辨率与图像分辨率的比值,通常设1 minDist=20, # 检测到的圆之间的最小距离,避免重复检测 param1=50, # Canny边缘检测的高阈值,低阈值是它的一半 param2=30, # 累加器阈值:值越小检测到的圆越多(易误检),值越大越严格 minRadius=5, # 检测圆的最小半径,过滤过小的噪声点 maxRadius=100 # 检测圆的最大半径,过滤过大的干扰 )
绘制检测到的圆
要先判断是否检测到圆(没检测到会返回None),然后把圆和圆心画到原画面上:
if circles is not None: # 把浮点型的圆参数转成整数 circles = np.uint16(np.around(circles)) for circle in circles[0, :]: # 绘制圆的外轮廓(绿色,线宽2) cv2.circle(frame, (circle[0], circle[1]), circle[2], (0, 255, 0), 2) # 绘制圆心(红色,半径3) cv2.circle(frame, (circle[0], circle[1]), 2, (0, 0, 255), 3)
5. 完整可运行代码
把所有部分整合起来,加上窗口显示和退出逻辑:
import cv2 import numpy as np cap = cv2.VideoCapture(0) # 优化后的黄色HSV阈值 lower_yellow = np.array([20, 100, 100]) upper_yellow = np.array([30, 255, 255]) while True: # 获取每一帧,ret表示是否成功读取 ret, frame = cap.read() if not ret: print("无法读取摄像头帧") break # BGR转HSV颜色空间 hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # 创建黄色掩码 mask = cv2.inRange(hsv, lower_yellow, upper_yellow) # 位与操作提取黄色区域 res = cv2.bitwise_and(frame, frame, mask=mask) # 预处理:转灰度+高斯模糊,为霍夫圆变换做准备 gray = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (5, 5), 0) # 霍夫圆变换检测圆形 circles = cv2.HoughCircles( blur, cv2.HOUGH_GRADIENT, dp=1, minDist=20, param1=50, param2=30, minRadius=5, maxRadius=100 ) # 如果检测到圆,在原帧上绘制 if circles is not None: circles = np.uint16(np.around(circles)) for circle in circles[0, :]: # 绘制圆轮廓 cv2.circle(frame, (circle[0], circle[1]), circle[2], (0, 255, 0), 2) # 绘制圆心 cv2.circle(frame, (circle[0], circle[1]), 2, (0, 0, 255), 3) # 显示各个窗口 cv2.imshow('Original Frame', frame) cv2.imshow('Yellow Mask', mask) cv2.imshow('Yellow Region', res) # 按q键退出循环 if cv2.waitKey(1) & 0xFF == ord('q'): break # 释放摄像头资源,关闭所有窗口 cap.release() cv2.destroyAllWindows()
6. 实用调整技巧
- 如果检测效果不好,可以微调霍夫圆的
param2参数:值减小会检测更多圆(可能误检),值增大则更严格 - 黄色阈值可以根据场景调整:比如光照偏暗时,V的下限可以调低到80左右
- 若摄像头帧率低,可以缩小帧尺寸(比如
frame = cv2.resize(frame, (640, 480)))来加快处理速度
内容的提问来源于stack exchange,提问作者Yavuzhan Erdem
相关产品推荐
相关产品推荐

