1. 前言
这篇文章本应放在第五个读,而我查阅资料后临时改变了顺序。因为之前的几篇是two-stage方法,如R-CNN系算法,其主要思路是先通过启发式方法(selective search)或者CNN网络(RPN)产生一系列稀疏的候选框,然后对这些候选框进行分类与回归;而SegLink,Textboxes/Textboxes++都是基于SSD,也就是one-stage方法,如Yolo和SSD,其主要思路是均匀地在图片的不同位置进行密集抽样,抽样时可以采用不同尺度和长宽比,然后利用CNN提取特征后直接进行分类与回归,整个过程只需要一步。因此对阅读顺序进行了调整,为保持思路了连贯性,把SegLink,Textboxes/Textboxes++放后面读。
言归正传,什么叫SegLink呢?因为本文提出了将文本分割成两个局部可检测的元素:Segment和Link。
Segment:带有方向的小文字块
Link:把小文字块用邻近连接给link成单词
Seglink提出了基于SSD的改进版网络结构(全卷积网络结构)同时预测不同尺度的segments和link,提出层内link、跨层link两种link,可以检测任意长度、任意方向的文本。
2. SSD网络结构
SSD全称Single Shot MultiBox Detector,Single代表是one-stage方法,multibox表示会有多个预测框。
2.1 不同算法基本框架图
对于Faster R-CNN,其先通过CNN得到候选框,然后再进行分类与回归,而Yolo与SSD可以一步到位完成检测。相比Yolo,SSD采用CNN来直接进行检测,而不是像Yolo那样在全连接层之后做检测。其实采用卷积直接做检测只是SSD相比Yolo的其中一个不同点,另外还有两个重要的改变,一是SSD提取了不同尺度的特征图来做检测,大尺度特征图(较靠前的特征图)可以用来检测小物体,而小尺度特征图(较靠后的特征图)用来检测大物体;二是SSD采用了不同尺度和长宽比的先验框(Prior boxes, Default boxes,在Faster R-CNN中叫做锚,Anchors)。Yolo算法缺点是难以检测小目标,而且定位不准,但是这几点重要改进使得SSD在一定程度上克服这些缺点。
2.2 SSD的三个核心设计理念
2.2.1 采用多尺度特征图用于检测
上图为不同尺度的特征图。SSD采用不同尺度的特征图,大的特征图(如上图的8x8)可划分更小尺度的检测单元,检测相对较小的目标,而小的特征图(如上图的4x4)检测的是相对较大的目标。
2.2.2 采用卷积进行检测
与Yolo最后采用全连接层不同,SSD直接采用卷积对不同的特征图来进行提取检测结果。对于形状为 m × n × p m\times n \times p m×n×p 的特征图,只需要采用 3 × 3 × p 3\times 3 \times p 3×3×p 这样比较小的卷积核得到检测值。
2.2.3 设置先验框
在Yolo中,每个单元预测多个边界框,但是其都是相对这个单元本身(正方块),但是真实目标的形状是多变的,Yolo需要在训练过程中自适应目标的形状。而SSD借鉴了Faster R-CNN中anchor的理念,每个单元设置尺度或者长宽比不同的先验框,预测的边界框(bounding boxes)是以这些先验框为基准的,在一定程度上减少训练难度。一般情况下,每个单元会设置多个先验框,其尺度和长宽比存在差异,如下图所示,可以看到每个单元使用了4个不同的先验框,图片中猫和狗分别采用最适合它们形状的先验框来进行训练。
2.3 SSD网络结构
上图中上面的是SSD,下面的是YOLO。对比可得,SSD利用了多尺度的特征图做检测。
SSD采用VGG16作为基础模型,然后在VGG16的基础上新增了卷积层来获得更多的特征图以用于检测。分别将VGG16的全连接层fc6和fc7转换成
3
×
3
3\times3
3×3 卷积层 conv6和
1
×
1
1\times1
1×1 卷积层conv7,同时将池化层pool5由原来的stride=2的
2
×
2
2\times 2
2×2 变成stride=1的
3
×
3
3\times 3
3×3,为了配合这种变化,采用了一种Atrous Algorithm,其实就是conv6采用扩展卷积或带孔卷积(Dilation Conv),其在不增加参数与模型复杂度的条件下指数级扩大卷积的视野,其使用扩张率(dilation rate)参数,来表示扩张的大小,如下图所示,(a)是普通的
3
×
3
3\times3
3×3 卷积,其视野就是
3
×
3
3\times3
3×3 ,(b)是扩张率为1,此时视野变成
7
×
7
7\times7
7×7 ,( c ) 扩张率为3时,视野扩大为
15
×
15
15\times15
15×15 ,但是视野的特征更稀疏了。Conv6采用
3
×
3
3\times3
3×3 大小但dilation rate=6的扩展卷积。
然后移除dropout层和fc8层,并新增一系列卷积层,在检测数据集上做finetuing。
2.4 SSD训练过程
2.4.1 先验框匹配
在训练过程中,首先要确定训练图片中的ground truth(真实目标)与哪个先验框来进行匹配,与之匹配的先验框所对应的边界框将负责预测它。SSD的先验框与ground truth的匹配原则主要有两点:
- 对于图片中每个ground truth,找到与其IOU最大的先验框,该先验框与其匹配,这样,可以保证每个ground truth一定与某个先验框匹配。通常称与ground truth匹配的先验框为正样本,反之,若一个先验框没有与任何ground truth进行匹配,那么该先验框只能与背景匹配,就是负样本。
一个图片中ground truth是非常少的, 而先验框却很多,如果仅按第一个原则匹配,很多先验框会是负样本,正负样本极其不平衡,所以需要第二个原则。
- 对于剩余的未匹配先验框,若某个ground truth的IOU大于某个阈值(一般是0.5),那么该先验框也与这个ground truth进行匹配。
这意味着某个ground truth可能与多个先验框匹配,这是可以的。但是反过来却不可以,因为一个先验框只能匹配一个ground truth,如果多个ground truth与某个先验框IOU大于阈值,那么先验框只与IOU最大的那个先验框进行匹配。第二个原则一定在第一个原则之后进行。
上图是一个例子,绿色的是Ground Truth,红色的是先验框。TP(Truth Positive)正样本,FP(False Positive)是负样本。
尽管一个ground truth可以与多个先验框匹配,但是ground truth相对先验框还是太少了,所以负样本相对正样本会很多。为了保证正负样本尽量平衡,SSD采用了hard negative mining,就是对负样本进行抽样,抽样时按照置信度误差(预测背景的置信度越小,误差越大)进行降序排列,选取误差的较大的top-k作为训练的负样本,以保证正负样本比例接近1:3。
2.4.2 损失函数
训练样本确定了,然后就是损失函数了。损失函数定义为位置误差(locatization loss, loc)与置信度误差(confidence loss, conf)的加权和:
( x , c , l , g ) = 1 N ( L c o n f ( x , c ) + α L l o c ( x , l , g ) ) (x, c, l, g) = \frac{1}{N}(L_{conf}(x,c) + \alpha L_{loc}(x,l,g)) (x,c,l,g)=N1(Lconf(x,c)+αLloc(x,l,g))
其中 N 是先验框的正样本数量。这里
x
i
j
p
∈
{
1
,
0
}
x^p_{ij}\in \{ 1,0 \}
xijp∈{1,0} 为一个指示参数,当
x
i
j
p
=
1
x^p_{ij}= 1
xijp=1 时表示第 i 个先验框与第 j 个ground truth匹配,并且ground truth的类别为 p 。 c 为类别置信度预测值。 l 为先验框的所对应边界框的位置预测值,而 g 是ground truth的位置参数。对于位置误差,其采用Smooth L1 loss,定义如下:
由于
x
i
j
p
x^p_{ij}
xijp 的存在,所以位置误差仅针对正样本进行计算。值得注意的是,要先对ground truth的 g 进行编码得到
g
^
\hat{g}
g^ ,因为预测值 l 也是编码值,若设置variance_encoded_in_target=True,编码时要加上variance:
g ^ j c x = ( g j c x − d i c x ) / d i w / v a r i a n c e [ 0 ] , g ^ j c y = ( g j c y − d i c y ) / d i h / v a r i a n c e [ 1 ] \hat{g}^{cx}_j = (g^{cx}_j - d^{cx}_i)/d^w_i/variance[0], \hat{g}^{cy}_j = (g^{cy}_j - d^{cy}_i)/d^h_i/variance[1] g^jcx=(gjcx−dicx)/diw/variance[0],g^jcy=(gjcy−dicy)/dih/variance[1]
g ^ j w = log ( g j w / d i w ) / v a r i a n c e [ 2 ] , g ^ j h = log ( g j h / d i h ) / v a r i a n c e [ 3 ] \hat{g}^{w}_j = \log(g^{w}_j/d^w_i)/variance[2], \space \hat{g}^{h}_j = \log(g^{h}_j/d^h_i)/variance[3] g^jw=log(gjw/diw)/variance[2], g^jh=log(gjh/dih)/variance[3]
对于置信度误差,其采用softmax loss:
权重系数
α
\alpha
α 通过交叉验证设置为1。
2.4.3 数据扩增
采用数据扩增(Data Augmentation)可以提升SSD的性能,主要采用的技术有水平翻转(horizontal flip),随机裁剪加颜色扭曲(random crop & color distortion),随机采集块域(Randomly sample a patch)(获取小目标训练样本),如下图所示:
2.5 SSD预测过程
预测过程比较简单,对于每个预测框,首先根据类别置信度确定其类别(置信度最大者)与置信度值,并过滤掉属于背景的预测框。然后根据置信度阈值(如0.5)过滤掉阈值较低的预测框。对于留下的预测框进行解码,根据先验框得到其真实的位置参数(解码后一般还需要做clip,防止预测框位置超出图片)。解码之后,一般需要根据置信度进行降序排列,然后仅保留top-k(如400)个预测框。最后就是进行NMS算法,过滤掉那些重叠度较大的预测框。最后剩余的预测框就是检测结果了。
2.6 SSD总结
SSD结合了YOLO中的回归思想和Faster R-CNN中的anchor机制,使用全图各个位置的多尺度区域特征进行回归,既保持了YOLO速度快的特性,也保证了窗口预测的跟Faster R-CNN一样比较精准。SSD在VOC2007上mAP可以达到72.1%,速度在GPU上达到58帧每秒。
3. Seglink
3.1 网络结构
- 主干网络是沿用了SSD网络结构,并修改了最后的Pooling层,将其改为卷积层。具体来说:首先用VGG16作为base net(论文中用了backbone这个词,很好),并将VGG16的最后两个全连接层改成卷积层(6-7层)。接着增加一些额外的卷积层(8-11层),用于提取更深的特征,最后的修改SSD的Pooling层,将其改为卷积层。
- 提取不同层的feature map,文中提取了conv4_3, conv7, conv8_2, conv9_2, conv10_2, conv11。这里其实操作还是和SSD网络一样。
- 对不同层的feature map使用3*3的卷积核产生最终的输出(包括segment和link),不同特征层输出的维度是不一样的,因为除了conv4_3层外,其它层存在跨层的link。这里segment是text的带方向bbox信息(它可能是个单词,也可能是几个字符,总之是文本行的部分),link是不同bbox的连接信息(文章将其也增加到网络中自动学习)。
- 然后通过融合规则,将segment的box信息和link信息进行融合,得到最终的文本行。
3.2 Segment检测
Segment也是box,表达形式如下:
它相比SSD来说增加了角度信息。
关于default box的个数,本文每个feature map的每个位置只采用了一个aspect ratio=1的default box,而SSD中是一系列(1, 2, 3, 1/2, 1/3),这也是Seglink速度很快的原因。关于default box的scale size,本文的是根据当前层的感受野来进行设置scale size,而SSD是通过人工设定的,具体的设置公式如下:
其中分子分母分别表示输入图像的宽度和当前feature map的宽度。
Segment计算公式:
总结来说,对于segments的预测包括:2个segment score和5个geometric offsets为
(
x
s
,
y
s
,
w
s
,
h
s
,
θ
s
)
(x_{s},y_{s},w_s,h_s,\theta_s)
(xs,ys,ws,hs,θs)。
3.3 Link检测
link主要是用于连接上述segment,对于link detection部分,主要分成层内link检测(within-layer)和跨层link检测(cross-layer)。
上面的是层内Link,连接的是同层的8个邻域;下面的是跨层Link,连接连续两层的Link。
3.3.1 层内link检测
在同一个feature map层,由于文中对feature map中每个位置只预测一个segment,所以对于层内的link,我们只需要考虑当前segment的8邻域:即判断每个segment与它周围的8连通邻域的segment的连接情况,每个link有两个分数,一个用是正分,一个是负分,正分用来表示二者是否属于同一个单词;负分表示二者是否属于不同单词,应该断开连接。所以,每个segment的link应该是8*2=16维的向量。具体公式如下:
3.3.2 跨层link检测
由于采用不同feature map,所以segment可能会被不同的feature map检测到,为了解决这种重复检测的冗余问题,文中提出了cross-layer Link。它主要是用于连续两层(注意这里前一层是后一层的邻居,但后一层不是前一层的邻居),所以只需要对conv7, conv8_2, conv9_2, conv10_2, conv11进行cross-layer link检测。
论文中说这些feature map中是前一层特征图的size是后一层的特征图的size的两倍(因为有pooling或者是步长为2的卷积层),这些特性需要保证feature map的size是偶数,所以输入图像的宽和高必须是128的倍数。
对于cross-layer link,对于feature map的每个位置需要预测2*4=8,这里4表示的是与上一层的4个邻域,就是对应前一层的感受野,具体公式如下:
总结来说:对于conv4_3层,其link输出的维度为2x8=16;对于conv7, conv8_2, conv9_2, conv10_2, conv11其输出的link维度为2x8+2x4=24。
3.3.3 网络预测输出的维度
上图中2表示是或不是字的二类分类分数,5表示位置信息x, y, w, h, θ,16表示8个同层的neighbor的连接或者不连接2种情况,8表示前一层的4个neighbor的连接与不连接情况。
对于conv4_3:其预测输出维度为:
2
+
5
+
2
×
8
=
23
2+5+2\times8=23
2+5+2×8=23 ,因为该层没有cross-layer link
对于conv7, conv8_2, conv9_2, conv10_2, conv11,其预测输出维度为:
2
+
5
+
2
×
8
+
2
×
4
=
31
2+5+2\times8+2\times4=31
2+5+2×8+2×4=31。
3.4 Combining Segments with Links算法
- 首先通过人工设定的 α 和β(这两个值是采用网格搜索找到最优),对网络预测的segments和links进行滤除
- 将每个segment看成node,link看成edge,建立图模型,再用DFS(depth first search)找到连通分量,每个连通分量包含一系列segments(用B表示),用下面的Alg1进行融合输出单词的box
- Alg1算法其实就是一个平均的过程。先计算所有的segment的平均θ作为文本行的θ,再根据已求的θ为已知条件,求出最可能过每个segment的直线(线段,这里线段就是以segment最左和最右的为边界),以线段中点作为word的中心点(x,y),最后用线段长度加上首尾segment的平均宽度作为word的宽度,用所有segment的高度的平均作为word的高度。
3.5 训练
3.5.1 Ground Truth
Seglink的Ground Truth包括defaut box的label、offset、层内Link和跨层Link的label。
- 那么如何确定default box为正样本还是负样本呢?
1)当前图像只有一个文本行,这时候判断当前default box为正样本必须同时满足:
a)default box的中心在当前文本行内;
b)default box的size与文本行的高度比必须满足: m a x ( a l h , h a l ) ≤ 1.5 max(\frac{a_l}{h},\frac{h}{a_l})\leq1.5 max(hal,alh)≤1.5 。
若不满足上述两个条件,则当前default box为负样本;
2)对于当前图像包含多个文本行,若不满足前面的两个条件,则default box为负样本,否则default box为正样本,并与 a l h \frac{a_l}{h} hal 最小的文本行匹配。 - 那么如何确定offset?
首先要知道offset只对正样本有效,也就是说负样本不需要计算。其具体做法是向将文本行的bbox与default box进行那个水平对齐(就是将文本行的bbox进行旋转,这里旋转逆时针的,之所以说是逆时针方向,是因为当前的角度为负,具体结合图像来理解);然后对文本行box进行裁剪,保留default box与文本行相交的部分(注意,这里垂直方向需要延伸,简单地说裁剪后的宽度保持default box与文本行box相交的部分,高度要保持文本行的高度);最后再绕default box的中心点进行顺时针旋转,即转回到原来的角度,这样就会得到一个裁剪后的带角度的bbox,它就是groundtruth segment.这样做的目的是当前网络检测是segment,而非整个文本行.网络要学习的偏移实际上就是default box相对于裁剪后的bbox的偏移,具体的细节流程图如下:
- 如何确定层内link和跨层link的label是positive还是negative?
要想使link的label为positive,必须满足:
1)两个default boxes connect it;
2)两个default box必须属于统一文本行。
3.5.2 损失函数
网络的损失函数包括三部分:segment classification损失(softmax),offsets regression损失(L1 regression),link classification损失(softmax),具体公式如下:
其中控制全中因子λ1 和 λ2设置为1。
3.5.3 数据增广
与SSD做法一致。
3.5.4 结果
4. 总结
- 创新点:
Seglink可以检测多方向文本(这是相对于SSD的一个创新点,因为在Segment中加入了角度信息);
Seglink将Link也放入了神经网络中学习,而不是像常规方法一样在后处理步骤中将多个bounding box通过合并算法合并,这也是Seglink的第二个创新点;
Seglink不涉及到感受野的问题,所以可以处理长文本;而且由于link的特性,Seglink可以很好地处理弯曲文本(看了这么多模型只有Seglink可以处理弯曲文本!!!)
- 局限性:
α和β这两个阈值设置需要人工,虽然用了网格搜索求得,网格搜索是一种暴力的模型超参数优化技术,这里采用0.1step进行超参数穷举搜索;
不能检测间隔很大(字很大)的文本行;
5. 参考资料
1.《Detecting Oriented Text in Natural Images by Linking Segments》
2.https://zhuanlan.zhihu.com/p/33544892
3.SSD的tensorflow实现
4.https://blog.csdn.net/v_JULY_v/article/details/80170182
5.https://www.cnblogs.com/lillylin/p/6596731.html
6.https://zhuanlan.zhihu.com/p/37781277
7.Seglink的tensorflow实现