如何区分扫描图像中的手写内容与打孔标记,优化空白检测?
解决方案:区分手写有效页与打孔空白页
核心思路
通过特征形态分析替代单一的像素占比或OCR,精准区分手写的连续线条和打孔的离散小斑点,避免误判。
具体实现步骤
1. 预处理:灰度化+自适应二值化
先统一图片格式,用自适应二值化适配手写内容的对比度不均问题,比全局二值化更鲁棒:
import cv2 img = cv2.imread("target_image.jpg") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 自适应二值化,突出手写内容同时弱化打孔斑点 binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
2. 形态学过滤:开运算+轮廓面积筛选
放弃单纯的cv2.dilate(),改用开运算先腐蚀去除小斑点,再膨胀恢复手写线条,接着通过轮廓面积区分有效内容与打孔噪声:
# 定义适配手写线条的矩形结构元素,过滤圆形打孔斑点 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) # 开运算:先腐蚀消去打孔斑点,再膨胀还原手写线条 opened = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel, iterations=1) # 提取轮廓并过滤面积过小的噪声 contours, _ = cv2.findContours(opened, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 面积阈值根据图片分辨率调整,打孔斑点面积通常<50像素,手写线条单笔画>50 valid_contours = [cnt for cnt in contours if cv2.contourArea(cnt) > 50]
3. 双重验证:轮廓特征+局部OCR
对筛选出的有效轮廓区域,结合轻量OCR进一步确认是否为手写内容:
import pytesseract if len(valid_contours) > 0: # 提取所有有效轮廓的外接区域,只识别关键区域减少OCR误差 x, y, w, h = cv2.boundingRect(cv2.vconcat(valid_contours)) roi = gray[y:y+h, x:x+w] # 用psm 6模式针对单一文本块识别,适配手写内容 text = pytesseract.image_to_string(roi, config='--psm 6') # 两种判定条件:有可识别文字 或 轮廓总面积达标 if len(text.strip()) > 0 or sum(cv2.contourArea(cnt) for cnt in valid_contours) > 200: print("保留页面:存在手写内容") else: print("删除页面:仅打孔噪声") else: print("删除页面:无有效内容")
4. 参数调优建议
- 轮廓面积阈值:根据你的图片分辨率调整,比如高分辨率图可将阈值设为100
- 结构元素:细手写用(2,2)矩形,粗手写用(3,3)矩形
- OCR参数:手写分散时改用
--psm 11模式
效果说明
- 打孔图:开运算过滤所有小斑点,无有效轮廓,判定为空白页删除
- 手写图:开运算保留连续线条,轮廓面积达标,结合OCR验证后判定为有效页保留
内容的提问来源于stack exchange,提问作者anonymousaccount32784
相关产品推荐
相关产品推荐

