[论文阅读] CTPN---Detecting Text in Natural Image with Connectionist Text Proposal Network

  • 这篇论文思路和Faster RCNN是差不多的。总体来说,就是先通过RPN(Region Proposal Network)来提取proposal,然后再对提取得到的proposal进行classification。

  • 阅读实现代码:CTPN

  • 文章对Faster RCNN有以下几点修改:

    • Faster RCNN中使用的3种size和3种长宽比组合的9种anchor,但是CTPN中,他固定了anchor为16px(vgg16, 因为有4个pooling 层),而只是设置了10种高的值。这样是结合了text detection的特点,一般都是细长的结构。
    • 再得到Feature map之后,我们通过一个BD-LSTM结构去提取每个pixel对应的Feature。这样做是为了利用global information。他将一行的pixel看成一个序列输入给BD-LSTM去提取Feature。得到BD-LSTM的输出以后,我们再去得到每个anchor的score以及对应的anchor的坐标值。
    • 还有一个contribution是他对水平坐标还做了一定的微调。具体的公式如下所示:
      o = ( x s i d e − c x a ) / w a , o ∗ = ( x s i d e ∗ − c x a ) / w a o = (x_{side} - c_x^a) / w^a, o^* = (x_{side}^* - c_x^a) / w^a o=(xsidecxa)/wa,o=(xsidecxa)/wa
      这里面o代表的predict, o ∗ o^* o代表的是GT。 x s i d e x_{side} xside代表的是未修正的预测的anchor的坐标, x s i d e ∗ x_{side}^* xside代表的就是ground truth。 c x a c_x^a cxa代表anchor的对心所对应的x坐标。 w a w^a wa代表anchor的宽,这里是固定值(16)。之所以除以宽相对于做了一定的归一化吧。
      [论文阅读] CTPN---Detecting Text in Natural Image with Connectionist Text Proposal Network_第1张图片
  • 算法的流程:如图上所示:

    • 首先通过常规的特征提取模块(例如,VGG16)来得到feature map,假设大小为 h ∗ w ∗ c h*w*c hwc,其stride为16。
    • 通过一个卷积层,将其转化为 h ∗ w ∗ 256 h*w*256 hw256的shape
    • 我们将其转化为 h ∗ ( w ∗ 256 ) h*(w*256) h(w256),其中,将 w ∗ 256 w*256 w256看成一个长度为w的输入序列,将其输入到BD-LSTM中。
    • 将得到feature 再转化成 h ∗ w ∗ d h*w*d hwd 其中d代表的是BD-LSTM输出的维度
    • 在此,我们得到了一个新的feature map, FM,他相对于VGG16的原始输入,他扩大了同一个pixel(feature map)的水平感受野,使其扩展到了整个水平方向。
    • 在新FM的基础上,我们再通过卷积层,将其转化为预测anchor的label和anchor的坐标回归值。
    • 现在我们已经得到了 H ∗ W ∗ ( A ∗ 2 ) H*W*(A*2) HW(A2) H ∗ W ∗ ( A ∗ 4 ) H*W*(A*4) HW(A4)的anchor score 和 anchore regression。接下来怎么办呢?接下来train和test有所不同。train比test多了一些计算anchor label和regression label的操作。对于两者共有的部分自然就是proposal的生成。
    • proposal对于训练来说其实就是过滤了一些anchor,保留了一些正负样本的anchor。对于测试来说只是通过nms来过滤了一些anchor,并没有通过label来确保正负anchor 的平衡(但是在训练阶段是有这项操作的)。
    • 训练的过滤机制:
      • 首先计算所有anchor和gt_boxes的overlap,由此可以确定anchor的label(是正还是负)
      • 知道是正负的后,正负数量平衡之后可以过滤掉一部分anchor。这里的过滤是指赋予小的权重。
    • regression的gt如何计算?
      • 从上面我们可以知道每个anchor和gt_boxes的overlap,所以我们就指定与正anchor overlap最大的gt_box为该anchor的gt
      • 然后我们计算dx,dy,dw,dh
      • d x = ( c e n t e r x a n c h o r − c e n t e r x g t ) / w i d t h a n c h o r dx = (center_{x_{anchor}} - center_{x_{gt}}) / width_{anchor} dx=(centerxanchorcenterxgt)/widthanchor
      • d y = ( c e n t e r y a n c h o r − c e n t e r y g t ) / w i d t h a n c h o r dy = (center_{y_{anchor}} - center_{y_{gt}}) / width_{anchor} dy=(centeryanchorcenterygt)/widthanchor
      • d w = l o g ( w i d t h g t w i d t h a n c h o r ) dw = log(\frac{width_{gt}}{width_{anchor}}) dw=log(widthanchorwidthgt)
      • d h = l o g ( h e i g h t g t h e i g h t a n c h o r ) dh = log(\frac{height_{gt}}{height_{anchor}}) dh=log(heightanchorheightgt)
      • 通例,我们在test阶段,也可以利用 d x p r e d , d y p r e d , d w p r e d , d h p r e d dx_{pred}, dy_{pred}, dw_{pred}, dh_{pred} dxpred,dypred,dwpred,dhpred来进行anchor坐标的更新。注意在faster RCNN中,我们即更新中心点的xy坐标,还更新height和width。但是在CTPN中,由于其使用的vertical mechanism,所以我们只更新y坐标的height的值。
    • CTPN其实本质上来说是one stage的,因为faster RCNN后续对proposal的处理CTPN是不需要的,因为正的proposal肯定都是一个类(文本),不存在再对proposal进行多分类的问题。
    • 然后再分别通过全连接层来对每个anchor预测score以及坐标。注意,这里是对feature map中的每个pixel进行预测的。也就是说我们fc的输出分别是hw(102)以及hw*(10*4)
    • 最后使用上面步骤训练好的网络,得到类似与上图B的许多anchor,然后在使用连接算法,将其连接起来。连接算法的定义如下:
      • 首先挑选出所有score>0.7的anchor
      • 针对每个anchor, B i B_i Bi定义他的邻居anchor B j B_j Bj, 他们要满足以下条件
        • 这两个anchor的最近的
        • anchor之间的距离小于50个pixel
      • 如果 B i B_i Bi B j B_j Bj互为邻居,那么就将其合并,知道找不到互为邻居的anchor为止。
  • anchor机制:

    • 我们先得到feature map上的每个点对应到原图的点得到一个数组,_anchor,其shape=[k, 4],k = FM的长乘以宽
    • 然后再将每个anchor相对的坐标加上去。得到最后在所有的anchor在原图中的坐标。
  • 上面讲了算法的流程,接下来我们看一下loss的定义,来了解具体我们怎么训练我们的网络
    L ( s i , v j , o k ) = 1 N s ∑ i L s c l ( s i , s i ∗ ) + λ 1 N v ∑ j L v r e ( v j , v j ∗ ) + λ 2 N o ∑ k L o r e ( o k , o k ∗ ) L(s_i,v_j,o_k) = \frac{1}{N_s}\sum_iL_s^{cl}(s_i, s_i^*) + \frac{\lambda_1}{N_v}\sum_jL_v^{re}(v_j, v_j^*) + \frac{\lambda_2}{N_o}\sum_kL_o^re(o_k, o_k^*) L(si,vj,ok)=Ns1iLscl(si,si)+Nvλ1jLvre(vj,vj)+Noλ2kLore(ok,ok)

    • 上面是训练的整体的loss,它由三部分组成,第一部分是分类的交叉熵,第二部分是对垂直坐标做regression的Smooth L1loss,第三部分是对水平坐标做regression的Smooth L1 loss。
    • s i s_i si代表的是第i个anchor预测是text的概率, s i ∗ s_i^* si是对应的ground truth{0,1}。
    • v j , v j ∗ 分 别 代 表 的 是 第 j 个 a n c h o r 所 对 应 纵 坐 标 的 预 测 值 和 g r o u n d t r u t h 。 注 意 , 这 里 的 j 和 i 不 一 样 是 因 为 , 这 里 我 们 只 计 算 p r o b a b i l i t y > 0.7 或 者 是 v_j, v_j^*分别代表的是第j个anchor所对应纵坐标的预测值和ground truth。注意,这里的j和i不一样是因为,这里我们只计算probability>0.7或者是 vj,vjjanchorgroundtruthjiprobability>0.7s_j^*=1$的anchor,也就是只计算正样本
    • Smooth L1 loss的定义如下:
      v a r = w i n ( x i − y i ) i ∈ { x , y , w , h } s m o o t h i = { 1 2 v a r i 2 σ 2 ∣ x σ ∣ < 1 ∣ v a r i ∣ − σ 2 0.5 o t h e r w i s e S m o o t h L 1 L o s s = ∑ i s m o o t h i var = w_{in} (x_i - y_i) i\in\{x,y,w,h\}\\ smooth_i = \left\{\begin{matrix} \frac{1}{2}var_i^2\sigma^2& |x\sigma|<1\\ |var_i|-\frac{\sigma^2}{0.5} & otherwise \end{matrix}\right.\\ SmoothL1Loss = \sum_{i}smooth_i var=win(xiyi)i{x,y,w,h}smoothi={21vari2σ2vari0.5σ2xσ<1otherwiseSmoothL1Loss=ismoothi
    • 这里使用Smooth L1 loss主要是因为:L1 loss会产生更稀疏的矩阵,L2 loss会产生更平滑的矩阵(原因)。但是有一个问题是L2如果我们var太大的话,还产生梯度爆炸,所以我们在这里使用了Smooth L1 Loss,他其实是一个分段的函数。如果var较小的话,我们使用L2 loss,否则,我们使用L1 loss。
  • 自问自答?

    • 什么是vertical mechanism?
      • 正如我们在上面提到的那样,我们会预测得到 d x , d y , d w , d h dx, dy, dw, dh dx,dy,dw,dh。一般的faster RCNN会利用上述四个值去修正anchor的坐标得到proposal。但是CTPN只利用了dy和dh的信息,因为横坐标的值是固定的。
    • 作者是如何将提取的proposal连接起来的?
      • 在测试阶段,我们先通过对anchor进行坐标修正和nms,得到proposal。每个proposal的width都是16(stride)。
      • 接下来,我们构建一个有向图,图中每个节点代表的一个proposal。判断proposal之间的联系。如下图所示。
        [论文阅读] CTPN---Detecting Text in Natural Image with Connectionist Text Proposal Network_第2张图片
      • 如果A->B
        • 则B的横坐标必须大于A,且在所有横坐标大于A的proposal中B的横坐标是最小的。
        • B与A的横坐标距离不超过50pixel
        • 垂直的overlap大于一定的阈值
        • height差距不是特别大
      • 接下来对于每个proposal,我们判断其在图中的入边的个数是否为0。如果是,并且出边不为0。纳入集合A中,再找到next指向的proposal,将其纳入集合A,迭代下去,直到proposal没有出边(也就是说是text line的最后一个proposal)。
      • 针对我们找到的每行,我们对应的是一个proposal的集合。那我们怎么得到最终这一行的bounding box呢?
        • 我们首先可以计算得到x_min 和 x_max
        • 我们先通过proposals[:, 0], proposal[:, 1]拟合一条直线,再取x_max, x_min在这条直线上y的值的最小值。
        • 我们先通过proposals[:, 0], proposal[:, 3]拟合一条直线,再取x_max, x_min在这条直线上y的值的最大值。
        • 上述之所以取最小最大是因为我们的输出是bounding box,而不是任意四边形。
      • 至此,我们就完成了一行proposal的合并。
  • 有问题,欢迎探讨

你可能感兴趣的:(深度学习,论文阅读,CTPN,Text,Detection,Deel,Learning,Paper)