OCR文字識別——手寫漢字識別(一)

2021-02-15 算法學習之心

一、引言

  OCR識別目前來說已經很成熟了,像百度、騰訊、訊飛等大佬都有自己的OCR識別技術,比如騰訊,可以登入騰訊AI開放平臺:https://ai.qq.com/product/ocr.shtml#handwrite

上傳一張圖片,它可以識別出圖片中的文字及其位置,其準確率還是不錯的。

OCR文字識別主要有兩種經典的方法:

1、字符分割+字符識別

  最開始人們想到的是先將一張圖片中的文本中的每個字分割出來,然後對每個字進行單獨識別,最後組合起來形成完整文本。

2、文本定位+文本識別

  隨著目標檢測算法的發展,漸漸出現了一種以「文本定位」+「文本識別」的不定長文本識別方法,利用目標檢測算法(如ssd、yolo)定位出每一行字,然後利用CRNN+CTC的方式進行不定長文本識別,直接識別出一行文字。這種方法目前應該是主流的ocr方法。

  這裡先講第一種方法,CRNN+CTC的方法下次再詳細討論,這裡不做介紹了。OCR文字識別主要分為對於「印刷體字符」和「手寫體字符」,其中「手寫體字符」更不容易識別,想想自己寫的字就知道了(連自己都認不出來)

  好了,下面讓我們開始吧~~~~~~~~~~~~

  主要流程如下:

二、準備工作

  在做OCR手寫漢字識別之前,需要準備手寫漢字數據集,目前免費公開的數據集有中科院的「CASIA-HWDB脫機手寫漢字數據集」以及北京郵電大學的「HCL2000漢字資料庫」,下載地址如下:

https://pan.baidu.com/s/1ZmQP8hx8DYiYG5i5dr0aGg 提取碼:rxm4 

  數據集很大,包含了國標一級漢字,一個有3755個漢字,由不同職業的人書寫的,有寫的工整的,也有潦草的,每個數據集包含100w+張手寫漢字圖片。

三、數據預處理

  下載下來的數據集是個壓縮包,這裡以HWDB1.1數據集為例,包含一個訓練數據集與一個測試數據集,分別解壓,得到多個xxx.gnt的文件,這裡需要用代碼讀取。

  用腳本解析完後可以得到3755個文件夾,每一個文件夾下包含240張手寫漢字圖片。


漢字個數

圖片總數

訓練集

3755

901200

測試集

3755

225300


四、網絡構建

  顯而易見,這是一個單標籤多分類問題,就按照分類問題解決即可,類別為3755類,其實可以採用VGG16、resnet等網絡,對其進行稍微修改,進行特徵提取,並將最後一層改成3755類,就可以直接訓練了。

  不過基於這裡的漢字圖片均為灰度圖,這裡採用一個更簡單的網絡,參考 https://arxiv.org/abs/1702.07975

這篇文章所講的進行實現。

  文中作者構建的網絡結構如下:

Input-96C3-MP3-128C3-MP3-160C3-MP3-256C3-256C3-MP3-384C3-384C3-MP3-1024FC-Output

註:96C3表示96個大小為3x3的卷積層;MP3表示大小為3x3的最大池化層;1024FC表示1024個全連接層。

    文中還提到了一種新Trick:

    一般卷積層中卷積核大小設置為(3x3)大小,那麼一個卷積核中需要優化的參數就有3x3=9個;如果將卷積核拆成(3x1)和(1x3)兩個卷積核呢?同樣是對原圖片(3x3)區域進行卷積,然而這樣的話所需要優化的參數就變成了1x3+3x1=6個,相比減少了3個(即減少了1/3),這樣不就在達到相同目的的同時降低了模型的複雜度,提高訓練與識別效率。

 介紹幾個其它trick:

1)加入BN層:BN層將卷積之後的結果進行歸一化避免卷積之後的數據過大或過小,影響收斂。BN層最初提出是加在卷積層與激活層之間的,但是現在也有許多研究者將其加在激活層之後,效果各有優劣。

2)激活函數:目前CNN中大部分情況下激活函數都是ReLU一族雄霸天下吧,默認都採用ReLU激活函數,不過可以嘗試其變種「ReLU6」或「PReLU(文中方案)」。

3)加入正則化:在機器學習中正則化一直都是防止過擬合的有效手段,常用的有L1和L2正則化,若在訓練過程中出現過擬合現象,試試在全連接層處加入L2正則化試試。

4)優化器:在反向傳播過程中更新參數的策略,由最初的SGD到後來的AdaGrad、RMSProp、Adam等,不能說哪一種最好,需要依據不同問題而定,一般來說後面幾種算法在前期收斂效果要比SGD快,但是很多時候SGD+Momentum可能比其他算法在最後的精度上要好。

5)學習率:學習率的設定也是一個技巧,學習率太大會導致不收斂,太小又會使得收斂速度太慢或者很快收斂到較差的局部最優點。一般學習率策略採用遞減的方式:在初始期間設定較大的學習率(如0.1,可以讓算法快速在全局進行探索,尋找最優目標),然後隨著迭代慢慢減小學習率(後期減小學習率有利於在最優處進行精細探索,免得找到了最優位置一不小心又跳出去了)。

6)初始化權重:權重的初始化方法對於收斂也有很大影響,選擇的不好可能會發生梯度爆炸或梯度消失,導致結果很差。目前各種深度學習框架都提供了很多初始化方法,可以都採用對比。

7)數據增強:數據增強也是一種防止過擬合的有效方法,通過對圖像進行旋轉、偏移、裁剪等操作,提高了樣本的多樣性,使算法更加健壯。

8)Dropout:Dropout層也是防止過擬合的一種方法,它是通過抑制部分網絡節點(將其值置為0)來實現提高網絡健壯性,一般抑制概率設置為0.2-0.5左右,一般放在全連接層之後。

  採用Keras構建網絡如下:

from keras.models import Modelfrom keras.layers import Input, Dropout, Reshape, Activation, Flatten, Densefrom keras.layers.convolutional import Conv2D, MaxPooling2Dfrom keras.initializers import orthogonal, constant, he_normalfrom keras.regularizers import l2from keras import backend as Kfrom keras.layers.normalization import BatchNormalizationfrom keras.layers.advanced_activations import PReLUimport configdef relu6(x):    """Relu 6    """    return K.relu(x, max_value=6.0)
def net(): inputs = Input(shape=(config.IMAGE_SIZE, config.IMAGE_SIZE, config.NUM_CHANNELS)) x = Conv2D(config.FILTER_NUM[0], (1, 3), padding='same', kernel_initializer=he_normal())(inputs) x = Conv2D(config.FILTER_NUM[0], (3, 1), padding='same', kernel_initializer=he_normal())(x) x = BatchNormalization()(x) x = PReLU()(x) x = MaxPooling2D(pool_size=(3, 3), strides=2, padding='same')(x)
x = Conv2D(config.FILTER_NUM[1], (1, 3), padding='same', kernel_initializer=he_normal())(x) x = Conv2D(config.FILTER_NUM[1], (3, 1), padding='same', kernel_initializer=he_normal())(x) x = BatchNormalization()(x) x = PReLU()(x) x = MaxPooling2D(pool_size=(3, 3), strides=2, padding='same')(x)
x = Conv2D(config.FILTER_NUM[2], (1, 3), padding='same', kernel_initializer=he_normal())(x) x = Conv2D(config.FILTER_NUM[2], (3, 1), padding='same', kernel_initializer=he_normal())(x) x = BatchNormalization()(x) x = PReLU()(x) x = MaxPooling2D(pool_size=(3, 3), strides=2, padding='same')(x)
x = Conv2D(config.FILTER_NUM[3], (1, 3), padding='same', kernel_initializer=he_normal())(x) x = Conv2D(config.FILTER_NUM[3], (3, 1), padding='same', kernel_initializer=he_normal())(x) x = BatchNormalization()(x) x = PReLU()(x) x = Conv2D(config.FILTER_NUM[4], (1, 3), padding='same', kernel_initializer=he_normal())(x) x = Conv2D(config.FILTER_NUM[4], (3, 1), padding='same', kernel_initializer=he_normal())(x) x = BatchNormalization()(x) x = PReLU()(x) x = MaxPooling2D(pool_size=(3, 3), strides=2, padding='same')(x)
x = Conv2D(config.FILTER_NUM[5], (1, 3), padding='same', kernel_initializer=he_normal())(x) x = Conv2D(config.FILTER_NUM[5], (3, 1), padding='same', kernel_initializer=he_normal())(x) x = BatchNormalization()(x) x = PReLU()(x) x = Conv2D(config.FILTER_NUM[6], (1, 3), padding='same', kernel_initializer=he_normal())(x) x = Conv2D(config.FILTER_NUM[6], (3, 1), padding='same', kernel_initializer=he_normal())(x) x = BatchNormalization()(x) x = PReLU()(x) x = MaxPooling2D(pool_size=(3, 3), strides=2, padding='same')(x)
x = Flatten()(x) x = Dense(config.FILTER_NUM[7], kernel_regularizer=l2(0.005), kernel_initializer=he_normal())(x) x = BatchNormalization()(x) x = PReLU()(x) x = Dropout(0.5)(x)
y = Dense(config.NUM_LABELS, activation='softmax', kernel_initializer=he_normal())(x) model = Model(inputs=inputs, outputs=y) return model

五、訓練

  模型定義完成,就可以進行訓練了,數據讀取還是採用迭代的方式,用多少讀多少,不然一下子全部讀進內存內存不夠,有近100w張圖片。

  優化器這裡採用SGD+Momentum的方式,初始學習率設為0.1,然後隨著迭代慢慢衰減,如下圖所示:

def step_decay(epoch):    initial_lrate = 0.1    initial_lrate = initial_lrate * 0.1**(epoch//10)    if initial_lrate < 1.0e-5:        initial_lrate = 1.0e-5    return initial_lrate
def main(): #----參數設置---- train_size = np.loadtxt(config.TRAIN_FILE, dtype=str).shape[0] val_size = np.loadtxt(config.TEST_FILE, dtype=str).shape[0]
model = net()
# 設置變化的學習率 # learning_rate_reduction = ReduceLROnPlateau(monitor='val_acc', patience=3, verbose=1, factor=0.5, min_lr=0.00001) learning_rate_reduction = LearningRateScheduler(step_decay) learning_rate = 0.1 model.compile(loss='categorical_crossentropy', # optimizer=Adam(lr=1e-4), optimizer=SGD(lr=learning_rate, decay=0, momentum=0.9, nesterov=True), metrics=['accuracy']) # plot_model(model, to_file='model.png', show_shapes=True) model.summary() # 生成圖片讀取迭代器,用多少讀多少,不用一次性全部把圖片讀進內存,這樣可以節省內存。 train = generator(config.TRAIN_FILE, config.BATCH_SIZE, config.IMAGE_SIZE, config.IMAGE_SIZE, True) val = generator(config.TEST_FILE, config.BATCH_SIZE, config.IMAGE_SIZE, config.IMAGE_SIZE, False)
if not os.path.exists('./results/'): os.mkdir('./results') if not os.path.exists('./weights/'): os.mkdir('./weights') # 每一輪保存歷史最好模型,以驗證集準確率為依據 save_file = './weights/best_weights.h5' checkpoint = ModelCheckpoint(save_file, monitor='val_acc', save_best_only=True, save_weights_only=True, verbose=1) history = model.fit_generator(train, steps_per_epoch=train_size // config.BATCH_SIZE, validation_data=val, validation_steps=val_size // config.BATCH_SIZE, epochs=config.EPOCHS, callbacks=[checkpoint, learning_rate_reduction] )

  訓練過程很漫長,而且對於學習率與優化器的設置很重要,最初採用Adam,學習率設為0.001效果很差,一直沒收斂。

六、測試

  訓練時間太長了,這裡我只取訓練中途的模型進行測試(準確率為93.7%)

測試一:

    首先需要進行字符分割(這裡不細講,到時候單獨寫一篇關於分割的文章,分割其實是整個模塊中最難的...),將文字分割成如下:

    識別結果如下:

    只有一個字識別錯了:「嬋」 錯誤識別為 「嬸」(字體結構太相似)

測試二:

    如果拿來識別印刷字又如何呢?我們試試看:

    識別結果如下:

可見,對於印刷體漢字也是可以準確識別的。

七、總結

  總的來說,對於單個字的識別還是很簡單的,無論是印刷還是手寫,漢字、數字還是英文都可以用這種方法,難點是在於分割,如何提高字符分割的準確性是提高整體識別準確率的關鍵,尤其是手寫字符,分割起來尤為困難,正因為如此,這種方法漸漸被淘汰,被CRNN+CTC這類的「文字定位+不定長文本識別」所代替,對於文字定位目前的方法也很多,yolo,ssd之類的都很有名,這部分下次再細講。

  

相關焦點

  • 文字識別(OCR)
    並且出現了許多相關的識別系統,如:紫光文通推出的名片識別系統(e一card)、身份證識別系統(e驗通)和「慧視」屏幕文字圖像識別系統等等。這些新的識別系統的出現,標誌著印刷體漢字識別技術的應用領域得到了廣闊的擴展。國家高技術研究發展「863」計劃、國家重點科技攻關計劃、國家自然科學基金和軍事基礎研究基金都對印刷體漢字識別這一研究課題予以極大的重視和大力的支持。
  • TensorFlow 2.0 中文手寫字識別(漢字OCR)
    不如來嘗試一下類別多大3000+的漢字手寫識別吧!!雖然以前有一些文章教大家如何操作,但是大多比較古老,這篇文章將用全新的TensorFlow 2.0 來教大家如何搭建一個中文OCR系統!讓我們來看一下,相比於簡單minist識別,漢字識別具有哪些難點:搜索空間空前巨大,我們使用的數據集1.0版本漢字就多大3755個,如果加上1.1版本一起,總共漢字可以分為多達7599+個類別!這比10個阿拉伯字母識別難度大很多!
  • 在線ocr圖片文字識別工具,將圖片識別成文字的方法
    如果不是今天真遇上一個朋友這麼操作,北北還真不敢相信,原來時到今日,還有人會用最原始最簡單粗暴的方式來提取圖片中的文字信息,沒錯,這裡所說的原始粗暴方式,就是手動碼字!實際上,想要提取圖片中的文字信息,最好的方法便是使用在線ocr圖片文字識別,至於怎麼用,具體要怎麼操作,下面,北北就來詳細的為大家分享一下操作的流程吧!
  • 【文字識別軟體】免費OCR文字識別軟體
    按下快捷鍵,滑鼠拉好選框後,會在選框右下彈出功能區,可以識別圖片、文字、表格、公式。還有很多功能,可以自行探索。/API+騰訊翻譯/API+百度翻譯/API+有道翻譯/API+谷歌翻譯+詞霸翻譯+必應翻譯+滬江翻譯+奇虎翻譯+海詞翻譯+小牛翻譯+彩雲翻譯+福昕翻譯+歐米翻譯+微軟翻譯+阿里翻譯+雲譯翻譯+歐路翻譯+靈雲翻譯+Deepl翻譯API+PaPaGo翻譯;2、天若OCR(部分免費、輕量、簡便、需聯網、vip表格識別)官網連結:https://ocr.tianruo.net
  • ocr識別文字的方法,有什麼文字識別軟體推薦?
    ocr識別文字的方法有什麼?朋友小葵可以說是一枚文藝女青年了,平時就愛看看書、旅旅遊,還有彈彈吉他。對了,有時候她還會做下兼職投稿,給雜誌社寫寫文章。此外,小葵還有個興趣愛好是摘抄、記錄入心字句,做寫作素材。
  • OCR識別軟體可以識別手寫的文字稿件嗎?
    現在科技發達,市場上關於OCR識別的軟體特別多,但也意味著質量良莠不齊,所以找到一款實用的OCR文字識別軟體不容易。經過一小段時間的調查和使用,小亮找到了一款比較受歡迎的迅捷文字識別APP軟體,下面是相關的圖文教程。
  • 圖片文字識別軟體 – 在線圖片文字識別
    圖片文字識別軟體 – 在線圖片文字識別圖片文字識別軟體 – 在線圖片文字識別。
  • OCR(字符識別)軟體
    ● 3.3 貓圖鷹(安卓 / IOS)白描和貓圖鷹對拍攝清晰的印刷體識別率基本上能達到準確率100%對手寫字的識別上,白描和貓圖鷹都很強,識別率很高了。測試了很多小程序,只有這一款能把左邊這段文字完美一字不差(符號也不差)的識別出來。
  • OCR識別服務,盤它
    而目前PaddleHub為大家提供的是超輕量級中文OCR模型,聚焦特定的場景,支持中英文數字組合式識別、豎排文字識別、長文本識別場景。1.2、OCR的技術路線OCR,即學字符識別(Optical Character Recognition),是指對文本資料的圖像文件進行分析識別處理、獲取文字及版面信息的過程。
  • 輕鬆識別文字,這款Python OCR庫支持超過80種語言
    有一款軟體叫掃描全能王,想必一些小夥伴聽過,這是一個OCR集成軟體,可以將圖像內容掃描成文字。所以說,OCR作用是對文本資料的圖像文件進行分析識別處理,獲取文字及版面信息。細心觀察便可發現,身邊到處都是OCR的身影,文檔掃描、車牌識別、證件識別、銀行卡識別、票據識別等等。OCR本質是圖像識別,其包含兩大關鍵技術:文本檢測和文字識別。
  • 輕鬆識別文字,這款 Python OCR 庫支持超過 80 種語言
    有一款軟體叫掃描全能王,想必一些小夥伴聽過,這是一個OCR集成軟體,可以將圖像內容掃描成文字。所以說,OCR作用是對文本資料的圖像文件進行分析識別處理,獲取文字及版面信息。OCR本質是圖像識別,其包含兩大關鍵技術:文本檢測和文字識別。先將圖像中的特徵的提取並檢測目標區域,之後對目標區域的的字符進行分割和分類。
  • CRNN+CTCLoss中文手寫漢字識別
    而OCR則還停留在對列印字體的識別上。為什麼不能把手寫輸入法的算法用在OCR上呢。手寫識別和OCR是有一定區別的。1. 手寫識別通常包涵更多的信息(這裡指的是在線識別,我接觸到的高識別率手寫識別都是在線識別), 如筆畫順序, 連筆等。 這些細節看似簡單, 卻在無形之中給識別提供了不少的特徵, 有助於識別率的提升。2. 手寫識別的樣本預處理比較容易。
  • 離線版圖片文字識別ocr
    離線版圖片文字識別ocr,精準識別超過十萬種物體和場景,包含多項高精度的識圖能力並提供相應的API服務,充分滿足各類個人開發者和企業用戶的業務需求。圖片文字識別可應用到的場景有哪些?1、 內容及廣告推薦 對客戶瀏覽頁面中圖片進行分析,通過識別圖片中的信息,給客戶推薦相關內容,或是在頁面中展示相關廣告,提升廣告點擊量。
  • 2020年好用的OCR文字識別軟體推薦
    白描是一款移動端的OCR文字識別軟體,支持Android、iOS和微信小程序,它採用了高精度的文字識別技術,可以精確識別各種場景下的文字。而且因為白描使用了百度的文字識別技術,它在各種場景下都能準確識別,是一款非常好用的文字識別APP另外,對於偶爾需要識別電腦上文字的朋友,白描還提供了一個能在網頁上使用的方法,點擊右上角的更多按鈕,選擇WiFi傳輸識別,然後白描會給你一個網頁地址,就可以在電腦上使用白描了掃描全能王
  • ocr在線識別軟體推薦,什麼軟體可以在線識別文字?
    要使用圖片中的文字、要使用PDF文檔中的文字,雖然不能直接複製,卻也不必要去手打,沒錯,關於圖片文字識別,其實我們依靠專業的軟體就可以搞定。今天,北北要做的,便是為大家推薦推薦好用的ocr在線識別軟體,那麼什麼軟體可以在線識別文字呢?下面這兩款,便是北北最愛的!
  • 用Python寫了一個圖像文字識別OCR工具
    在之前的文章裡,我們多次嘗試用Python實現文本OCR識別!點擊藍字查看歷史文章👉OCR識別的花樣使用、5行Python實現驗證碼識別、3行Python代碼識別圖片文字。不過今天我們要搞一個升級版:直接寫一個圖像文字識別OCR工具!引言最近在技術交流群裡聊到一個關於圖像文字識別的需求,在工作、生活中常常會用到,比如票據、漫畫、掃描件、照片的文本提取。
  • 基本的圖像處理與 OCR 文字識別工具總結 (Python)
    圖像處理和文字識別對於非標準控制項的識別十分有效,同時也能做很多事情。
  • Halcon OCR識別
    2.目標區域分割(ROI)對預處理後的圖像進行ROI提取,分割出單個字符組成的區域3.字符識別,即模式識別技術4.結果處理將識別完的文字按特定的次序和規則組合輸出!上述4個步驟中,OCR的核心部分自然是第3步,即模式識別技術模式識別技術訓練分類器第一步:將分割好的字符區域加入訓練集,使用函數append_ocr_trainf(Character,Image::Class,TrainingFile:)參數解析:Character:字符區域Image
  • 在線OCR文字識別工具!
    小貼士:文末有提示  留言點歌網站名稱: PearOCR
  • 用Python進行圖文識別(OCR)
    OCR與Tesseract介紹  將圖片翻譯成文字一般被稱為光學文字識別(Optical Character Recognition,OCR)。可以實現OCR 的底層庫並不多,目前很多庫都是使用共同的幾個底層OCR 庫,或者是在上面進行定製。