OpenCV骰子识别作业:骰子外接矩形绘制异常问题求助
解决OpenCV骰子识别中外接矩形绘制不准确的问题
Hey there! 很高兴看到你已经搞定了骰子点数统计的核心功能,这已经很棒了!针对你遇到的外接矩形(bounding box)无法稳定正确绘制的问题,我给你整理几个实用的优化方向,应该能帮你解决这个小麻烦:
一、优化预处理流程,减少噪点干扰
外接矩形画不准,很多时候是因为预处理没做好,导致无效轮廓被检测出来。你可以试试这些调整:
- 替换固定阈值二值化:用
cv2.adaptiveThreshold()代替cv2.threshold(),它能根据图像局部区域的光照自动调整阈值,对于桌面这种可能存在光照不均的场景,能更精准地分离骰子和背景。 - 增加形态学操作:用
cv2.morphologyEx()做开运算(先腐蚀再膨胀),可以过滤掉图像中的小噪点;如果骰子表面有小孔,也可以用闭运算填充,避免这些细节被当成独立轮廓。
二、给轮廓加“筛选条件”,只保留骰子的轮廓
拿到所有轮廓后,不要直接给每个轮廓画矩形,通过几个维度过滤无效轮廓:
- 面积过滤:计算每个轮廓的面积
cv2.contourArea(contour),设置合理的最小/最大阈值(比如根据你的图像,骰子面积大概在500-5000像素之间,你可以自己调整),过滤掉太小的噪点和太大的背景区域。 - 长宽比过滤:骰子是近似正方形的,计算外接矩形的宽高比
width/height,只保留比值在0.8-1.2之间的轮廓,排除细长的无效区域。 - 轮廓近似过滤:用
cv2.approxPolyDP()把轮廓近似成多边形,骰子的轮廓应该是四边形,所以可以判断近似后的顶点数是否为4,进一步筛选出骰子的轮廓。 - 层级过滤:如果你的点数轮廓被当成了独立轮廓,可以用
cv2.findContours()返回的hierarchy参数,只选择没有子轮廓的父轮廓(也就是骰子本身的轮廓),忽略点数的子轮廓。
三、尝试旋转自适应的最小外接矩形
如果你现在用的是cv2.boundingRect()(轴对齐的矩形),对于倾斜的骰子可能会框出多余的区域。可以换成cv2.minAreaRect(),它能生成贴合骰子旋转角度的最小矩形,不过需要用cv2.boxPoints()把返回的矩形参数转换成顶点坐标才能绘制。
示例代码片段
这里给你一段简单的轮廓过滤+矩形绘制的示例,你可以参考调整:
import cv2 import numpy as np # 读取图像并预处理 img = cv2.imread("dice_image.jpg") gray = cv2.cvtColor(img, 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) thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel) # 查找轮廓及层级 contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for idx, cnt in enumerate(contours): # 过滤面积不符合的轮廓 area = cv2.contourArea(cnt) if area < 400 or area > 6000: continue # 计算外接矩形并过滤长宽比 x, y, w, h = cv2.boundingRect(cnt) aspect_ratio = w / float(h) if not 0.75 < aspect_ratio < 1.25: continue # 只绘制没有子轮廓的父轮廓(骰子本体) if hierarchy[0][idx][2] == -1: cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) # 显示结果 cv2.imshow("Dice Detection", img) cv2.waitKey(0) cv2.destroyAllWindows()
你可以根据自己的实际图像调整阈值参数,应该能有效改善外接矩形的绘制准确性!
内容的提问来源于stack exchange,提问作者Mr.Potatinator
相关产品推荐
相关产品推荐

