如何检测轮盘赌图像中的两个椭圆并生成其封闭区域掩码以实现后续球检测
如何检测轮盘赌图像中的两个椭圆并生成其封闭区域掩码以实现后续球检测
看起来你已经尝试了基础的边缘检测和轮廓提取,但轮盘图里的数字、刻度这些干扰元素很容易让普通的轮廓检测失效。针对这种椭圆(实际是透视变形的圆)检测的需求,我们可以结合阈值分割+形态学去噪+椭圆拟合的思路来实现,下面是具体的步骤和代码:
步骤1:图像预处理——去除干扰,突出椭圆轮廓
首先我们需要把图像里的干扰线条(比如数字、刻度)过滤掉,只保留椭圆的轮廓:
import cv2 import numpy as np # 加载图像 image = cv2.imread('roulette.png') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 自适应阈值分割:针对光线不均匀的场景,突出深色椭圆轮廓 thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 形态学开运算:去除小的噪声点(比如数字的像素) kernel = np.ones((3,3), np.uint8) cleaned = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
步骤2:提取轮廓并筛选椭圆候选
接下来提取轮廓,然后通过轮廓的面积、形状来筛选出我们需要的两个椭圆轮廓:
# 寻找轮廓 contours, _ = cv2.findContours(cleaned.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 筛选轮廓:只保留面积较大、且能拟合出椭圆的轮廓 ellipses = [] for cnt in contours: # 轮廓点数量足够才能拟合椭圆 if len(cnt) >= 5: area = cv2.contourArea(cnt) # 根据你的图像调整面积阈值,过滤掉小的干扰轮廓 if area > 10000: ellipse = cv2.fitEllipse(cnt) ellipses.append(ellipse) # 确保我们找到了两个椭圆(如果数量不对,可以调整面积阈值) if len(ellipses) != 2: print("Warning: 检测到的椭圆数量不符合预期,请调整参数")
步骤3:生成中间封闭区域的掩码
现在我们有了两个椭圆的参数(中心、轴长、旋转角度),接下来生成掩码:中间的环形区域(大椭圆减去小椭圆)就是我们需要的球检测区域。
# 创建空白掩码,大小和原图一致 mask = np.zeros_like(gray) # 区分大椭圆和小椭圆:通过长轴长度判断 ellipses.sort(key=lambda x: x[1][0], reverse=True) big_ellipse, small_ellipse = ellipses # 先在掩码上填充大椭圆(白色) cv2.ellipse(mask, big_ellipse, 255, -1) # 然后用黑色填充小椭圆,得到中间的环形区域 cv2.ellipse(mask, small_ellipse, 0, -1) # 现在mask就是我们需要的封闭区域掩码,可以用来后续检测球 # 比如把掩码和原图结合,只保留中间区域 result = cv2.bitwise_and(image, image, mask=mask) # 显示结果 cv2.imshow('Mask', mask) cv2.imshow('Result', result) cv2.waitKey(0) cv2.destroyAllWindows()
额外优化建议
- 如果轮盘近似正圆,也可以尝试用
cv2.HoughCircles来检测,操作会更简单;部分OpenCV版本支持cv2.HoughEllipses,也可以尝试该方法 - 如果椭圆拟合有偏差,可以调整阈值分割的参数,或者增加形态学操作的迭代次数,进一步去除干扰
- 针对拍摄角度导致的椭圆变形,拟合后的椭圆参数可以用来校正图像,让后续球检测更准确
备注:内容来源于stack exchange,提问作者Blind0ne
相关产品推荐
相关产品推荐

