一次完整的OCR實踐記錄


一、任務介紹

  這次的任務是對兩百余張圖片里面特定的編號進行識別,涉及保密的原因,這里就不能粘貼出具體的圖片了,下面粘貼出一張類似需要識別的圖片。

   

  假如說我的數據源如上圖所示,那么我需要做的工作就是將上面圖片里面標紅的數字給識別出來。

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

二、 圖像標注

  既然要進行OCR識別,那么一定要對已有的數據源進行圖像標注工作,這里采用的工具是labelImg,相信大家如果有搞深度學習這塊的話一定對這個工具不會陌生。

   

  對圖像具體的標注流程,我這里就不做說明了,網上有很多資料可以查找。這里需要作特別說明的是,對於ctpn的訓練,label的名字為text,對於densenet的訓練來說的話,就需要把標注框里面的內容當作label。

  然后就是數據增強這塊,這里需要記錄的有兩點,一就是原始的數據源比較少就必須做數據增強,不然做出來的效果肯定不太行,二就是怎么做數據增強,由於這里的數據比較簡單,需要識別的內容也是有規律可行的,那這里就用不着采用比較復雜的數據增強,所以我做的數據增強就是對圖像隨機進行裁剪和傾斜,當然這里裁剪的尺寸和傾斜的角度一定要控制好,不然就會影響圖片的質量。

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張左右的圖片就開始進行數據標注了,標注了大概六七個小時才把這些數據標注給完成。

  有了這些標注數據過后,就可以正式開始訓練了。

三、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文件夾

四、DenseNet+CTC訓練

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

  圖像處理的話,在我們拿到標注好的數據之后需要對原始圖像進行裁剪工作,就是根據標注的坐標裁剪出具體的圖像,就拿上面的圖像來說,我們需要的圖像如下所示。

   

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

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

   

  前面card_900.jpg代表圖像名稱,后面這一串字符代表需要識別的字符在下面這個文件里面的位置索引

   

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

  做到這一步過后,在把生成的txt划分成訓練集和測試集,就算成功制作出來訓練DenseNet的數據集了。

    

  然后就可以開始訓練了,截圖如下:

   

五、總結

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

  這個記錄只是記錄了大概的流程,很多代碼細節並不方便透露,更多詳情參閱上面給出的GitHub地址。記錄下這個更多是方便自己以后查閱。

 


免責聲明!

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



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