《我的眼睛–图灵识别》第八章:训练:图像字符切割
图像字符切割是把图像上的每个文字分割成独立的单个字符,这是识别最有效的基础。
字符分割是图像识别最关键的一步,因为分割的正确与否直接关系到最后的结果,如果4个字符分割成了3个,即便后面的识别算法识别率达到100%,结果也是错的。当然,前面预处理如果做得够好,干扰因素能够有效的去除,而没有影响到字符的像素点(px),那么对分割来讲就容易得多。反过来,如果前面的干扰因素都没有去除掉,那么分割出来的可能就不是字符了。
字符的黏连是分割的难点,这一点也可以作为验证图形码安全系数的标准,如果图像上的几个字符完全是分开的,那么可以保证字符分割成功率是百分之百的,这样识别的难度就降低了很多。
图像字符切割的方法很多,比如:滴水分岭、水平垂直投影、离散聚类、傅里叶变换、八皇后、泛水填充、直方图和扫描线等等,这些都太专业了,不一般的人不用学,一般的人又学不会,至少我现在还都不会懂的玩:)
1、固定位置
固定位置(Fixed Location)切割方法就是,首先确定图像上的首个字符左上角的位置作为起始点坐标,并设置宽度和高度组成单个字符的切割范围,再确定切割的字符数量,即可进行准确定位切割出每个同等大小的独立字符。
主要适用于图像中的字符都是固定位置的,而且字与字之间还必须是间距相等的。
(等间距)固定位置切割
这是最基础的、最简单的和最粗暴的一种字符切割方法,它会无视字符黏连、位置错乱和干扰因素等等,但无法保证切割出来的字符是完整性的,有可能会出现少一部分或者多一部分数据的情况。
固定位置切割情况
等间距的图像字符如何进行固定位置切割?
具体操作步骤如下:
第1步,首先找到图像上的每个字与字之间的间隔距离,只需要对同大小或同个字符的左边位置进行距离计算即可;
原始图片
字之间的间距尺
第2步,之后在不变距离的情况下调整间距尺的位置,使其每个字符的最左边不能留有像素做到刚好对齐,这样就能确定每个字符最左边的位置;
字符最左边的位置
第3步,再找到所有字符的最上边和最下边的位置,就完成了高度范围的确定;
确定高度范围
第4步,此时已经能够得到首个字符的左上角的位置,完成了起点坐标的确定;
每个字符左上角位置
第5步,接着设置每个字符需要切割的宽度和切割的字符数量;
字符宽度和数量
第6步,最后根据首个字符左上角位置的起点坐标(假设1,1)、字符的宽高(5px和8px)、字符的间距(6px)和字符的切割数量(8),最终就完成了固定位置的字符切割。
进行固定切割
切割完成的字符
固定位置切割方法优缺点也是非常的明显,就是不灵活太死板了。优点就是不需要去遍历定位切割范围的时间;缺点就是切割位置死板,切割大小和数量都是固定的。
问题:
如果存在双排字符的图像,如何进行固定位置切割?
(作业)双排字符
VB6代码:
调用例子:
Dim 切割字符() As 切割类型
Call 切割_固定位置(图像数据, 0, 0, 5, 8, 6, 4, 切割字符)
封装函数:
Public Type 切割类型
宽 As Long
高 As Long
点阵 As String
End Type
Public Sub 切割_固定位置(图像数据() As Byte, 起点x As Long, 起点y As Long, 字宽 As Long, 字高 As Long, 字间距 As Long, 字数 As Long, 返回切割字符() As 切割类型)
Dim w As Long, h As Long, 宽 As Long, 高 As Long
Dim i As Long, x As Long, n As Long, 点数 As Long
Dim 字库点阵() As 切割类型, 单个点阵() As String, 多个点阵() As String
宽 = UBound(图像数据, 2)
高 = UBound(图像数据, 3)
n = 字数 - 1
ReDim 字库点阵(n) As 切割类型
ReDim 单个点阵(字高 - 1) As String, 多个点阵(字宽 - 1) As String
x = 起点x
For i = 0 To n
For w = 0 To 字宽 - 1
If w + x > 宽 Then Exit For '为数据越界处理
For h = 0 To 字高 - 1
If h + 起点y > 高 Then Exit For '为数据越界处理
If 图像数据(0, w + x, h + 起点y) = 255 Then
单个点阵(h) = 1
Else
单个点阵(h) = 0
End If
Next
多个点阵(w) = Left(Join(单个点阵, "") & String(字高, "0"), 字高) '拼接点阵
Next
点数 = 字宽 * 字高
字库点阵(i).宽 = 字宽
字库点阵(i).高 = 字高
字库点阵(i).点阵 = Left(Join(多个点阵, "") & String(点数, "0"), 点数) '拼接点阵
x = x + 字间距
Next
返回切割字符 = 字库点阵
End Sub
按键精灵2014脚本:
调用例子:
Call Plugin.TULING.Pixel_FromScreen(0,0,200,100)
Call Plugin.TULING.Filter_Binaryzation("0-128")
//显示获取的图像
Call Plugin.TULING.Pixel_Preview()
数量=Plugin.TULING.Incise_FixedLocation(0,0,64,64,50,3) //固定位置切割
For i = 0 To 数量
Call Plugin.TULING.Incise_Preview(i)
Next