字符识别中的图像归一化算法

源地址:http://blog.csdn.net/rushkid02/article/details/9242415

本文介绍3种基本的字符形状归一化算法(Character Shape Normalization)。字符归一化是光学字符识别中的一个子步骤,给定一个字符区域,我们要做的就是将该区域内的字符归一化到一个标准模板大小,然后才能提取特征,并送给分类器做具体的识别。好的归一化算法可以尽量提高后续特征提取在同一类内的一致性。

 

先来看一个例子,假如上帝拥有一个完美的字符归一化算法,那么他将可以做到如下所示的效果:

 

 

图1,完美的归一化:左边为原始字符区域,右边为归一化后的结果。

 

如果说我们能做到上述结果,那么也就无需再做特征提取,也无需再做训练,而只需简单的模板匹配即可得到100%准确的分类结果。可以看到,上述算法的能力在于:

1. 归一化到标准模板大小

2. 倾斜校正

3. 笔画宽度归一化

4. 字形归一化

 

可惜的是,今天介绍的几种常见算法仅能保证第1点的实现,而2,3则只能实现部分。至于4,就让后续的特征提取去弥补吧。言归正传,3个算法分别是:线性归一化算法,基于图像矩的归一化以及非线性归一化算法。

 

 

按惯例,3个算法的标准c实现可在:

https://github.com/UnilVision/visionbase/tree/master/ocr/baseline/normalization找到。希望对大家有所帮助。

 

 

线性归一化:线性归一化算法就是一个标准的线性采样过程,采用线性插值获得最终的图像结果。在我们的实现中,使用反向计算的方式:

其中为长和宽的比值。

 

对应代码中的函数为:

 

  1. void backward_linear(unsigned char* src, int src_wid, int src_hei, int src_widstep,  
  2.                      CHARECT_t* region,  
  3.                      unsigned char* dst, int dst_wid, int dst_hei, int dst_widstep,  
  4.                      int ratio_preserve_func);  
[cpp] view plain copy
 
 print?
  1. void backward_linear(unsigned char* src, int src_wid, int src_hei, int src_widstep,  
  2.                      CHARECT_t* region,  
  3.                      unsigned char* dst, int dst_wid, int dst_hei, int dst_widstep,  
  4.                      int ratio_preserve_func);  

 

 

图像矩归一化: 我们可以通过图像矩来预先校正字符的倾斜度,并通过矩来获得字体的实际大小[w1, h1]及中心位置[xc, yc]。归一化的原始区域被修改为

[xc-w1/2, xc+w1/2, yc-h1/2, yc+h1/2]。其计算方法为:

是一个经验值,一般取4。

 

其中图像矩的计算方法:



在找到新的区域[xc-w1/2, xc+w1/2, yc-h1/2, yc+h1/2]后,后续即调用线性归一化算法即可。对应代码中的实现为:

 

  1. void backward_moment(unsigned char* src, int src_wid, int src_hei, int src_widstep,  
  2.                      CHARECT_t* region,  
  3.                      unsigned char* dst, int dst_wid, int dst_hei, int dst_widstep,  
  4.                      int ratio_preserve_func);  
[cpp] view plain copy
 
 print?
  1. void backward_moment(unsigned char* src, int src_wid, int src_hei, int src_widstep,  
  2.                      CHARECT_t* region,  
  3.                      unsigned char* dst, int dst_wid, int dst_hei, int dst_widstep,  
  4.                      int ratio_preserve_func);  

 

 

图像矩倾斜校正:利用图像矩,我们可以找到字符的倾斜角

采样计算方式为:

注意这里我们仅调整x的位置以保证图像的中心仍然处于原始的xc,yc。其实现对于:

 

  1. // slant correction   
  2. // Note>> (dst_wid, dst_hei) must equal to (region.width, region.height)   
  3. void backward_moment_slantcorrection(unsigned char* src, int src_wid, int src_hei, int src_widstep,  
  4.                      CHARECT_t* region,  
  5.                      unsigned char* dst, int dst_wid, int dst_hei, int dst_widstep);  
[cpp] view plain copy
 
 print?
  1. // slant correction  
  2. // Note>> (dst_wid, dst_hei) must equal to (region.width, region.height)  
  3. void backward_moment_slantcorrection(unsigned char* src, int src_wid, int src_hei, int src_widstep,  
  4.                      CHARECT_t* region,  
  5.                      unsigned char* dst, int dst_wid, int dst_hei, int dst_widstep);  


通常倾斜校正会放在归一化之前,已获得更好的效果。

 

 

非线性归一化:这里实现的是Jun Tsukumo在1988年提出的一个经典算法(原论文名称为Classification of Handprinted Chinese Characters Using Non-linear Normalization and Correlation Methods)。作者的思路是希望每一行,每一列的背景区域都可以平均分布。

为此,他首先为每个像素在x,y方向分别定义了个概率密度函数:以及。这两个函数的计算方法是:

如果(x,y)是一个属于字符区域的像素,那么都取一个极小值(在我们的实现中,这个值是0.001f,调整这个参数可以引起归一化后笔画的粗细变化)。

如果(x,y)是背景区域像素,那么:

其中分别是当前像素所处x方向背景像素的run-length和y方向的run-length。有了这两个密度函数,定义:

这里px和py就是归一化后的投影直方图了,为了在归一化后的图像中让px和py平均分布,引入两个函数hx,hy:

通过前向映射采样即可实现归一化操作:

 

注意这里与前两个算法的不同之处,前向映射是将当前图像的某个像素映射到归一化的图像中。而反向映射则是将归一化的图像中的某个像素位置映射到原图像中。

非线性归一化的实现对应:

 

  1. void forward_nonlinear_1d(unsigned char* src, int src_wid, int src_hei, int src_widstep,  
  2.                           CHARECT_t* region,  
  3.                           unsigned char* dst, int dst_wid, int dst_hei, int dst_widstep,  
  4.                           int ratio_preserve_func);  
[cpp] view plain copy
 
 print?
  1. void forward_nonlinear_1d(unsigned char* src, int src_wid, int src_hei, int src_widstep,  
  2.                           CHARECT_t* region,  
  3.                           unsigned char* dst, int dst_wid, int dst_hei, int dst_widstep,  
  4.                           int ratio_preserve_func);  

 

 

参考结果

最后看下各个算法的结果:


图2,参考结果。从左到右依次:1. 原始扣取的图像通过OpenCV的resize函数缩放。2. 线性归一化。3.基于矩的归一化。4.先倾斜校正再基于矩的归一化。5.非线性归一化。

 

[原创文章,转载请注明出处:http://blog.csdn.net/unilvision/article/details/8624606]

posted @ 2016-04-07 14:45  蓝夜  阅读(4200)  评论(0编辑  收藏  举报