一次完整的OCR實踐記錄

1、任務介紹

  此次的任務是對兩百餘張圖片裏面特定的編號進行識別,涉及保密的緣由,這裏就不能粘貼出具體的圖片了,下面粘貼出一張相似須要識別的圖片。python

   

  假如說個人數據源如上圖所示,那麼我須要作的工做就是將上面圖片裏面標紅的數字給識別出來。git

  我採用的算法是https://github.com/YCG09/chinese_ocr,這是基於Tensorflow和keras框架採用ctpn+densenet+CTC算法來完成對圖片指定內容的字符識別。github

2、 圖像標註

  既然要進行OCR識別,那麼必定要對已有的數據源進行圖像標註工做,這裏採用的工具是labelImg,相信你們若是有搞深度學習這塊的話必定對這個工具不會陌生。算法

   

  對圖像具體的標註流程,我這裏就不作說明了,網上有不少資料能夠查找。這裏須要做特別說明的是,對於ctpn的訓練,label的名字爲text,對於densenet的訓練來講的話,就須要把標註框裏面的內容看成label。app

  而後就是數據加強這塊,這裏須要記錄的有兩點,一就是原始的數據源比較少就必須作數據加強,否則作出來的效果確定不太行,二就是怎麼作數據加強,因爲這裏的數據比較簡單,須要識別的內容也是有規律可行的,那這裏就用不着採用比較複雜的數據加強,因此我作的數據加強就是對圖像隨機進行裁剪和傾斜,固然這裏裁剪的尺寸和傾斜的角度必定要控制好,否則就會影響圖片的質量。框架

import cv2
import numpy as np
import random
import os
from PIL import Image

# 數據加強的代碼

img_path = r"*****************"
save_path = r"****************"

# 隨機傾斜圖片
def rotate_ima(img_path,save_path):
    for file in os.listdir(img_path):
        img = cv2.imread(os.path.join(img_path,file),0)
        rows,cols = img.shape

        # cols-1 and rows-1 are the coordinate limits.
        # 每張圖片傾斜4張
        for i in range(4):
            a = random.randint(2,6)
            print(a)
            # 指定左右傾斜
            for j in range(2):
                a = -a
                M = cv2.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),a,1)
                dst = cv2.warpAffine(img,M,(cols,rows))

                #cv2.imshow('img',img)
                #cv2.imshow('dst',dst)
                cv2.imwrite(os.path.join(save_path,'rot_'+str(i)+'_'+str(j)+file),dst)
                #cv2.waitKey(0)
                cv2.destroyAllWindows()
    
    
# 隨機裁剪圖片
def cut_img(img_path,save_path):
    all_file=[]
    for file in os.listdir(img_path):
        all_file.append(file)
    file1=random.sample(all_file,2)
    for x in file1:
        im=Image.open(os.path.join(img_path,x))
        crop_all=[]
        for c in range(5):  # 對每張圖片隨機生成5張
            for i in range(4):
                a=random.randint(100,400)
                crop_all.append(a)
            region=im.crop((crop_all[0],crop_all[1],im.size[0]-crop_all[2],im.size[1]-crop_all[3]))
            region.save(os.path.join(save_path,'cut_'+str(c)+'_'+x))
            
#rotate_ima(img_path,save_path)
cut_img(img_path,save_path)

  而後我大概生成了3000張左右的圖片就開始進行數據標註了,標註了大概六七個小時才把這些數據標註給完成。dom

  有了這些標註數據事後,就能夠正式開始訓練了。工具

3、CTPN訓練

  關於CTPN訓練流程在https://github.com/YCG09/chinese_ocr/tree/master/ctpn的readme已經說的很清楚了。可是我這裏就列出我所踩的坑吧。學習

  最開始我直接把標註的數據製做成VOC2007數據集的格式丟進去訓練,而後訓練出來的效果並很差,後面我纔在周圍同事的提醒下有一個關鍵的步驟忘了作。測試

   

  由於CTPN是進行文字檢測並不一樣於普通的目標檢測,它的檢測原理是對單個的字符進行檢測而後拼接在一塊兒。

   

  由於咱們在進行數據標註的時候是對一整行文本進行拉框標註,可是若是要進行CTPN訓練的話就須要對這個框劃分紅不少個矩形小框,劃分的方法就是上面的split_label.py程序。

  可是要進行上面一步的前提就是須要更改標註文件,使用labelImg標註出來的文件是一個圖像對應一個xml文件,可是這裏須要更改爲一個圖像對應一個txt文件,txt裏面存放的是標註框的四個座標,共計八個點(注意座標點的順序)。以下所示

410,1554,1723,1554,1723,1736,410,1736

  而後在運行split_label.py,接着ToVoc.py,這裏面的代碼細節須要自行更改,這裏就不作說明了。

  而後就能夠正式開始訓練了,截圖以下:

   

  這裏粘貼出一個錯誤須要注意

   

  解決方案就是刪除cache文件夾

4、DenseNet+CTC訓練

  DenseNet+CTC訓練主要分爲兩個步驟,一是圖像處理,二是txt文件處理。

  圖像處理的話,在咱們拿到標註好的數據以後須要對原始圖像進行裁剪工做,就是根據標註的座標裁剪出具體的圖像,就拿上面的圖像來講,咱們須要的圖像以下所示。

   

  而後再對裁剪後的圖像進行resize工做,resize成(280,32),這樣的話圖像處理這一部分就算完成了。

  txt處理的話,這裏咱們須要對xml文件進行一系列處理來達到下面的效果。

   

  前面card_900.jpg表明圖像名稱,後面這一串字符表明須要識別的字符在下面這個文件裏面的位置索引

   

  注意這裏txt裏面存放的是全部圖像裏面待識別字符的編號,不是一個圖像對應一個txt。

  作到這一步事後,在把生成的txt劃分紅訓練集和測試集,就算成功製做出來訓練DenseNet的數據集了。

    

  而後就能夠開始訓練了,截圖以下:

   

5、總結

  此次這個小的OCR項目歷時大概十天左右,從數據標註再到訓練模型,裏面踩了不少坑,也作了不少次嘗試,也查閱了不少資料,也向周圍同事請教了不少次,總算功夫不負有心人,總算完成了此次項目。

  這個記錄只是記錄了大概的流程,不少代碼細節並不方便透露,更多詳情參閱上面給出的GitHub地址。記錄下這個更可能是方便本身之後查閱。

相關文章
相關標籤/搜索