自然场景文字是图像高层语义的一种重要载体,近些年自然场景图像中的文本检测与识别技术越来越引起人们的重视。特别是近年来ICDAR的历界比赛,更是逐渐将这一领域的score不断提升。如http://rrc.cvc.uab.es/?ch=4&com=evaluation&task=1>v=1这个主页上看到列出的result结果,都有达到90%多的。此外,一些大公司的AI都提供了这样的接口,如百度AI的SDK上已经有这一块,看起来非常猛的样子。
自然场景文本检测是图像处理的核心模块,也是一直想要接触的一个方面。刚好看到国内的旷视今年在CVPR2017的一篇文章:EAST: An Efficient and Accurate Scene Text Detector。而且有开放的代码,学习和测试了下。
题目说的是比较高效,它的高效主要体现在对一些过程的消除,其架构就是下图中对应的E部分,跟上面的比起来的确少了比较多的过程。这与去年经典的CTPN架构类似。不过CTPN只支持水平方向,而EAST在论文中指出是可以支持多方向文本的定位的。
论文采用的架构如下:
这个架构的细节应该包括几个部分:
(1) The algorithm follows the general design ofDenseBox [9], in which an image is fed into the FCN andmultiple channels of pixel-level text score map and geometryare generated. 从论文中这句话可以看出,参考了DenseBox的架构,采用FCN网络,同时在多个通道中进行特征层的输出与几何的生成。
(2) 文中采用了两种几何对象,rotated box (RBOX) and quadrangle (QUAD),通过这两种,可以实现对多方向场景文本的检测。
(3) 采用了Locality-Aware NMS来对生成的几何进行过滤,这也是代码中lanms(C++)代码的因素。
模型的实现源码如下:
def model(images, weight_decay=1e-5, is_training=True):
'''
define the model, we use slim's implemention of resnet
'''
images = mean_image_subtraction(images)
with slim.arg_scope(resnet_v1.resnet_arg_scope(weight_decay=weight_decay)):
logits, end_points = resnet_v1.resnet_v1_50(images, is_training=is_training, scope='resnet_v1_50')
with tf.variable_scope('feature_fusion', values=[end_points.values]):
batch_norm_params = {
'decay': 0.997,
'epsilon': 1e-5,
'scale': True,
'is_training': is_training
}
with slim.arg_scope([slim.conv2d],
activation_fn=tf.nn.relu,
normalizer_fn=slim.batch_norm,
normalizer_params=batch_norm_params,
weights_regularizer=slim.l2_regularizer(weight_decay)):
f = [end_points['pool5'], end_points['pool4'],
end_points['pool3'], end_points['pool2']]
for i in range(4):
print('Shape of f_{} {}'.format(i, f[i].shape))
g = [None, None, None, None]
h = [None, None, None, None]
num_outputs = [None, 128, 64, 32]
for i in range(4):
if i == 0:
h[i] = f[i]
else:
c1_1 = slim.conv2d(tf.concat([g[i-1], f[i]], axis=-1), num_outputs[i], 1)
h[i] = slim.conv2d(c1_1, num_outputs[i], 3)
if i <= 2:
g[i] = unpool(h[i])
else:
g[i] = slim.conv2d(h[i], num_outputs[i], 3)
print('Shape of h_{} {}, g_{} {}'.format(i, h[i].shape, i, g[i].shape))
# here we use a slightly different way for regression part,
# we first use a sigmoid to limit the regression range, and also
# this is do with the angle map
F_score = slim.conv2d(g[3], 1, 1, activation_fn=tf.nn.sigmoid, normalizer_fn=None)
# 4 channel of axis aligned bbox and 1 channel rotation angle
geo_map = slim.conv2d(g[3], 4, 1, activation_fn=tf.nn.sigmoid, normalizer_fn=None) * FLAGS.text_scale
angle_map = (slim.conv2d(g[3], 1, 1, activation_fn=tf.nn.sigmoid, normalizer_fn=None) - 0.5) * np.pi/2 # angle is between [-45, 45]
F_geometry = tf.concat([geo_map, angle_map], axis=-1)
return F_score, F_geometry
可以看出,几何图的生成过程。
实验部分:
由于该源码已经公布,进行了测试,效果如下:
(1) ICDAR相关的数据集测试,有相当部分的效果还是可以的,这也是文中所说能够达到80%的,也有一定的可信之处。
(2) 一些公开互联网的数据集:这个结果就有些可怜了,不过主要采用了文中提供的预训练数据集,可能训练数据集不包括这些吧。
可见,场景文本识别检测还有很长的一段路要走。不过最后一张图实在过于复杂,包括CTPN的效果也都是非常一般。利用百度识别SDK也测试了下,结果也是差不多。