前言

目标检测分为两种方法:一阶段法和两阶段法。一阶段法的代表算法为YOLO,SSD,具有速度快的优势。所谓两阶段法就是先找出图像中的region proposal ,再分别对每个proposal进行回归和分类,它的优势则是精确度高,Mask R-CNN则是这一方法,从一开始的R-CNN到Fast R-CNN再到Faster R-CNN,FPN,到最后的Mask R-CNN,演进过程中的一些方法依旧用于其他的机器视觉任务中,所以这个路线中的网络架构和方法非常值得我们去学习。

Sliding windows

2020121901

这是目标检测的最早期的算法——滑动窗口法,很好理解,就是固定一个窗口(不同的size 和长宽比)从左向右,从上到下的去滑动,对每个窗口的图像进行目标识别与分类。这种方法可想而知,非常耗时。

R-CNN

2014年的时候随着深度学习的兴起,R-CNN横空出世了。与滑动窗口法不同,这里使用selective search 这种 region proposal method 来提取图像的RoIs (感兴趣区域)。这里我们可以看下这种方法的思想,相似的像素、纹理或者是灰度等会被归为一个区域,并得到这样的很多个小bounding box后,在对这些bounding box进行归类或者说聚类,使得整个图像的RoIs保持在2000个左右。

下面我们来看下R-CNN的网络结构图

image-20201218110258776

总结一下网络结构图:

  • 首先对图像使用 selective search方法,得到图像的RoIs
  • 根据 RoIs 在原图像中裁剪,得到2k个不同尺寸的小image,再wrap 成相同尺寸大小的img
  • 把相同大小的2k个img分别喂入CNN中提取特征,并使用SVM对目标进行分类,使用 bbox reg对 bounding Box进行定位。

SVM我们都知道是如何分类的,那么bounding box是如何通过回归来确定呢?

首先我们可以看到这个一张飞机的图像,红色是候选的建议框,绿色是ground truth真实框,这个回归就是去学习这种变换映射关系,一个bounding box 通常由四个坐标表示,x,y坐标以及长宽w,h。通过映射公式可以看出 在 x,y上做平移变换,在 w,h做缩放变换,经过整理,就可以得到目标的优化对象。

image-20201218110519892

现在,我们来回顾一下R-CNN的贡献和缺点

  • 使用selective search 来做region proposal
  • 使用 SVM分类,boundingbox reg 回归

缺点:

  • selective search依旧费时
  • 分别把2k个RoI图像送入CNN提取特征,存在大量重复计算

Fast R-CNN

Fast R-CNN出现就是为了解决这个重复计算的问题,它最大的贡献就是把region proposal method 直接应用到feature map上,因此只要对一张图片喂入CNN中进行特征提取,然后把selective search得到的RoI位置映射到feature map(这点作者在论文中已经证明, feature map 中的位置和原图像的位置具有对应关系)。

image-20201219231330001

image-20201219231337746

总结一下Fast R-CNN的网络结构:

  • 对原图像应用selective search 得到2k 个region proposal
  • 把原图像喂入CNN网络提取特征,得到feature map
  • 把region proposal 映射到feature map 中,并对这2k 个proposal 的进行ROI pooling 来 wrap 到固定的尺寸
  • 使用CNN网络来做分类和回归

那么 ROI pooling 到底是怎么实现的呢?

比如一个 8 x 8 的 feature map ,我们要在这个feature map上得到ROI,并且进行ROI pooling到2x2大小的输出。

假设一个ROI的 bounding box 为(0,3,7,8) , 将它划分为2x2的网格,因为ROI的长宽除以2是不能整除的,所以会出现每个格子大小不一样的情况,对每个区域进行最大池化,就可以得到 2 x 2 的的输出。

image-20201219231532213

因此,总结一下,Fast R-CNN的贡献和缺点

  • 从 feature map 得到proposal 而不是 images
  • 使用ROI pooling 把所有RoI特征图 wrap到固定尺寸

缺点:

  • selective search的时间消耗问题仍未解决

Faster R-CNN

Faster R-CNN出现就是为了解决selective search 耗时的问题,这里使用了RPN深度学习网络来生成region proposal,下面先看一下算法的网络架构图。

image-20201218124454510

总结一下Faster R-CNN的网络结构:

  • 把原图像喂入CNN网络提取特征,得到feature map
  • 在得到的 feature map上用RPN网络获取 region proposal ,大大降低时间。
  • 将得到的 region proposal 在映射到特征图中,并做ROI pooling 来wrap成相同的尺寸
  • 使用CNN网络来做分类和回归

那么,RPN是怎么实现的呢?

这里就不得不说到 anchor的思想,下图是一个256维度的8 x 8 的 feature map,其中每一个特征点都对应原图像的一块区域,先用3 x 3 的卷积来获得更大的感受野 ,然后每个特征点用 9 种 anchor 来尝试框住目标区域(3种size ,3 抓种长宽比)。

1

通过这张图可以看出 8 x 8 x 256 的特征图 经过两次1 x 1的卷积 变成两部分: 8 x 8 x 9 x 2 分数和 8 x 8 x 9 x 4 坐标偏移

image-20201218132245129

总结一下

  • Training:在训练的时候,通过 IoU(交并比)来训练,这样的特征可能对应这样的anchor
  • Predition:预测的时候,对feature map 中的每一个特征点做预测,得到分数

至此,Faster R-CNN可以说是解决了之前存在的问题,但是依旧有优化的空间。

其中有两个点值得优化:

  • Faster R-CNN 是单尺度的目标检测框架,会遗漏一些小的目标。

  • ROI pooling 优化为ROI Align

FPN

FPN 的全称是 Feature Pyramid Network 特征金字塔网络,我们首先来看下单尺度的框架

image-20201218140731596

其中,高分辨率的特征比如 112x112x128的特征

  • 精确地空间位置信息
  • 低维度的语义信息

低分辨率的特征比如7x7x512的特征

  • 高维度的语义信息
  • 模糊的空间位置信息

而单尺度的框架最后只用了7x7x512 这样的低分辨率特征,丢失了精确地空间位置信息,因此,多尺度的特征金字塔解决了这个问题!

下面看一下FPN的简单结构图:

image-20201218141837927

总结一下结构,由三部分组成:

  • 自下而上的下采样,提取高维度的语义特征
  • 自上而下的上采样(双线性插值或者反卷积)
  • 横向连接,保留空间位置信息

FPN只是一种思路,具体可以有很多种网络架构实现,比如 VGG,AlexNet,ResNet,下图是使用 ResNet 实现的FPN,也是Mask R-CNN中使用的架构,下面是架构图。

image-20201218142911230

FPN+Faster R-CNN

将 FPN 加入到 Faster R-CNN 网络架构中,变成下图

image-20201218143049566

那么问题来了,对于多尺度的特征图,选择哪个feature map来切出这些ROI区域呢?

实际上,我们会选择最合适的尺度的feature map来切ROI。具体来说,我们通过一个公式来决定宽w和高h的ROI到底要从哪个来切:

$k=\left\lfloor k_{0}+\log _{2}(\sqrt{w h} / 224)\right\rfloor$

先来说一下这几个参数的意义

  • 224 : 使用ImageNet预训练数据集的图片尺寸
  • k0 : 当 RoI 为 224 x 224 时所在的层级,作者将 k0 设置为 4,也就是ROI从P4中切出来

比如一个112 x 112 的ROI ,k=3, 这个ROI 应该从 P3 从切出来,这很好理解,分辨率越小的RoI应该从feature map 尺寸较大的层级切出来,因为这样的feature map 保留了更多的空间位置信息。

Mask R-CNN

FPN+Faster R-CNN+Mask Prediction = Mask R-CNN

下图是 Mask R-CNN的网络结构图

image-20201219200434400

总结一下结构:

  • backbone:ResNet-FPN 用于特征提取,另外,ResNet还可以是:ResNet-50,ResNet-101,ResNeXt-50,ResNeXt-101;
  • Head:包括边界框识别(分类和回归)+ mask预测。头部结构见下图

现在细看一下Mask branch 是怎么做的

image-20201218155313527

可以从结构图中看出,前面经过POIAlign后的ROI被送入两个分支

  • 第一个分支用来分类和回归boundingbox

  • 第二个mask分支来做实例分割,通过全卷积和反卷积最后得到一个28x 28 x80 的mask,要注意这里的80个通道指分类的类别数为80,后面我们也会通过损失函数来详细说明

至此,从R-CNN到Mask R-CNN的演变之路就讲完了,下面我们讲一下MaskR-CNN的一些细节。

ROIAlign

首先是ROIAlign,我们知道之前的网络对ROI wrap到固定的尺寸都是使用的ROI Pooling,那么这样做有什么缺点呢?这里我们通过一组图来说明

image-20201219212431878

image-20201219215855556

可以看出,原本的original ROI 最后变成2x2的ROI一共经历了两次取整的操作,存在误差,会影响bounding box的位置准备度

  • 第一次取整: regional ROI可能是浮点数,首先是取整,将ROI和feature map 对齐
  • 第二次取整:regional ROI 可能不能被最后的2x 2整除,比如原本的ROI尺寸是5x4,那么如图,最终分成的2x2ROI并不是每一块都是一样大的,进行了不均等的切分。

这两次取整操作,对于大目标来说还好,但是小目标的包围框坐标对这样的误差还是很敏感的,为了解决这个问题,ROIAlign出现了,下面是结构图

image-20201219213447848

  • 针对第一次取整,这里图画的本来就是和feature map对准的,其实不是对准的也没关系,ROI Align保留这里的浮点数,不做取整操作
  • 针对第二次取整,我们可以看到7x5的ROI被平均的分成了四份,针对每一小份又使用了4个采样点对这块区域进行采样,那么是如何采样的呢?首先4个采样点就是把这一小份平均分成四份,每一小份的值由双线性插值方法获得。因此每一小份最终可以由4份得到,在对这样的特征图进行MaxPooling , 最终得到2x2的ROI,这里为什么用4个采样点呢,其实用1个也是可以的,作者在实验中证明4个采样点的效果最好。
  • 双线性插值我们可以从图中直观地看到,其实就是做了三次线性插值

Loss function

Mask R-CNN的损失函数有些特殊,我们来看一下公式

image-20201219212439319

其中的Lmask 就是Mask branch的损失,这个mask就是指每个像素是0还是1,用来区分背景,做分割

image-20201219220637393

这个7x7的mask,其中每一个像素都有80个通道,每一个通道都对应一个类别,通常 对于实例分割来说,都是使用softmax做分类,得出这80个类别分别的概率,然后再去区别是目标还是背景,因此需要做两个任务,一个是类别预测,一个是mask预测.

而Mask RCNN是怎么做的呢,它不做类别预测,只做mask预测,通过其他分支的类别预测选择对应的80个通道中一个,比如是狗,那么只要对这7x7个像素预测,这个像素是目标狗还是背景,输出一个0或1的二值mask,因此只做了一个任务mask预测

相比之前的softmax方法,有两个优势

  • 避免了类间竞争,使得性能提高
  • 类别预测和mask预测分开来做,解耦

Application

Instance segmentation

image-20201219224118913

Human pose estimation

image-20201219224141806