字符識別中的圖像歸一化算法


源地址: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找到。希望對大家有所幫助。

 

 

線性歸一化:線性歸一化算法就是一個標准的線性采樣過程,采用線性插值獲得最終的圖像結果。在我們的實現中,使用反向計算的方式:

其中為長和寬的比值。

 

對應代碼中的函數為:

 

[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);  
[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]后,后續即調用線性歸一化算法即可。對應代碼中的實現為:

 

[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);  
[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。其實現對於:

 

[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);  
[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:

通過前向映射采樣即可實現歸一化操作:

 

注意這里與前兩個算法的不同之處,前向映射是將當前圖像的某個像素映射到歸一化的圖像中。而反向映射則是將歸一化的圖像中的某個像素位置映射到原圖像中。

非線性歸一化的實現對應:

 

[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);  
[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]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM