在前一篇文章印刷体中文字符的分割中,我们对于图像中的印刷体字符分割进行了介绍,细心的网友可能会发现,现实生活中我们从书中拍到的文本图像往往是如图1的情况。图像文本中会会有一定的角度错位。
图1:存在旋转图像及其投影结果
对于这样的图像,如果我们使用上文中提到的二值化,然后进行投影,可以看到y方向的投影是没有办法进行按行分割的。处理方法有很多,本文提供一种利用角度变换来进行矫正的方法以供大家参考借鉴。主要包括两个步骤:一是旋转角计算,二是图像任意角度旋转。
一、旋转角计算
细心的网友可能会发现,如果我们给做每一行文本做一个外接最小矩形,那么他的长边是基本平行的,如图2所示。
图2:文字行的外接矩形
如果我们能够找到这些外接矩形与水平方向的夹角,也就是图像的旋转角,实现方法如图3所示:
具体来说:
第15-第17行:将图像进行膨胀。由于一行中的每个文字之间存在间隙,如果直接进行处理,将得不到每行文字的整体结果,通过膨胀,使得一行中的大部分文字能够形成一个整体,从而利用后续的操作来找到整体的外接矩形。其中v_span和h_span分别表示水平方向和垂直方向膨胀大小,一般来说水平方向要大于垂直方向,从而同一文本行能够形成一个整体。
第19行:查找图像的外接轮廓。该函数的输入图像要求是二值化的图像,同时返回图像,轮廓列表和结构关系。具体的用法大家可以查阅官方文档,在此不进行展开。
第22行:设置旋转角精度。轮廓查找得到的旋转角度往往存在一定的误差,我们的思路是使用旋转角度出现次数最多的角度作为整体的旋转角。如果直接使用浮点型的数据来进行比较,数据将非常分散,通过设置一个精度值,实现将精度范围内的角度进行合并处理。
第23-27行:使用minAreaRect函数计算每个子轮廓的旋转角并保存起来。minAreaRect函数有3个输出,分别是左上角坐标、右下角坐标以及偏转角。
第29-30行:使用collections模块中的Counter方法得到旋转角中出现次数最多的角度,并恢复成原始角度。
二、图像旋转
计算出旋转角后,就要将图像进行矫正,实现的方法主要是利用OpenCV中提供的仿射变换功能,实现方法如下:
具体来说:
第32-34行:计算新的图像长度和宽度。其中高度计算原理如图5所示,对于任意的旋转角,新的图像高度为图中两段红线的总长度,即:新的高度等于宽度乘以正弦加上高度乘以余弦。宽度的计算方法类似。
图5:旋转后高度的计算示意图
第36-39行:使用OpenCV提供的getRotationMatrix2D方法计算旋转矩阵,需要提供旋转中心的旋转角。计算出矩阵之后要进行平移。因为一但旋转,就会使坐标值出现负值。
第41-42行:使用warpAffine进行变换。需要提供四个参数:图像,旋转矩阵,旋转后的高度、宽度以及填充值。
通过以上操作,我们就能得到一幅标准图像,如图6所示。
图6:旋转矫正后的图像
至此,我们通过旋转角计算及图像旋转,将一个幅有角度偏差的图像变成标准图像,从而能够利用投影法等方法来进行字符的分割。
作者:花木兰
申明:本文为易学智能原创内容,如需转载请私信
欢迎关注“易学智能”头条号,评论区有问必答
www.ea论坛提在线开发和学习平台