Read a text character recognition CRNN + CTC

Original:  https://zhuanlan.zhihu.com/p/43534801   Recommended

Image character recognition is also a common problem areas. However, the natural scene image, the text must first locate the position of the image, and then to be identified.

So, in general, from character recognition in natural scene image, comprising requires two steps:

  • Text detection: Solving the problem is where there is text, the text number range
  • Character recognition: good positioning for text areas are identified, the main problem is what each character is the character area in the image is converted into character information.

https://pic3.zhimg.com/80/v2-6e4468f2ae0101809d4bc681b979fdc2_hd.jpgA character recognition step of FIG.

For readers do not understand the text detection, refer to this column:

-CTPN scene text detection principle and implementation zhuanlan.zhihu.com

This article focuses on how the text area already positioned picture identification.

Directly after classification of simple character recognition based on a single character positioning + classification, i.e., a single character area positioned.

https://pic4.zhimg.com/80/v2-b60d3033a91fc9476da6d9eb62837f37_hd.jpgFIG 2 positioned character image text detection region

There are two main framework RNN ​​character recognition algorithm based on:

 

https://pic2.zhimg.com/80/v2-43adade51e86ba6bf9719597080cf1b5_hd.jpgFIG 3 recognizes two basic algorithm framework based text RNN

  1. CNN + RNN + LBC (LBC CRNN +)
  2. CNN+Seq2Seq+Attention

This paper describes a first frame CRNN + CTC, corresponding to the code (Tensorflow implemented) as follows, CRNN network structure described herein are based on this code. In addition to the identification code has been supported uncertain English.

Bai-Shang / crnn_ctc_ocr_tf github.com

CRNN basic network structure

https://pic3.zhimg.com/80/v2-7ed5c65fe79dce49f006a9171cc1a80e_hd.jpgFIG 4 CRNN network structure (according to the figure given herein implementation code github painting)

CRNN entire network can be divided into three parts:

It is assumed that the input image size  , the image is referred to note   form.

  • Convlutional Layers

这里的卷积层就是一个普通的CNN网络,用于提取输入图像的Convolutional feature maps,即将大小为   的图像转换为   大小的卷积特征矩阵,网络细节请参考本文给出的实现代码。

  • Recurrent Layers

这里的循环网络层是一个深层双向LSTM网络,在卷积特征的基础上继续提取文字序列特征。对RNN不了解的读者,建议参考:

完全解析RNN, Seq2Seq, Attention注意力机制zhuanlan.zhihu.com

所谓深层RNN网络,是指超过两层的RNN网络。对于单层双向RNN网络,结构如下:

https://pic4.zhimg.com/80/v2-9f5125e0c99924d2febf25bafd019d6f_hd.jpg图5 单层双向RNN网络

而对于深层双向RNN网络,主要有2种不同的实现:

tf.nn.bidirectional_dynamic_rnn

https://pic3.zhimg.com/80/v2-c0132f0b748eb031c696dae3019a2d82_hd.jpg图6 深层双向RNN网络

tf.contrib.rnn.stack_bidirectional_dynamic_rnn

https://pic2.zhimg.com/80/v2-00861a152263cff8b94525d8b8945ee9_hd.jpg图7 stack形深层双向RNN网络

在CRNN中显然使用了第二种stack形深层双向结构。

由于CNN输出的Feature map是 大小,所以对于RNN最大时间长度   (即有25个时间输入,每个输入   列向量有   )。

  • Transcription Layers

将RNN输出做softmax后,为字符输出。

关于代码中输入图片大小的解释:

在本文给出的实现中,为了将特征输入到Recurrent Layers,做如下处理:

  • 首先会将图像在固定长宽比的情况下缩放到   大小(   代表任意宽度)
  • 然后经过CNN后变为 
  • 针对LSTM设置   ,即可将特征输入LSTM。

所以在处理输入图像的时候,建议在保持长宽比的情况下将高缩放到  ,这样能够尽量不破坏图像中的文本细节(当然也可以将输入图像缩放到固定宽度,但是这样由于破坏文本的形状,肯定会造成性能下降)。

考虑训练Recurrent Layers时的一个问题:

https://pic2.zhimg.com/80/v2-5803de0cd9eb4e20f6a722e02b196809_hd.jpg图8 感受野与RNN标签的关系

对于Recurrent Layers,如果使用常见的Softmax cross-entropy loss,则每一列输出都需要对应一个字符元素。那么训练时候每张样本图片都需要标记出每个字符在图片中的位置,再通过CNN感受野对齐到Feature map的每一列获取该列输出对应的Label才能进行训练,如图9。

在实际情况中,标记这种对齐样本非常困难(除了标记字符,还要标记每个字符的位置),工作量非常大。另外,由于每张样本的字符数量不同,字体样式不同,字体大小不同,导致每列输出并不一定能与每个字符一一对应。

当然这种问题同样存在于语音识别领域。例如有人说话快,有人说话慢,那么如何进行语音帧对齐,是一直以来困扰语音识别的巨大难题。

https://pic3.zhimg.com/80/v2-11fcc223d3288932fd15a1d2a26f2c26_hd.jpg图9

所以CTC提出一种对不需要对齐的Loss计算方法,用于训练网络,被广泛应用于文本行识别和语音识别中。

Connectionist Temporal Classification(CTC)详解

在分析过程中尽量保持和原文符号一致。

Connectionist Temporal Classification: Labelling Unsegmented Sequence Data with Recurrent Neural Networksftp.idsia.ch

 

整个CRNN的流程如图11。先通过CNN提取文本图片的Feature map,然后将每一个channel作为   的时间序列输入到LSTM中。

https://pic2.zhimg.com/80/v2-6e2120edda0684a2a654d0627ad13591_hd.jpg图10 CRNN+CTC框架

为了说明问题,我们定义:

  • CNN Feature map

Feature map的每一列作为一个时间片输入到LSTM中。设Feature map大小为   (图11中     )。下文中的时间序列   都从   开始,即   

定义为:

 

其中   每一列   为:

 

  • LSTM

LSTM的每一个时间片后接softmax,输出   是一个后验概率矩阵,定义为:

 

其中,   的每一列   为:

 

其中   代表需要识别的字符集合长度。由于   是概率,所以服从概率假设:

对   每一列进行   操作,即可获得每一列输出字符的类别。

那么LSTM可以表示为:

 

其中   代表LSTM的参数。LSTM在输入和输出间做了如下变换:

 

https://pic1.zhimg.com/80/v2-7a20ee2f70e41a8662fe89fc8773ead0_hd.jpg图11

  • 空白blank符号

如果要进行   的26个英文字符识别,考虑到有的位置没有字符,定义插入blank的字符集合:

 

其中blank表示当前列对应的图像位置没有字符(下文以 符号表示blank)。

  • 关于  变换

定义变换   如下(原文是大写的   ,知乎没这个符号):

 

其中   是上述加入blank的长度为   的字符集合,经过   变换后得到原始   ,显然对于 的最大长度有   

举例说明,当   时:

     

对于字符间有blank符号的则不合并:

 

当获得LSTM输出 后进行 变换,即可获得输出结果。显然   变换不是单对单映射,例如对于不同的 都可获得英文单词state。同时   成立。

那么CTC怎么做?

对于LSTM给定输入   的情况下,输出为   的概率为:

 

其中   代表所有经过   变换后是   的路径   

其中,对于任意一条路径   有:

 

注意这里的   中的   ,下标   表示   路径的每一个时刻;而上面   的下标表示不同的路径。两个下标含义不同注意区分。

*注意上式   成立有条件,此项不做进一步讨论,有兴趣的读者请自行研究。

如对于   的路径   来说:

 

实际情况中一般手工设置   ,所以有非常多条   路径,即   非常大,无法逐条求和直接计算   。所以需要一种快速计算方法。

CTC的训练目标

https://pic3.zhimg.com/80/v2-aa0e26bbce5b7b45ce7b6c767b6584b2_hd.jpg图14

CTC的训练过程,本质上是通过梯度   调整LSTM的参数   ,使得对于输入样本为   时使得   取得最大。

例如下面图14的训练样本,目标都是使得   时的输出   变大。

https://pic2.zhimg.com/80/v2-faa81dec02bd2bb4b186808a3b7ac689_hd.jpg图14

CTC借用了HMM的“向前—向后”(forward-backward)算法来计算 

要计算   ,由于有blank的存在,定义路径   为在路径   每两个元素以及头尾插入blank。那么对于任意的   都有   (其中   )。如:

 

显然   ,其中   是路径的最大长度,如上述例子中   

定义所有经   变换后结果是   且在   时刻结果为  (记为  )的路径集合为   

求导:

 

注意上式中第二项与   无关,所以:

 

而上述   就是恰好与概率   相关的路径,即   时刻都经过   (  )

举例说明,还是看上面的例子   (这里的下标   代表不同的路径):

https://pic1.zhimg.com/80/v2-b35c7212d02f2c4847a6038a5ef9a200_hd.jpg图15

蓝色路径   

 

红色路径   

 

还有   没有画出来。

而   在   时恰好都经过   (此处下标代表路径   的   时刻的字符)。所有类似于   经过   变换后结果是   且在   的路径集合表示为   

观察   。记   蓝色为   ,   红色路径为   ,   可以表示:

 

那么   可以表示为:

 

计算:

 

为了观察规律,单独计算   

 

 

 

 

 

不妨令:

 

 

那么 可以表示为:

 

推广一下,所有经过   变换为   且   的路径(即   )可以写成如下形式:

 

进一步推广,所有经过   变换为   且   的路径(即   )也都可以写作:

 

所以,定义前向递推概率和   

对于一个长度为   的路径   ,其中   代表该路径前   个字符,   代表后   个字符。

 

其中   表示前   个字符   经过   变换为的   的前半段子路径。   代表了   时刻经过   的路径概率中   概率之和,即前向递推概率和。

由于当   时路径只能从blank或   开始,所以   有如下性质:

   

如上面的例子中   ,   ,   。对于所有   路径,当   时只能从blank和   字符开始。

https://pic2.zhimg.com/80/v2-2371b50895b935ecb8f3925a0462e5e5_hd.jpg图16

图16是   时经过压缩路径后能够变为   的所有路径   。观察图15会发现对于   有如下递推关系:

 

也就是说,如果   时刻是字符   ,那么   时刻只可能是字符   三选一,否则经过   变换后无法压缩成   

那么更一般的:

 

同理,定义反向递推概率和   

 

其中   表示后   个字符   经过   变换为的   的后半段子路径。   代表了   时刻经过   的路径概率中   概率之和,即反向递推概率和。

由于当   时路径只能以blank或   结束,所以有如下性质:

   

如上面的例子中   ,   ,   ,   。对于所有   路径,当   时只能以   (blank字符)或   字符结束。

观察图15会发现对于   有如下递推关系

 

与   同理,对于   有如下递推关系:

 

那么forward和backward相乘有:

 

或:

 

注意,   可以通过图16的关系对应,如   

对比   :

 

可以得到   与forward和backward递推公式之间的关系:

 

 

* 为什么有上式   成立呢?

回到图15,为了方便分析,假设只有   共4条在   时刻经过字符   且   变换为   的路径,即 :

 

那么此时(注意虽然表示路径用   加法,但是由于   和   两件独立事情同时发生,所以   路径的概率   是乘法):

 

则有:

https://pic2.zhimg.com/80/v2-ef2eaf1c36fe5af6a0e0e1a0f4cc4955_hd.jpg

训练CTC

对于LSTM,有训练集合   ,其中   是图片经过CNN计算获得的Feature map,   是图片对应的OCR字符label(label里面没有blank字符)。

现在我们要做的事情就是:通过梯度 调整LSTM的参数 ,使得对于输入样本为 时有   取得最大。所以如何计算梯度才是核心。

单独来看CTC输入(即LSTM输出)   矩阵中的某一个值   (注意   与   含义相同,都是在   时   的概率):

 

上式中的   是与   无关的数值,任何时候都可以通过递推快速计算,那么即可快速计算梯度   ,之后梯度上升算法你懂的。

CTC编程接口

在Tensorflow中官方实现了CTC接口:

tf.nn.ctc_loss(

    labels,

    inputs,

    sequence_length,

    preprocess_collapse_repeated=False,

    ctc_merge_repeated=True,

    ignore_longer_outputs_than_inputs=False,

    time_major=True

)

在Pytorch中需要使用针对框架编译的warp-ctc:https://github.com/SeanNaren/warp-ctc

CTC总结

CTC是一种Loss计算方法,用CTC代替Softmax Loss,训练样本无需对齐。CTC特点:

  • 引入blank字符,解决有些位置没有字符的问题
  • 通过递推,快速计算梯度

看到这里你也应该大致了解MFCC+CTC在语音识别中的应用了(图17来源)。

https://pic4.zhimg.com/80/v2-31abfbb4be0cc6995367ea956488c20b_hd.jpg图17 MFCC+CTC在语音识别中的应用

CRNN+CTC总结

这篇文章的核心,就是将CNN/LSTM/CTC三种方法结合:

  • 首先CNN提取图像卷积特征
  • 然后LSTM进一步提取图像卷积特征中的序列特征
  • 最后引入CTC解决训练时字符无法对齐的问题

即提供了一种end2end文字图片识别算法,也算是方向的简单入门。

特别说明

一般情况下对一张图像中的文字进行识别需要以下步骤

  1. 定位文稿中的图片,表格,文字区域,区分文字段落(版面分析)
  2. 进行文本行识别(识别)
  3. 使用NLP相关算法对文字识别结果进行矫正(后处理)

本文介绍的CRNN框架只是步骤2的一种识别算法,其他非本文内容。CTC你学会(fei)了么?

 

Published 62 original articles · won praise 235 · Views 1.69 million +

Guess you like

Origin blog.csdn.net/javastart/article/details/104061167