背景
本文,主要介紹我之前在學校時候,研究的一些跟手寫數字識別相關的技術心得,主要涉及:數字圖像處理、特征提取、神經網絡等等相關的一些技術。。
雖然很多用到的還是網上現有的比較成熟的算法,但是在這些基礎上,我還是有做了不少算法上的改進的。。
並且為了寫這個項目,我當時還特地寫了一整套神經網絡庫,從圖像處理開始到最后的識別過程,沒有使用任何第三方庫,都是從0還是寫起
也沒有用到opencv啊什么的。
上層ui當時用的qt,雖然當時也算是為了跨平台,但那個時候畢竟還是學生,代碼經驗欠缺,因此我的基礎庫對跨平台處理的並不是很好。。
那個基礎庫,我稍微簡單說下,那是我的第一個開發庫,是一個類似boost的c++模板庫,里面用到了很多c++的模板元編程的特性,但是現在已經對c++無愛了,所以早已廢棄不用了。
不過也就是這個庫的開發,很大程度上影響了我之后的編碼風格,也是至此之后,我重點轉向了對c的開發上。。
這套識別系統,僅僅是我當時為了學習神經網絡,拿來練手用的,沒法跟那些成熟的相比,識別率不是很高哈,只能給大家用來參考學習了。
簡介
本文在基本BP算法和數字圖像與處理的基礎上,通過改進網絡、圖像處理算法,並結合實踐來探索如何實現具有高魯棒的、高精度的、高效率的脫機數字識別。
在這我主要研究脫機單體數字識別,其主要步驟為:

overview_1
數字樣本的采集
主要采用5行10列的數字樣本規格。采集方式是通過掃描樣本卡片來獲取圖像,也盡量避免樣本了的失真,如圖:

overview_2
圖像二值化
主要采用全局閾值分割法和自適應的局部閾值分割法,來實現在不同亮度背景下的自適應分割,並對結果進行比對。
數字提取
目前主要考慮聚類法、矩陣式分割法、連通區域標記法,並比較其優劣,選取效果最好的一種算法。
圖像歸一化
主要采用雙線性內插和最鄰近內插來實現放大,為了減少圖像在收縮時帶來的失真,目前打算采用求平均法來實現。
特征提取
主要采用逐像素提取法,PCA主成分提取兩種方法來實現。
樣本學習
主要采用基於BP算法(反向傳播學習算法)的神經網絡進行識別,並對BP進行一定的改進和優化,來改進訓練效果並且適當的提高訓練速率。
目前,針對BP的改進算法,主要采添加動量項和自適應步長法。
而對於BP算法,其主要步驟為:
前向計算=〉反向計算=〉權值修正=〉循環迭代
為了進一步改進網絡,實現高精度、高效率的識別,打算考慮采用多網絡集成法,來進行優化。
主要針對不同權值、隱層數的基本BP網絡進行集成。通過每個網絡分類的結果進行加權輸出,來達到有效的分類。
閾值分割
閾值分割法是一種基於區域的圖像分割技術,其基本原理是:通過設定不同的特征閾值,把圖像像素點分為若干類。
在本文中,我們主要處理針對兩類的分割,令閾值為T,圖像像素對應的灰度級為f(x, y) ,那么經閾值分割后的圖像 g(x, y) 定義為:

split_1
因此,標記為1的像素對應於對象,也就是前景,而標記為0的對象對應於背景,也就是我們通常所說的圖像二值化。
利用閾值分割進行圖像二值化的主要難題就是閾值的選取,事實證明,閾值的選擇的恰當與否對分割的效果起着決定性的作用。
常用的閾值分割方法有以下三種:
整體閾值法
利用整幅圖像的信息對圖像求出最優閾值, 在二值化分割過程中只使用這一個固定閾值,因此計算量小,但對於亮度條件不好的圖像的分割效果較差。
局部閾值法
它是把原始圖像分為幾個小的子圖像,再對每個子圖像求出最佳閾值。因此效果較好,但開銷較大,且局部大小不太好確定,太小容易失真,太大效果不顯著。
動態閾值法
它的閾值求取方法不僅取決於該像素的灰度值及其領域內像素灰度值, 而且還與像素的坐標位置有關, 這種方法靈活性大, 但是復雜度高, 計算量和時間開銷都比較大。
而岡薩雷斯寫的那本書 數字圖像處理 里面,給出了一種最小誤差閾值,通過利用共軛梯度法對灰度直方圖進行雙峰的高斯密度曲線進行擬合,求取最佳閾值,效果相當好,但是計算太大,而且對於雙峰不顯著的圖像比較難處理,還需進行附加的單峰檢測,並進行插值處理,由於過於復雜且實現也相當困難。

split_2
而本文采用具有自適應性的OTSU局部閾值法來分割圖像,並對OTSU和局部閾值法進行了改進,不僅提高了性能而且改善了分割效果,對於亮度不均勻的圖像也能實現較好的分割。
最大類間方差法(OTSU)
由Otsu於1978年提出的最大類間方差法以其計算簡單、穩定有效,一直廣為使用。其主要思想就是選取閾值使其類內方差最小化或類間方差最大化。Otsu算法不僅計算簡單,而且能夠應用於多閾值確定,因此可以說是一種相當好的閾值選取方法。
我們通常采用最大化類間方差,來實現閾值分割,其類間方差定義為:

otsu_1
其中
|| u || 圖像中總的灰度均值 ||
|| u1 || 圖像中小於閾值T的像素灰度均值 ||
|| u2 || 圖像中大於閾值T的像素灰度均值 ||
|| n1 || 圖像中小於閾值T的像素數 ||
|| n2 || 圖像中大於閾值T的像素數 ||
因此,只需通過遍歷256個灰度級,尋找使其類間方差最大的那個灰度值就是最佳閾值T。
OTSU的實現與改進
然而如果每次遍歷都需要重新計算閾值兩邊的均值與像素數的話計算量是相當大的,如果能夠在下次遍歷時利用上次計算的結果,那么計算量可以大大減少。
假設灰度直方圖為,圖像總均值為,圖像總像素數為,那么其遞推方式如下:

otsu_2
為了進一步簡化計算,我們可以通過用

otsu_3
來替換,得到

otsu_4
由於n在遞歸中不變可以省略,因此可以改為

otsu_5
由於本文是針對字符圖像的分割,由於字符的筆畫通常較細,通常只占圖像的1/4都不到,因此可以適當的調整閾值,以實現較好的分割效果,改進后的閾值為

otsu_6
局部閾值的實現與改進
然而在實際圖像中, 由於噪聲或其他干擾等因素的影響,OTSU閾值分割並不能使圖像分割得到滿意的結果, 往往會產生嚴重的分割錯誤。這是因為圖像的灰度直方圖分布不一定
出現明顯的峰和谷, 像素灰度值僅僅反映了像素灰度級的幅值大小, 並沒有反映出像素與鄰域的空間相關信息。
通過具體的實驗發現:
當圖像亮度分布不均勻時,往往無法得到好的分割效果,通常會出現大塊的黑塊,或者過渡分割而丟失信息的情況。
因此,可以通過對圖像進行分塊,針對每一小塊進行OTSU分割,可以減少這些情況的發生,但是這又會出現不希望的“棋盤”效果,為了避免這種情況的發生,可以采用如下改進的局部閾值算法:
遍歷圖像中每一像素,在該像素的鄰域內進行灰度統計,計算OTSU閾值,並僅對該點進行閾值分割。
這樣就能在較好的分割效果下實現像素平滑過渡,避免了“棋盤”效應,由於在當像素移動時,只有一行或一列改變,所以可以在每步移動中,以新數據更新前一個位置得到的直方圖,從而避免了每次重新計算整個直方圖,大大減少了計算量,使其在一個可接受的范圍內。
為了防止部分區域受到噪聲干擾而產生的黑塊現象,可以在進行局部閾值處理前,進行三階的平滑處理,效果相當顯著。
結果
原圖

split_3
經全局閾值處理后的圖象

split_4
經改進的局部閾值處理后的圖像

split_5
總結
由上圖可見,經改進的局部閾值處理后的圖像的效果還是相當明顯的,可是還是有些不足之處。。
就是處理后的圖像筆畫較粗,容易填掉數字中的空洞,尤其是4,6,8,9這些含有小孔的數字,這些都有待進一步改進。
后續,我還會總結下:傾斜矯正、數字提取、特征提取、神經網絡相關的一些心得和改進算法。。
最后,再貼兩張hnr項目,界面截圖哈。。

before

after
個人主頁: TBOOX開源工程
原文出處: http://www.tboox.org/cn/2016/07/28/hnr-split-image/