OpenCV开发OCR/OCV应用时如何连接断裂字符的两个轮廓
问题背景
开发OCR/OCV应用时,已解决印刷文本墨迹扩散问题,但字符中间断裂(例如下图字母B)会导致同一字符被识别为多个独立轮廓,影响后续边界矩形提取与OCR识别,已尝试常规形态学开闭运算未得到理想效果。
当前轮廓提取代码基于EmguCV实现,逻辑为查找外轮廓后计算每个轮廓的近似多边形与外接矩形,在矩形区域内执行OCR/OCV操作,代码如下:
using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) { CvInvoke.FindContours(binaryimg, contours, null, RetrType.External, ChainApproxMethod.ChainApproxSimple); int count = contours.Size; for (int i = 0; i < count; i++) { double perimeter = CvInvoke.ArcLength(contours[i], true); VectorOfPoint approx = new VectorOfPoint(); CvInvoke.ApproxPolyDP(contours[i], approx, 0.04 * perimeter, true); CvInvoke.DrawContours(mainimg, contours, i, new MCvScalar(0, 255, 0), 2); Rectangle r = CvInvoke.BoundingRectangle(approx); id++; int area = r.Width * r.Height; int width = r.Width; int height = r.Height; } }
可行解决方案
- 优化形态学操作参数
常规3*3核闭运算无法连接断裂的核心原因是核尺寸小于断裂间隙,需先统计当前场景下单笔画的平均宽度,选择尺寸为「笔画宽度+12像素」的十字形/矩形结构元执行闭运算(先膨胀后腐蚀),即可在不造成相邻字符粘连的前提下连接同字符的断裂部分。如果断裂以垂直/水平单方向为主,可使用定向结构元:比如示例中B的横向断裂,可使用高度为35像素、宽度为1像素的竖形结构元做闭运算,仅连接上下方向的邻近像素,完全避免左右字符误连。 - 轮廓外接矩形后合并
跳过单轮廓直接生成识别区域的逻辑,新增矩形合并步骤:- 先提取所有轮廓的外接矩形存入集合,统计场景内无缺陷正常字符的平均宽度、高度、宽高比范围、字符平均间距作为判定阈值
- 遍历集合内所有矩形对,满足三个条件即可判定为同一字符的断裂部分:两个矩形的垂直投影重叠率大于60%、矩形水平/垂直间距小于2倍平均笔画宽度、合并后矩形的宽高比落在正常字符宽高比区间内
- 合并符合条件的矩形,重复遍历直到集合内无符合合并条件的矩形,最终用合并完成的矩形作为OCR识别区域
- 从源头减少断裂
多数字符断裂是全局二值化阈值过高导致,将全局二值化替换为自适应高斯二值化,调整块大小与偏移补偿参数,可保留浅印的笔画部分,从源头上减少断裂轮廓的产生。
内容的提问来源于stack exchange,提问作者Alisha
相关产品推荐
相关产品推荐

