写在前面
常见计算机视觉的任务:
- 图像分类(image classification)
- 物体检测(object detection)
- 语义分割(Semantic Segmentation)
- 实例分割(Instance Segmentation)
图像分类就不做介绍了,就是输入一张图,输出该图的类别标签,可以是单个类别的也可以是多个类别的。
物体检测,前面介绍的RCNN,Fast RCNN,Faster RCNN都是属于物体检测,它需要你得到一个物体的位置并用一个框,框住该物体,同时还要给框内的物体打上类别标签.简而言之就是分类+定位。
语义分割,FCN就是属于语义分割,主要是通过给图上的每个像素打上标签归为一类.语义分割看上去和实例分割很像,但还是有一些区别的,在语义分割中同类物体的颜色是一样的,而不同类的物体的颜色是不同的,而实例分割则是即使同类,但是不同的实例仍是不同颜色的
下图的例子就能说明语义分割和实例分割的区别
而下面要介绍的Mask-RCNN,要实现的是object detection+classification+instance segmentation
显然这与我们之前介绍的RCNN系列有一些不同,即instance segmentation.
回顾:RCNN->Fast RCNN->Faster RCNN
RCNN
- 通过selective search找到一些region proposal
- 对这些region proposals warp 到固定大小
- 通过CNN,先分类后回归
Fast RCNN
- 先通过一个CNN提取特征
- 依然采用selective search,但是在feature map上做
- 用ROI pooling 代替原来的warp操作,缩放到固定大小
- 后用2个全连接层,一个分类+一个回归,Loss用multi-task形式,同时训练分类和回归
Faster RCNN
- 先通过CNN提取特征
- 用一个需要训练的RPN代替原来的Selective Search操作
- 继承Fast RCNN运用ROI pooling的操作
- 后用2个全连接层,一个分类+一个回归,Loss用multi-tasj形式,同时训练分类和回归
Mask RCNN
overview
从上图可以粗略地看出,Mask RCNN也只是在Faster RCNN上进行进一步的修改.
不同点:
- ROI pooling 替换成了ROIAlign layer
新增加了一个分支mask branch
细节
ROIAlign
下图可以显示ROIPooling与ROIAlign的区别
简单来说:我们这里得到了一个框,但它的长宽与我们指定的长宽不同,所以需要将这个框先分割成我们指定长宽个bin.上面这步对于ROI Pooling和ROI Align都是一样的,不同的是对于ROI pooling 来说,它要进行一个量化操作,调整bin的分割,这里的量化操作可以理解为取整.然后再Pooling.而ROIAlign不进行量化操作,而是用双线性内插的方法然后再用Pooling.ROI Pooling
引用何凯明演讲用的图片:
在从原图到特征图上时会进行一次量化
ROI pooling时会进行一次量化
这两次量化都会使框产生一定的偏倚.
ROI Pooling反向传播:
这里$x_i$代表池化前特征图上的像素点;$y_{rj}$代表池化后的第r个候选区的第j个点,$i^ (r,j)$代表点$y_{rj}$像素值的来源(最大池化的时候选出的最大像素值所在的坐标).由上式可以看出,只有当池化后某一个点的像素值在池化过程中采用了当前点$x_i$(即满足i=$i^ (r,j)$,才在$x_i$处回传梯度)
- ROI Align
引用何凯明演讲用的图片:
原图上的坐标映射到特征图上时不进行量化(不取整,保持float形式)
特征图进行Pooling,同样也不进行量化
ROI Align的反向传播
类比于ROI Pooling,ROIAlign的反向传播需要作出稍许修改:首先,在ROIAlign中,$x^ (r,j)$是一个浮点数的坐标位置,在池化前的特征图中,每一个与$x^\ (r,j)$横纵坐标均小于1的点都应该接收与此对应的点$y_{rj}$的回传的梯度,故ROI Align的反向传播公式如下:
上式,d(.)表示两点之间的距离,$\Delta h$和$\Delta w$表示$x_i$与$x_i^* (r,j)$横纵坐标的差值,这里作为双线性内插的系数乘在原始的梯度上.
为什么要将原来的ROI Pooling替换为ROI Align
我的理解是:现在的任务不再仅仅是原来Faster RCNN那种物体检测的粗略的任务,而是变为了需要实例分割(instance segmentation).实例分割需要给每个像素进行分类,因此其的精度要求比较高,而用ROI Pooling会在量化时造成一定的偏倚,从而导致misalignment的问题.值得一提的是,在做实验的时候发现,ROI Align在VOC2007数据集上提升效果并不如在COCO上明显.经过分析,造成这种区别的原因是COCO上小目标的数量更多,而小目标对misalignment问题的影响更为明显(比如,同样是0.5像素点的偏差,对于较大的目标而言显得微不足道,但是对于小目标,误差的影响就高很多)
附上双线性内插的内容:
Mask分支
除了将ROIPooling改为了ROI Align以外,Mask RCNN还增加了一个Mask 分支,很显然其作用就是为了实现它的实例分割.
Mask分支通过在ROI Align层后吐出的ROI特征上接上一个FCN,最终得到一个与ROI区域相对应的mask map出来(形式为:K×m×m,其中m表示ROI Align特征图的大小).这个mask map有K个channel.K在这里表示目标可能的类别数目.另外每个channel的mask map上面都是些二元信息,分别表示ROI区域上面的某位置点是前景还是背景(是否为该类别).这里采样二元信息的目的就是为了实现类间无竞争.(Softmax就会导致类间竞争此消彼长)
这里沿用FCN的特点,不以向量的形式输出是为了避免丢失空间信息,有效保留空间信息.
损失函数
MaskRCNN沿用之前的Multi-task loss的形式:由于新增了一个Mask分支,网络所使用的损失函数为:
其中$L_{cls}+L_{box}$与Faster RCNN中的一样,并且它们与新增的Mask 分支是独立的.
至于$L_{mask}$,我们知道 mask 分支输出的是一个K×m×m的形式.$L_{mask}$是对每一个像素使用二值的sigmoid交叉损失.
注意:这里Loss是只对groud-truth k层上得m×m个像素计算所有点得交叉熵,并求平均[For an Roi associated with ground-truth class k, LmaskLmask is only defined on the k-th mask(other mask outputs do not contributed to the loss)]
其他细节
在Mask RCNN的overview里我们看到,最一开始的特征提取层被称为backbone,也可以叫他共享基础网络.
文中尝试了多种基础网络:
- ResNet
- ResNeXt
- FPN(Feature Pyramid Network)
- RseNet+FPN
最终发现,ResNet+FPN的效果最好
目标检测正负样本的问题
正负样本的问题在目标检测任务中是普遍存在的,只不过之前没有重视到,这里再理解一遍.
我们拿到一张训练数据的图,图上的各个物体都是包含一个框的(称为ground truth).就一个物体一个框而言,只有ground truth的才为正例其他情况都为负例,这会导致正负样例不平衡的问题,所以需要我们生成一些正负样本,并平衡它们.这些正负样本就是为了我们更好的训练.例如在RCNN中,用Selective Search会找到一系列的proposal region,我们会将它们与ground truth做IOU操作,将一部分选为正样本,一部分选为负样本.最终重要的是还会进行正负样本的平衡,从上述分得的正负样本中选取出合适比例的样本参与训练.(对于Faster RCNN正负样本就是哪些anchor box)