基于OpenCV的复选框勾选状态检测问题求解
复选框勾选状态检测优化方案

原有方案问题
你当前通过轮廓长度判断是否勾选的逻辑鲁棒性较差,不同尺寸的复选框、扫描/拍摄产生的形变、图像噪点都会导致固定阈值210失效,无法稳定判断勾选状态。
优化实现逻辑
换用复选框内部有效像素占比作为判断依据,适配性更强:
- 先对识别到的轮廓做形状校验,过滤宽高比偏差过大、面积不符合要求的非复选框轮廓,减少误识别
- 提取每个复选框的内部ROI区域,统计反二值图中ROI内的非零像素占比(反二值化后勾选的笔迹为白色像素)
- 占比超过设定阈值即判定为已勾选,阈值可根据实际场景调整,通用场景下设置为5%~15%即可
优化后可运行代码
import os import cv2 file_path = "page1.jpg" # 勾选判断阈值,ROI内白色像素占比超过该值判定为已勾选,可按需调整 TICK_THRESHOLD = 0.1 # 复选框宽高比允许误差,越接近1越接近正方形 ASPECT_RATIO_TOLERANCE = 0.2 if os.path.isfile(file_path): # 读取图像 img = cv2.imread(file_path, 1) # 转灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 反二值化 _, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU) # 查找轮廓 contours, hierarchy = cv2.findContours(binary, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) img2 = img.copy() boxes_found = 0 ticked_count = 0 for cnt in contours: # 过滤过小的噪点轮廓 area = cv2.contourArea(cnt) if area < 100: continue # 校验形状是否接近正方形 x, y, w, h = cv2.boundingRect(cnt) aspect_ratio = w / h if abs(aspect_ratio - 1) > ASPECT_RATIO_TOLERANCE: continue # 提取复选框内部ROI,向内缩进2像素避免边框干扰统计 roi_x, roi_y = x + 2, y + 2 roi_w, roi_h = w - 4, h - 4 if roi_w <= 0 or roi_h <=0: continue roi = binary[roi_y:roi_y+roi_h, roi_x:roi_x+roi_w] # 统计ROI内非零像素占比 non_zero_pixels = cv2.countNonZero(roi) total_pixels = roi_w * roi_h tick_ratio = non_zero_pixels / total_pixels boxes_found +=1 if tick_ratio > TICK_THRESHOLD: # 已勾选用绿色框标记 cv2.rectangle(img2, (x,y), (x+w, y+h), (0,255,0), 2) ticked_count +=1 print(f"选项{boxes_found}:已勾选") else: # 未勾选用红色框标记 cv2.rectangle(img2, (x,y), (x+w, y+h), (0,0,255), 2) print(f"选项{boxes_found}:未勾选") cv2.imshow('检测结果', img2) cv2.waitKey(0) cv2.destroyAllWindows() print(f"共识别到复选框:{boxes_found}个,其中已勾选:{ticked_count}个") else: print("文件不存在")
参数调整说明
- 如果漏检小尺寸复选框,可适当调小
area < 100的面积阈值 - 如果误把噪点判定为勾选,可适当调高
TICK_THRESHOLD的数值 - 如果处理的是长方形样式的复选框,可适当调大
ASPECT_RATIO_TOLERANCE的数值
内容的提问来源于stack exchange,提问作者Nithishkumar
相关产品推荐
相关产品推荐

