一次完整的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地址。记录下这个更多是方便自己以后查阅。
一次完整的OCR实践记录的更多相关文章
- 9-2、大型项目的接口自动化实践记录----递归判断两个json串是否相等
1.已知json串构成的情况下判断 先构造一下场景,假设已经把各个数据都移除掉不对比的字段 图1 预期.实际结果,复杂接口返回多层嵌套json时,同下 图2 预期.实际结果值为:{child_json ...
- 9-1、大型项目的接口自动化实践记录----数据库结果、JSON对比
上一篇写了如何从DB获取预期.实际结果,这一篇分别对不同情况说下怎么进行对比. PS:这部分在JSON对比中也适用. 1.结果只有一张表,只有一条数据 数据格式:因为返回的是dicts_list的格式 ...
- 【转】android 最新 NDK r8 在window下开发环境搭建 安装配置与使用 详细图文讲解,完整实际配置过程记录(原创)
原文网址:http://www.cnblogs.com/zdz8207/archive/2012/11/27/android-ndk-install.html android 最新 NDK r8 在w ...
- Spring Boot 2 实践记录之 封装依赖及尽可能不创建静态方法以避免在 Service 和 Controller 的单元测试中使用 Powermock
在前面的文章中(Spring Boot 2 实践记录之 Powermock 和 SpringBootTest)提到了使用 Powermock 结合 SpringBootTest.WebMvcTest ...
- Spring Boot 2 实践记录之 使用 ConfigurationProperties 注解将配置属性匹配至配置类的属性
在 Spring Boot 2 实践记录之 条件装配 一文中,曾经使用 Condition 类的 ConditionContext 参数获取了配置文件中的配置属性.但那是因为 Spring 提供了将上 ...
- Spring Boot 2 实践记录之 MyBatis 集成的启动时警告信息问题
按笔者 Spring Boot 2 实践记录之 MySQL + MyBatis 配置 中的方式,如果想正确运行,需要在 Mapper 类上添加 @Mapper 注解. 但是加入此注解之后,启动时会出现 ...
- android 最新 NDK r8 在window下开发环境搭建 安装配置与使用 详细图文讲解,完整实际配置过程记录(原创)
android 最新 NDK r8 在window下开发环境搭建 安装配置与使用 详细图文讲解,完整实际配置过程记录(原创) 一直想搞NDK开发却一直给其他事情耽搁了,参考了些网上的资料今天终于把 ...
- Ionic3项目实践记录
Ionic3首次项目实践记录 标签(空格分隔): Angular Ionic Ionic3踩坑 1. 路由懒加载(lazy load) 如果设置了懒加载,就必须全部懒加载(包括TabsPage),否则 ...
- k8s1.4.3安装实践记录(2)-k8s安装
前面一篇已经安装好了ETCD.docker与flannel(k8s1.4.3安装实践记录(1)),现在可以开始安装k8s了 1.K8S 目前centos yum上的kubernetes还是1.2.0, ...
随机推荐
- MFC_对话框_访问控件_7种方法_A
访问对话框控件的七种方法 方法一. GetDlgItem()->GetWindowText(); GetDlgItem()->SetWindowText(); 方法二. GetDlgIte ...
- 第二阶段:1.流程图:9.excel绘制甘特图
后面的框都是日期 可以以一个月为周期计算或者周或者... 因为产品经理应该严格把控产品的时间 因此甘特图特别有必要 注意:任务拆解的越细 把控度越强 然后对格式进行设置 注意时间下面可以用颜色填充来表 ...
- 王雅超的学习笔记-大数据hadoop集群部署(七)
MySQL的安装部署
- $vjudge-$搜索专题题解
退役了,刷点儿无脑水题$bushi$放松下$QwQ$ 然后先放个链接,,,$QwQ$ $A$ 虽然是英文但并不难$get$题目大意?就说给定一个数独要求解出来,$over$ 昂显然直接$dfs$加剪枝 ...
- JVM探秘:内存溢出
本系列笔记主要基于<深入理解Java虚拟机:JVM高级特性与最佳实践 第2版>,是这本书的读书笔记. 在 Java 虚拟机内存区域中,除了程序计数器外,其他几个内存区域都可能会发生OutO ...
- 用TensorFlow做图像识别(python)
一.TensorFlow简介 TensorFlow是由谷歌开发的一套机器学习的工具,使用方法很简单,只需要输入训练数据位置,设定参数和优化方法等,TensorFlow就可以将优化结果显示出来,节省了很 ...
- 微信公众号 唤醒手机导航APP 一看就懂 复制即用
公司自研发框架,基本上没啥看不懂的 基本都是直接复制用就好了!希望能帮助到需要的朋友! 新建俩个同级文件用来保存 jsapi_ticket 和 access_token的文件 命名:jsapi_tic ...
- Java防锁屏小程序
为防止系统桌面自动锁屏,只需打成jar包,写个批处理程序start.bat,双击执行保持dos窗口执行即可,无其他影响. 程序设计为每30秒动一次鼠标,可根据需要调整. 附代码: package ma ...
- Linux Cgroup浅析
cgroup从2.6.4引入linux内核主线,目前默认已启用该特性.在cgroup出现之前,只能对一个进程做资源限制,比如通过sched_setaffinity设置进程cpu亲和性,使用ulimit ...
- EFCore Database-first深入研究
EFCore Database-first深入研究 使用Scaffold-DbContext从数据库生成实体 说明文档: 关于 Scaffold-DbContext 微软有官方说明文档 https:/ ...