DBNet学习记录

DBNet网络介绍

  • 总体概述
    • 整体思路
    • label的生成
    • 如何通过P和T得到B
    • 损失函数的设计
    • inference过程
  • 网络详解
    • backbone:ResNet
    • neck: FPN
    • head: DBHead
  • 结语

总体概述

本文中的一些图片来自B站大佬录制的DBNet的讲解视频,文中一些地方也是通过看视频才搞清楚,视频链接放下面了。
链接: 视频链接

整体思路

DBNet学习记录_第1张图片
首先放上一张原论文中的图片。其中segmentation map简称为P threshold map简称为T binarization map简称为B
传统的文字检测方法都是用蓝色的线这个流程。但是DBNet的创新点就是用的这个红色的线的流程。他的创新就是提出了一个可微分的二值化操作,通过T和P来得到最后的B,最终可以得到文字区域。
DBNet学习记录_第2张图片

在训练过程中,B、T、P这三张图都受监督。其中B和P受相同label的监督,而T受另一种label的监督。
P和T经过上图中的阈值函数(也就是这篇论文的创新点)处理,得到B。
DBNet学习记录_第3张图片
这里在放上一张实例图,来解释一下什么是P、T,以及B。
首先最左侧是原图,中间这个是P,白色的地方就是文字所在的区域,其实他是小于文字区域的,再生成P的时候实际上用了一个shrink的操作,在这里假设白色的地方是1,那么黑色的地方就是0。
最右侧的是T,我认为可以这样来理解,T是将文字框所在的位置给标注出来了。可以看到T图中的颜色并不是黑白两种,他是两种灰色。其中深一点的灰色不是文本框的位置,他对应的值假设为0.3(也就是一个阈值,小于这个值我们就认为不是文本框了),浅色的地方是文本框的位置(这些浅色的位置,其实他的值并不是一个固定的,后面讲到它里面的值具体怎样计算)。这里的0.3和0.7是原文中设置的两个值,可以根据自己的数据集来进行调整。
DBNet学习记录_第4张图片
放在同一张图上大概就是这样的。

label的生成

简单解释一下P和T是如何生成的。这里这样做的原因是参照PSENet网络,防止将两个联系紧密的文字分割成一个实例。具体解释可以看一下PSENet的原文,这里不在过多赘述。
P:将原图中的文本框的大小经过shrink得到的。也就是进行一定的算法(具体见原文中的公式,其中有一个超参数缩放比例r,原文取的是0.4),将文本框缩小一定的比例,然后将这个框内得值全部设置为1(白色),其他地方的值全部设置为0(黑色)。
T:将原图中文本框分别经过一定算法进行缩放(这个得到的大小和P中得到的大小是相同的)和扩张。文本框的位置指的是夸张和缩放之间的位置。注意,这里缩放和扩张用的算法并不太一样。得到之后进行简单的处理,将整张图中的值变为0.3-0.7之间(这两个值也是可以通过自己去设置的)。其中非文本框的位置全部设置为0.3,文本框的位置是0.3-0.7之间。并且越靠近原图中的框的位置,值越接近0.7。
DBNet学习记录_第5张图片
红色为原本的文字框,蓝色是shrink之后的框,绿色是扩张之后的框。其中红色箭头所指的方向是像素值不断变大的地方(0.3变为0.7)。具体怎样得到右侧这个像素图,可以去看源码,操作起来可能有些繁琐,但是思路并不难。
这里简单说一下大概思路:首先求蓝色框和红色框之间的每个像素点到红框4个边的距离中的最小距离,之后将这个距离进行简单的处理(首先进行归一化,变到0-1之间,接着用1减去每个点的像素值,实现一个反转),使其变到0.3-0.7之间。蓝色框和绿色框之间的像素值用同样的方法得到。
下面贴上原问中的一个实例图,方便理解。
DBNet学习记录_第6张图片

如何通过P和T得到B

这里在详细解释一下怎样由P和T经过阈值函数处理得到B。
DBNet学习记录_第7张图片
详细见上图。可以很明显的看出,P图中的白色区域,和T图中的最内部的灰色区域大小实际上是一样大的。也就是最后得到的二值图像,实际上也是shrink后的。那么这个T图的目的是什么呢?是为了满足可微分二值化,并且经过训练之后效果会更好。
关于这样做为什么会效果更好一点,论文中也进行了一定的解释。
DBNet学习记录_第8张图片
这里的损失函数用CELoss来计算。其中a图中的蓝线是DB的图像,b图为l+的导数图像,c为l-的导数图。
在计算损失的过程中,假设来了一个正样本(也就是文字区域),应该预测出来x是一个整数,假设这个网络判断错了,输出的x是一个复数,那么从b图中可以看出,会得到一个小于负10的数,再反向传播的过程中,可以加速网络的收敛。对于原本是一个负样本,网络判断为正样本的时候,也就获得一个大于10的梯度,加速网络的收敛。

损失函数的设计

在这里插入图片描述
其中LS表示P图的损失,Lb表示B图的损失。这两个损失直接用BELoss进行计算。当然这里还用到了Hard negative mining(错题集)的思想:就是说在目标检测中,我们会弄很多框进行损失的计算,但其实在实际图片中,物体比较少,很多框里面全是背景,训练半天对我们的网络没有任何作用。这种框一般叫做easy negative。还有一些框,里面有物体的一部分,但是我们可以计算一下他和物体框的交并比,如果这个值大于设定的一个阈值,那么就判断他是一个正例。
一般我们在目标检测过程中,会事先随机生成一些框,根据交并比判断正负样本。一般让正:负=1:3。在训练过程中,对于总是预测错误的负样本,将其作为hard negative样本加入到训练集中,继续进行训练。
Lt是T图的损失:计算膨胀之后框内所有像素点的L1距离。

inference过程

以上所说都是train过程,下面简单介绍一下inference过程。
在inference过程中,原文是根据P图进行预测的(当然你可以用二值图来预测实际上他们两个文本框的大小是相同的)。但是经过P图中的文本区域,实际上是shrink后的,需要将其扩大为原来的大小后进行输出。这里是设置了一个固定的阈值0.2,大于0.2就认为是文字区域,赋值为1,否则赋值为0,这样就得到一个二值图了。接着可以用cv2中的一些函数,将文本框出来。
cv2.findContours() ----> 绘制出一个不规则图形框出来
cv2.minAreaRect() ----->绘制一个可以将文字框出来的最小矩形(paddleocr貌似就是这样做的)
也就是说T图和B图实际上只是在训练过程中用到了,目的是实现可微,并且当网络预测错的的时候,产生较大的损失,从而加速网络的收敛。

网络详解

这部分简单介绍一下DBNet的三个网络结构。

backbone:ResNet

backbone,顾名思义,也就是网络的主干。这里的主干主要是指的在特征提取过程中的主干网络。原文中采用了ResNet18和ResNet50这两种网络结构。其中用ResNet的效果会更好一点,不过缺点就是速度稍慢。下面以ResNet18为例简单讲解。
DBNet学习记录_第9张图片
图中,红框圈起来的地方就是ResNet的结构。首先将其进行三次卷积接着进行最大值池化,缩小为原图的一半,也就是红框中左侧第一个图,此时图片的通道数是64。接着经过两个相同的残差块,使得图像缩小为原来的四分之一,通道数保持为64。接着经过两个相同的残差块,图片变为原图的八分之一,通道数变为128。接下来以此类推,每次经过两个相同的残差块,使得图像大小缩小为上次的二分之一,同时通道数翻倍。到最后,得到一个原图大小1/32的,通道数为512的特征图。

neck: FPN

FPN也就是特征金字塔,就是在resnet的基础上,进行多层特征融合的一个过程。
低层的特征图更大,也更注重比较小的物体,而高层的特征图更注重比较大的物体。一般的网络都是通过最后一层特征图进行预测。但是如果这样会导致在目标检测过程中,由于池化层的影响,原本在原图中比较小的物体,到最后一层特征图的时候就消失了,因此不利于检测小的目标。FPN的思想就是将低层和高层的特征图进行融合,从而解决多尺度检测的问题。
在DBNet中,可以看到从最后一层大小为原图1/32的特征图,经过上采样,将其变为原图的1/16和倒数第二层进行相加。当然因为后两层的通道数不同,所以在相加之前,会经过1*1的卷积,将二者的通道数统一变为64,依次往前类推。最后将处理过后的几个特征图分别经过上采样,变为原图的1/4,在进行concat,得到最终的特征图。特征图的形状 batch_size x 256 x 1/4width x 1/4heigt
其他信息具体可见FPN的原文。

head: DBHead

最后就是对上一步得到的特征图进行处理分别得到P和T。也就是完成了下图中的内容。
DBNet学习记录_第10张图片
特征图分别经过一次卷积+BN+Relu,将通道数变为64,之后经过两次上采样,将图片变为原图大小,并且通道数变为1,得到P和T。其形状都是batch_size x 1 x width x height。接着经过原文中的DB操作得到最后的B图。
最后将三张图在dim=1的维度上进行拼接,得到一个batch_size x 3 x width x height的Tensor进行后续的损失计算。

结语

这是本人第一次写博客,目的是将近期所学内容进行简单的回顾,以上都是个人对于原文的理解,如有错误,欢迎大家批评指正,一起讨论。

你可能感兴趣的:(学习,人工智能,算法)