如何基于OpenCV识别问卷中X/V标记的选中单元格?
问卷X/V标记选中单元格的识别方案
问题背景
我需要处理问卷,将选中选项以布尔值(true/false)存入数据库。通过Microsoft Recognize定位表格后,用OpenCV裁剪单元格图像判断选中状态,核心裁剪代码如下:
imagePage = cv2.imread(image.path) x = int(coordinates[0]) y = int(coordinates[1]) w = int(coordinates[2]) h = int(coordinates[3]) imageCell = imagePage[y:y+h, x:x+w] cv2.rectangle(imagePage, (x, y), (x + w, y + h), (0, 255, 0), 3)
最初尝试统计黑像素数量判断选中,但单元格边框的黑像素干扰导致方法失效,统计黑像素的代码如下:
def countBlackPixels(imageCell): lowerBlack = np.array([0, 0, 0], np.uint8) blackRange = cv2.inRange(imageCell, lowerBlack, lowerBlack) blackPixels = cv2.countNonZero(blackRange) return blackPixels
例如两个带X的单元格分别统计出258和98个黑像素,无法有效区分选中状态。
可行识别方法
1. 预处理消除边框干扰
- 先将单元格图像转为灰度图并二值化,突出标记与边框的差异:
gray = cv2.cvtColor(imageCell, cv2.COLOR_BGR2GRAY) _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV) - 用形态学开运算去除细小边框线条,保留内部标记:
kernel = np.ones((3,3), np.uint8) cleaned = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel, iterations=1) - 之后统计清理后图像的非零像素数量,设定合理阈值判断是否选中。
2. 轮廓检测与过滤
- 对二值化后的图像提取轮廓,过滤掉边框的大轮廓和噪点的小轮廓:
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 根据实际场景调整面积阈值 valid_contours = [cnt for cnt in contours if 50 < cv2.contourArea(cnt) < 500] - 若存在有效轮廓,判定单元格为选中(true),否则为未选中(false)。
3. 模板匹配
- 提前制作标准的X/V模板图像,对每个单元格进行模板匹配:
# 加载灰度模板 template = cv2.imread('x_template.png', 0) t_w, t_h = template.shape[::-1] # 执行匹配 res = cv2.matchTemplate(gray, template, cv2.TM_CCOEFF_NORMED) # 设定匹配阈值(需根据实际调整) match_threshold = 0.8 loc = np.where(res >= match_threshold) - 若匹配结果中存在超过阈值的区域,说明单元格内有对应标记,判定为选中。
4. 简单机器学习分类
- 提取单元格图像的特征(如像素密度、轮廓数量、Hu矩等),用少量标注样本训练SVM或KNN分类器:
from sklearn.svm import SVC # 假设已准备好训练特征和对应标签(1=选中,0=未选中) clf = SVC() clf.fit(train_features, train_labels) # 预测新单元格状态 is_selected = bool(clf.predict(new_cell_feature))
内容的提问来源于stack exchange,提问作者beg2016
相关产品推荐
相关产品推荐

