非正视角下飞镖盘实时检测的OpenCV Python技术问询
非正视角飞镖盘的OpenCV实时检测方案(无机器学习)
针对非正视角下飞镖盘检测的问题,我们可以利用飞镖盘的椭圆形态特征和环形纹理优化检测逻辑,替代仅能识别正圆的cv2.HoughCircles,同时解决轮廓误识别的问题。以下是具体实现方案:
关键优化点
- 替换固定阈值为自适应阈值,适配不同光照环境下的打印飞镖盘
- 结合Canny边缘检测+形态学操作,强化飞镖盘的环形纹理特征
- 对候选轮廓进行椭圆拟合,筛选符合飞镖盘形态的椭圆(非正视角下呈现椭圆)
- 加入轮廓的纵横比、面积占比等约束,过滤背景干扰
完整代码实现
import cv2 import numpy as np def detect_dartboard(frame): # 1. 预处理:灰度化+高斯模糊 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (7, 7), 1.5) # 2. 自适应阈值分割,适配不同光照 thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 3. 形态学操作:闭运算填充小间隙,开运算去除噪点 kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel) thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel) # 4. Canny边缘检测,提取环形纹理边缘 edges = cv2.Canny(thresh, 50, 150) # 5. 查找轮廓,只保留最外层轮廓 contours, _ = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) dartboard_contour = None for contour in contours: area = cv2.contourArea(contour) # 过滤过小/过大的轮廓(根据摄像头分辨率调整阈值) if area < 8000 or area > frame.shape[0]*frame.shape[1]*0.5: continue # 计算轮廓周长,用于多边形近似 perimeter = cv2.arcLength(contour, True) approx = cv2.approxPolyDP(contour, 0.02*perimeter, True) # 尝试拟合椭圆(至少需要5个点) if len(approx) >= 5: ellipse = cv2.fitEllipse(contour) (x, y), (MA, ma), angle = ellipse # 过滤极端纵横比的椭圆(飞镖盘非正视角下不会太扁或太窄) aspect_ratio = max(MA, ma)/min(MA, ma) if 0.5 < aspect_ratio < 2.0: # 验证轮廓面积与椭圆面积的匹配度(飞镖盘轮廓接近椭圆) ellipse_area = np.pi * (MA/2) * (ma/2) area_ratio = area / ellipse_area if 0.7 < area_ratio < 1.3: dartboard_contour = contour # 绘制检测结果 cv2.ellipse(frame, ellipse, (0, 255, 0), 2) cv2.circle(frame, (int(x), int(y)), 5, (0, 0, 255), -1) break return frame # 摄像头实时检测 cap = cv2.VideoCapture(0) # 可选:设置摄像头分辨率,提升检测精度 cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) while True: ret, frame = cap.read() if not ret: break processed_frame = detect_dartboard(frame) cv2.imshow('Dartboard Detection', processed_frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
测试注意事项
- 打印的飞镖盘尽量平整,避免褶皱导致纹理变形
- 调整摄像头角度,保证飞镖盘在画面中占比适中(不小于1/10画面)
- 避免强光直射,防止反光导致阈值分割失效
内容的提问来源于stack exchange,提问作者Indy2013
相关产品推荐
相关产品推荐

