一次完整的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地址。记录下这个更可能是方便本身之后查阅。

相关文章
相关标签/搜索