扫描图像手写标记图形分类问题求助:SVM模型优化需求
问题描述
我正在实现扫描图像中的标记图形分类,需区分以下类别:
- 划叉方块
- 完全涂黑方块
- 空白方块
- 划叉/涂黑圆圈
- 空白圆圈
当前实现流程:
- 识别外部黑边框
- 对齐图像以补偿扫描偏移
- 提取ID条形码
- 将图像分割为小方块,每个方块包含一个圆圈或方块
- 对每个方块分类(划叉方块标绿、涂黑方块标蓝、划叉/涂黑圆圈标红,空白图形无需处理)
核心实现代码(evaluator.py中的detect_answers函数):
def detect_answers(bgr_image: np.array, bgr_img_for_debug: np.array, x_cut_positions: List[int], y_cut_positions: Tuple[int], is_60_question_sim, debug: str): question_multiplier: int = 15 if is_60_question_sim else 20 letter: Tuple[str, ...] = ("L", "", "A", "B", "C", "D", "E") user_answer_dict: Dict[int, str] = {i: "" for i in range(1, 61 - 20 * int(not is_60_question_sim))} gr_image: np.array = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2GRAY) # load SVM model load_path = os.getcwd() clf = load(os.path.join(load_path, "reduced.joblib")) for y_index in range(len(y_cut_positions) - 1): for x_index in range(len(x_cut_positions) - 1): # if you are on a column with only numbers, skip it if not (x_index - 1) % 7: continue x_top_left = int(not x_index % 7) * 7 + x_cut_positions[x_index] x_bottom_right = int(not x_index % 7) * 2 + x_cut_positions[x_index + 1] y_top_left: int = y_cut_positions[y_index] y_bottom_right: int = y_cut_positions[y_index + 1] crop_for_prediction: np.array = gr_image[y_top_left:y_bottom_right, x_top_left:x_bottom_right] crop_for_prediction: np.array = cv2.resize(crop_for_prediction, (18, 18)) # category = ("QB", "QS", "QA", "CB", "CA") # 0 1 2 3 4 crop_for_prediction: np.array = np.append(crop_for_prediction, [x_index % 7, int(np.mean(crop_for_prediction))]) predicted_category_index: int = clf.predict([crop_for_prediction])[0] return user_answer_dict
当前存在的问题:
- 依赖像素均值、黑像素计数等简单特征的SVM模型,无法可靠处理手写差异
- 分类错误频发,例如第1题D选项(涂黑方块)未被正确标记,最后一列图形几乎全部识别错误
- 需要满足高效性要求,每次需处理500-800份测试卷
优化建议
1. 特征工程优化
- 增加形状与纹理特征:
- 用
cv2.findContours提取轮廓,计算轮廓面积、周长、近似多边形顶点数,区分方块(4个顶点)和圆圈(近似圆形的顶点数)的形状差异 - 统计目标区域(方块/圆圈的固定范围)内的黑像素占比,比如涂黑方块中心区域黑像素占比接近100%,划叉方块则有明显的线条分布
- 提取HOG(方向梯度直方图)特征,捕捉手写划叉的纹理方向,比单纯像素均值更鲁棒
- 用
- 移除冗余特征:当前代码中加入的
x_index%7列索引特征可能引入偏差(导致最后一列识别全错),建议先移除该特征,验证分类效果是否改善
2. 模型改进
- 替换为轻量CNN模型:SVM对复杂手写特征拟合能力有限,改用3-4层卷积+池化的自定义小CNN,或MobileNetV2精简版,自动提取更有效的视觉特征
- 训练时加入数据增强:对标注数据做±5度旋转、小范围平移、轻微缩放、灰度扰动,模拟扫描偏移和手写差异,提升模型泛化性
- 模型量化:对训练好的CNN做INT8量化,在几乎不损失精度的前提下提升推理速度,满足批量处理需求
3. 预处理优化
- 自适应二值化:用
cv2.adaptiveThreshold替代单纯灰度转换,应对扫描时的光照不均问题,确保手写标记与背景的分割更准确 - 分割区域校准:最后一列识别全错可能是
x_cut_positions的分割逻辑有偏差,打印分割后的裁剪图,验证最后一列的区域是否正确包含目标图形,调整x_top_left和x_bottom_right的计算逻辑
4. 后处理逻辑
- 规则校验:结合题目选项的分布逻辑(通常每题仅一个标记选项),对分类结果做校验,若同一题目出现多个高置信度标记,保留置信度最高的结果,或标记为异常待人工复核
- 置信度过滤:使用
clf.predict_proba获取分类置信度,只保留置信度高于阈值(如0.8)的结果,低置信度样本暂存后批量人工处理
内容的提问来源于stack exchange,提问作者Lorenzo Paolin
相关产品推荐
相关产品推荐

