如何提取边缘强度不均的图像矩形?支票账号提取难题求助
支票账号提取中浅色/细边缘矩形轮廓检测问题求助
我现在在做支票图像里的账号提取,思路是先定位账号所在的矩形区域,截取出这个 bounding rectangle 后再用OCR识别文本。但现在碰到个棘手的问题——当矩形轮廓不明显、颜色较浅时,边缘没法完全连通,根本提取不到对应的矩形contour。
我已经试过下面几种方法,但都没解决问题:
- 没法增加erosion的迭代次数:次数多了边缘会和周围的黑色像素连在一起,形成奇怪的形状,完全没法用;
- 降低threshold offset理论上可能有用,但效率太低:我的代码得适配各种支票,如果从offset=10开始逐步递增检查有没有找到矩形,那些轮廓明显、offset=20及以上就能正常识别的支票处理时间会被大幅拉长,而且现在也没条件判断矩形边缘是否明显,所有支票都得走一遍这个循环,太不现实了。
我用的库和版本是:
scikit-image==0.13.1 opencv-python==3.3.0.10
现有代码流程
步骤1:读取图像
image = cv2.imread('cropped.png')
步骤2:自适应阈值处理
我用skimage的自适应阈值来去除背景,以此定位账号的矩形框。这个方法在矩形轮廓清晰的支票上没问题,但碰到边缘较细或颜色浅的情况,阈值处理后边缘就断了,根本找不到contours。完整导入与处理代码如下:
from skimage.filters import threshold_adaptive, threshold_local import cv2 import numpy as np account_number_block = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) account_number_block = threshold_adaptive(account_number_block, 251, offset=20) account_number_block = account_number_block.astype("uint8") * 255
步骤3:腐蚀操作与轮廓查找
我尝试用轻微腐蚀来连接边缘的微小断点,然后查找轮廓:
kernel = np.ones((3,3), np.uint8) account_number_block = cv2.erode(account_number_block, kernel, iterations=5) (_, cnts, _) = cv2.findContours(account_number_block.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) # cnts = sorted(cnts, key=cv2.contourArea)[:3] rect_cnts = [] # Rectangular contours for cnt in cnts: approx = cv2.approxPolyDP(cnt,0.01*cv2.arcLength(cnt,True),True) if len(approx) == 4: rect_cnts.append(cnt) rect_cnts = sorted(rect_cnts, key=cv2.contourArea, reverse=True)[:1]
示例对比
成功案例(轮廓清晰的支票)
- 原始图像:HDFC银行支票的账号区域,矩形框轮廓清晰、颜色深,与背景对比度高
- 阈值处理后:背景被完全去除,矩形框的四条边缘完整连通,无断点
- 轮廓查找结果:成功筛选出面积最大的矩形轮廓,精准框住账号区域
失败案例(浅色矩形边界)
- 原始图像:SBI银行支票的账号区域,矩形框边缘颜色浅、线条细,与背景对比度低
- 阈值处理后:矩形框的边缘出现多处断点,无法形成完整的闭合矩形
- 轮廓查找结果:找不到符合条件的4边轮廓,无法定位账号所在的矩形区域
内容的提问来源于stack exchange,提问作者Parthapratim Neog
相关产品推荐
相关产品推荐

