700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > tensorflow LSTM + CTC实现端到端OCR

tensorflow LSTM + CTC实现端到端OCR

时间:2024-07-08 09:01:10

相关推荐

tensorflow LSTM + CTC实现端到端OCR

最近在做OCR相关的东西,关于OCR真的是有悠久了历史了,最开始用tesseract然而效果总是不理想,其中字符分割真的是个博大精深的问题,那么多年那么多算法,然而应用到实际总是有诸多问题。比如说非等间距字体的分割,汉字的分割,有光照阴影的图片的字体分割等等,针对特定的问题,特定的算法能有不错的效果,但也仅限于特定问题,很难有一些通用的结果。于是看了Xlvector的博客之后,发现可以端到端来实现OCR,他是基于mxnet的,于是我想把它转到tensorflow这个框架来,顺便还能熟悉一下这个框架。本文主要介绍实现思路,更加细节的实现方法见另一篇。

正文

生成数据

利用captcha来生成验证码,具体生成验证码的代码请见这里,共生成4-6位包含数字和英文大小写的训练图片128000张和测试图片400张。命名规则就是num_label.png,生成的图片如下图

关于生成数据,再多说一点,可以像Xlvector那样一边生成一边训练,这样样本是无穷的,效果更好。但是实际应用中有限样本的情况还是更多的。

载入数据

两种载入数据方式

pipeline

最开始想通过一个tf.train.string_input_producer来读入所有的文件名,然后以pipline的方式读入,但是由于标签的是不定长的,想通过正则来生成label,一开始是想用py_func来实现,后来发现传入string会有问题,所以最后还是选择生成tf.record文件,关于不定长问题,把比较短的标签在后面补零(0是blank的便签,就是说自己的类别中不能出现0这个类),然后读出每个batch后,再把0去掉。

一次性载入

我这里给一个目录,然后遍历里面所有的文件,等到训练的时候,每一个epoch循环把文件的index给手动shuffle一下,然后就可以每次截取出一个batch来用作输入了

需要注意的是tensorflow lstm输入格式的问题,其label tensor应该是稀疏矩阵,所以读取图片和label之后,还要进行一些处理,具体可以看代码

关于载入图片,发现12.8w张图一次读进内存,内存也就涨了5G,如果训练数据加大,还是加一个pipeline来读比较好。

网络结构

然后是网络结构

这里我参考了stackoverflow的一篇帖子写的,根据tensorflow 1.0.1的版本做了微调,使用了Adam作为optimizer。

需要注意的是ctc_beam_search_decoder是非常耗时的,见下图

和greedy_decoder的区别是,greedy_decoder根据当前序列预测下一个字符,并且取概率最高的作为结果,再此基础上再进行下一次预测。而beam_search_decoder每次会保存取k个概率最高的结果,以此为基础再进行预测,并将下一个字符出现的概率与当前k个出现的概率相乘,这样就可以减缓贪心造成的丢失好解的情况,当k=1的时候,二者就一样了。

结果

—update—

稍微调一调,网络可以跑到85%以上。

把网络用在识别身份证号,试了73张网上爬的(不同分辨率下的)真实图片,错了一张,准确率在98%左右(不过毕竟身份证号比较简单)

大概14个epoch后,准确率过了50%,现在跑到了73%的正确率。

最后,代码托管在Github上。

后记

百度出了一个warpCTC可以加速CTC的计算,试用了一下CPU的版本发现好像没什么速度的提升,不知道是不是姿势不对,回头再试试GPU的版本。

对于更加细节的实现方法(输入输出的构造,以及warpCTC和内置ctc_loss的异同)放在了另一篇博客。

warpCTC的GPU版本试过之后发现速度差不多,但是能极大的减少CPU的占用对于不同的优化器,数据,同样的参数是不能普适的。往往之前的参数可以收敛,换个optimizer,数据,网络就不能收敛了。这个时候要微调参数。对于不同的优化器之间区别,文末有一篇神文可以参考

如果有发现问题,请前辈们一定要不吝赐教,在下方留言指出,或者在github上提出issue

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。