目标检测论文阅读笔记
目标检测论文阅读 SPPNet Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition-CSDN博客
目标检测论文阅读 Cascade R-CNN: Delving into High Quality Object Detection-CSDN博客
目标检测论文阅读 YOLO You Only Look Once:Unified, Real-Time Object Detection-CSDN博客
Mask R-CNN,通过在每个感兴趣区域(RoI)上添加一个用于预测分割掩码的分支(FCN)---每个RoI输出一个二进制掩码,扩展了Faster R-CNN。
Baseline待改进:Faster RCNN不是为网络输入和输出之间的像素到像素对齐而设计的,在ROIPool上表现尤为明显,于是论文提出了RoIAlign---提升掩码精度
Mask RCNN将mask和类预测分成两个互不影响的部分,二者独立预测,相较于一些将分割和分类结合在一起的算法,效果更佳。
不同于以往的方法使用全连接层预测蒙版,论文中使用了全卷积网络FCN,所需参数更少、效果更佳。
目标分割对位置精度的要求高,特别是小物体,为提升mask预测精度,作者提出ROI Align
文中采用ResNet-FPN骨干网提取图像特征图,把底层的特征和高层的特征进行融合,便于细致检测
FPN 特征金字塔网络
卷积网络中,深层网络容易响应语义特征,浅层网络容易响应图像特征。然而,在目标检测中往往因为卷积网络的这个特征带来了不少麻烦:高层网络虽然能响应语义特征,但是由于Feature Map的尺寸太小,拥有的几何信息并不多,不利于目标的检测;浅层网络虽然包含比较多的几何信息,但是图像的语义特征并不多,不利于图像的分类。这个问题在小目标检测中更为突出。因此,如果我们能够合并深层和浅层特征的话,同时满足目标检测和图像分类的需要,那我们的问题就迎刃而解
FPN可以把高层的特征传下来,补充低层的语义,这样就可以获得高分辨率、强语义的特征,有利于小目标的检测。
运用这种金字塔的思想可以提高算法的性能,但是他需要大量的运算和内存。
因此特征金字塔要在速度和准确率之间进行权衡,通过它获得更加鲁棒的语义信息。
图像中存在不同大小的目标,而不同的目标具有不同的特征,所以我们需要特征金字塔来利用浅层的特征将简单的目标区分开,利用深层的特征将复杂的目标区分开。
ResNet50-FPN:
resnet50由一个预处理模块和4个卷积模块构成。4个卷积模块分别命名为res2, res3, res4, res5。预处理模块包括一个卷积层和一个池化层,分别会使图像的大小缩小两倍。3*800*1216的图像经过预处理模块之后,大小会变成64*200*304,然后再送入后续4个block。FPN需要resnet的4个模块输出的特征图,其大小分别是:[res2: 256*200*304, res3: 512*100*152, res4: 1024*50*76, res5: 2048*25*38]。
接下来是FPN部分。FPN取res2, res3, res4, res5的输出特征作为输入,然后对这些特征图进行不同尺度之间的交互。具体就是这样的:先对res5来个1*1卷积把channel数量降到256,然后再来个3*3卷积得到特征p5: 256*25*38;然后把p5上采样,得到256*50*76,这个p5上采样结果加上res4的1*1卷积结果,得到256*50*76,再来个3*3卷积得到p4。然后p4上采样,res3 1*1卷积,相加,3*3卷积得到p3,然后同理得到p2。最终p5被搞了一个MaxPooling得到p6。如此一来,FPN的输出即为:[p2: 256*200*304, p3: 256*100*152, p4: 256*50*76, p5: 256*25*38, p6: 256*13*19]。
图像经过了resnet50-FPN,变成了不同尺度的特征图p2--p6。接下来这些特征图送入到proposal-generator(即RPN)中来生成初步的proposal。
RPN阶段:
RPN的输入为image,特征图以及图像的label,如果是测试等不需要计算loss的时候,不输入label也可以。然后第一步:根据输入的特征图生成anchors。生成anchors的话,首先要确定每个特征图对应的anchor size(可以理解为正方形框的边长)以及anchor的长宽比。假设此时的anchor size为[32,64,128,256,512],长宽比为[0.5, 1, 2]。然后根据不同的size和不同长宽比的排列组合,可以得到15 组个base anchor,这15个base anchor都假设中心点为(0,0)。接下来根据size和stride(stride为每个特征图对应的缩小系数,如p2对应的缩小系数为4.)生成偏移,将这些偏移应用于base anchor,就得到了每个特征图对应的anchors。再具体一点,以特征图p2为例:p2对应的stride
为4。首先根据[32,64,128,256,512]以及纵横比得到了15个base anchor,这15个base anchor的中心都是(0,0)。然后又根据特征图size (200,304)和stride 4,在原图[(200*4)*(304*4)]上以步长为4生成了200*304个中心点。这200*304个中心点与那15个base anchor组合,得到了200*304*15个anchor。然后p3上得到100*152*15个anchor,p4得到50*76*15个,依次类推。
生成了anchors之后,接下来是rpn_head。rpn_head将输入的特征图映射为每个anchor的正负类以及对应的4个顶点的offset。还是拿p2为例子。rpn_head首先用一个3*3卷积卷一下p2,输出的大小还是256*200*304。然后再分别用两个1*1卷积,分别输出p2对应的15*300*304的logits_score和60*300*304的offsets。p3--p6同理。
接下来就是计算loss和predict proposals......
ROI Pooling和ROI Align:
这两个都是用在rpn之后的。具体来说,从feature map上经过RPN得到一系列的proposals,大概2k个,这些bbox大小不等,如何将这些bbox的特征进行统一表示就变成了一个问题。
FasterRCNN使用的是ROI Pooling,继承自fastRCNN,而fastRCNN灵感源于SPPnet的金字塔池化层。
ROI Pooling:
假如现在有一个8x8的feature map,现在希望得到2x2的输出,有一个bbox坐标为[0,3,7,5](x,y,w,h)。
这个bbox的w=7,h=5,如果要等分成四块是做不到的,因此在ROI Pooling中会进行取整。就有了上图看到的h被分割为2,3,w被分割成3,4。这样之后在每一块(称为bin)中做max pooling,可以得到如图的结果。
这样就可以将任意大小bbox转成2x2表示的feature。
ROI Pooling需要取整,这样的取整操作进行了两次,另一次是得到bbox在feature map上的坐标时。
例如:
原图上的bbox大小为665x665,经backbone后,spatial scale=1/32。因此bbox也相应应该缩小为665/32=20.78,但是这并不是一个真实的pixel所在的位置,因此这一步会取为20。
0.78的差距反馈到原图就是0.78x32=25个像素的差距。如果是大目标这25的差距可能看不出来,但对于小目标而言差距就比较巨大了。
ROI Align
因此有人提出不需要进行取整操作,如果计算得到小数,也就是没有落到真实的pixel上,那么就用最近的pixel对这一点虚拟pixel进行双线性插值,得到这个“pixel”的值。
具体做法:
- 将bbox区域按输出要求的size进行等分,很可能等分后各顶点落不到真实的像素点上
- 在每个bin中再取固定的4个点(作者实验后发现取4效果较好),也就是图二右侧的蓝色点
- 针对每一个蓝点,距离它最近的4个真实像素点的值加权(双线性插值),求得这个蓝点的值
- 一个bin内会算出4个新值,在这些新值中取max(最大池化),作为这个bin的输出值
- 最后就能得到2x2的输出