文字检测与识别

在Sensetime工作快两个月了,工作内容主要是文字识别。总结一下现在主流的文字检测和识别方法。

文字检测主要有两个套路,一种是基于通用物体检测(detection)的方法,一种是基于图像分割(segmentation)的方法,这两种方法各有优劣,适用于不同的任务。

之前很多做文字识别方法是先做character-wise的detection,然后对每个字符做识别,这种方法很难把每个字符都检测地很准。现在state-of-art的方法都是检测出文字的大框再做识别。

基于检测的方法能很好地解决水平文字的检测问题,缺点是对于非水平的文字不能检测。具体的做法可以参考Detecting Text in Natural Image with Connectionist Text Proposal Network,ECCV16的一篇论文,网络结构为RPN,针对文字检测的特点做了一些修改,最重要的有两点,一是改变了判断正负样本的方法,不同于物体检测,文字检测中proposal如果只框住了一行文字中的几个文字其实也算正样本,而用IOU计算的话会被当成负样本,所以判断正负样本只需要计算proposal与ground truth高度的overlap就可以了。第二点是anchor的选取,既然我们判断正负样本的时候不考虑宽度,自然选anchor的时候也不用选择不同宽度的了,只需要固定宽度然后根据具体任务选择几个合适的高度就可以了。其他地方和RPN基本一样。

上面说的方法适用的前提是文字都是水平的,如果要检测倾斜的文字,现在主流的方法都是基于segmentation。segmentation最大的问题在于有多行文字相邻很近时怎么把他们正确的分开。ICDAR 2015 challenge 4就是这种任务,目前做的最好的是Baidu IDL,但他们的论文还没公开,第二是友商Face++,他们的方法具体可以看论文Scene Text Detection via Holistic, Multi-Channel Prediction,大概做法是这样,首先用CNN pixel-wise地预测图片中的文字区域,字符区域和方向,方向指文字区域中每个像素所属文字的整体方向,CNN结构类似Holistically-Nested Edge Detection,最后输出三个map。得到这三个map后进行后处理,后处理比较复杂,大概的步骤是把每个字符当做一个点,根据字符间的距离和它们的方向计算字符属于同一行文字的概率,把属于同一行文字概率较大的字符连起来,得到一个带权重的图,然后用最小生成树算法得到一个树,再在这个树上减掉n个边就能得到n+1个子图,每个图有一些字符,这些字符构成一个文字区域,剪边的策略具体见原文,这样再结合整体文字区域的map就能得到每行文字的区域了,这些后处理方法比较好地解决了多行文字相邻很近时难以区分的问题。

文字识别就用CNN+RNN做就可以了,华科的CRNN写的比较详细,论文名叫An End-to-End Trainable Neural Network for Image-based Sequence Recognition and Its Application to Scene Text Recognition。框架其实也很简单,输入是高度固定的图像,经过CNN后得到h*w*c的feature map,h和c是固定的,w和输入的宽度有关,因为RNN的输入可以不定长度,所以下面接w个RNN的unit,每个的输入为h*c的feature。输入的RNN每个unit的实际上是图片上一段宽度的feature,这个feature代表的文字和这段图片前后的内容都有关系,所以一般接双向的RNN,接多层RNN效果会更好,RNN后接一个FC层,输入为RNN的每个unit的feature,输出为它对应于每个文字的概率,最后再接CTC作为loss function,CTC可以看做一个解码器,根据每个unit对应每个文字的概率分布可以得到每个字符串的概率,而-log(P(ground truth))就是loss啦。预测的时候CTC作用就是算出概率最大的字符串作为预测结果,具体的计算方法可以参考Supervised Sequence Labelling with Recurrent Neural Networks一文。

lufo /
Published under (CC) BY-NC-SA tagged with cnn  cv  daily