下面会介绍基于ResNet50的Mask RCNN网络,其中会涉及到RPN、FPN、ROIAlign以及分类、回归使用的损失函数等
介绍时所采用的MaskRCNN源码(python版本)来源于GitHub:https://github.com/matterport/Mask_RCNN
下面的介绍都是基于这部分源码进行的(少数地方会和原始论文中有差别,不过不影响整个网络的理解)
一)、整体框架结构
通过对代码的理解,重新绘制出一张MASKRCNN的整体架构图
二)、分解各个节点
1)ResNet50网络简单介绍
ResNet50网络主要用来提取图片的特征。
MASKRCNN网络虽然对于输入图片的大小没有要求,但是在代码中存在IMAGE_MIN_DIM和IMAGE_MAX_DIM两个参数的定义,会将图片统一成设定的大小。设定的规则这里主要介绍两种常用的方式:
①‘squre’:先将图片较短边按照IMAGE_MIN_DIM进行等比例缩放,再将图片以零像素填充到IMAGE_MAX_DIM大小
②‘crop’:同样,先将图片较短边按照IMAGE_MIN_DIM进行等比例缩放,再从图片中随机剪裁一个IMAGE_MIN_DIM大小的子图片作为输入图片
这里,基于‘squre’这种方式介绍,即将参数IMAGE_MAX_DIM设定为1024,因此,网络的输入图片大小就是1024*1024
ResNet50网络比较简单,主要包括卷积、BN、RELU三步提取特征的操作,其中:
①C1:256*256*64表示特征图的大小为256*256,特征图的个数是64个
②C2:256*256*256表示特征图的大小为256*256,共有256个特征图
③C3:128*128*512表示特征图的大小为128*128,共有512个特征图
④C4:64*64*1024表示特征图的大小为64*64,共有1024个特征图
⑤C5:32*32*2048表示特征图的大小为32*32,共有2048个特征图
C1和C2的特征图大小是一样的,所以,FPN的建立也是基于从C2到C5这四个特征层上。
2)FPN网络的建立
通过ResNet50网络,得到图片不同阶段的特征图,利用C2,C3,C4,C5建立特征图金字塔结构
①将C5经过256个1*1的卷积核操作得到:32*32*256,记为P5
②将P5进行步长为2的上采样得到64*64*256,再与C4经过的256个1*1卷积核操作得到的结果相加,得到64*64*256,记为P4
③将P4进行步长为2的上采样得到128*128*256,再与C3经过的256个1*1卷积核操作得到的结果相加,得到128*128*256,记为P3
④将P3进行步长为2的上采样得到256*256*256,再与C2经过的256个1*1卷积核操作得到的结果相加,得到256*256*256,记为P2
⑤将P5进行步长为2的最大池化操作得到:16*16*256,记为P6
结合从P2到P6特征图的大小,如果原图大小1024*1024,那各个特征图对应到原图的步长依次为[P2,P3,P4,P5,P6]=>[4,8,16,32,64]
3)Anchor锚框生成规则
基于上一步得到的特征图[P2,P3,P4,P5,P6],介绍下MASKRCNN网络中Anchor锚框的生成,根据源码中介绍的规则,与之前的Faster-RCNN中的生成规则有一点差别。
①遍历P2到P6这五个特征层,以每个特征图上的每个像素点都生成Anchor锚框
②以P2层为例,P2层的特征图大小为256*256,相对于原图的步长为4,这样P2上的每个像素点都可以生成一个基于坐标数组[0,0,3,3]即4*4面积为16大小的Anchor锚框,当然,可以设置一个比例SCALE,将这个基础的锚框放大或者缩小,比如,这里设置P2层对应的缩放比例为16,那边生成的锚框大小就是长和宽都扩大16倍,从4*4变成64*64,面积从16变成4096,当然在保证面积不变的前提下,长宽比可以变换为32*128、64*64或128*32,这样以长、宽比率RATIO=[0.5,1,2]完成了三种变换,这样一个像素点都可以生成3个Anchor锚框。在Faster-RCNN中可以将SCALE也可以设置为多个值,而在MASKRCNN中则是每一特征层只对应着一个SCALE即对应着上述所设置的16。
③以P2层每个像素点位中心,对应到原图上,则可生成256*256*3(长宽三种变换)=196608个锚框
④以P3层每个像素点为中心,对应到原图上,则可生成128*128*3=49152个锚框
⑤以P4层每个像素点为中心,对应到原图上,则可生成64*64*3=12288个锚框
⑥以P5层每个像素点为中心,对应到原图上,则生成32*32*3=3072个锚框
⑦以P6层每个像素点为中心,对应到原图上,则生成16*16*3=768个锚框
从P2到P6层一共可以在原图上生成261888个Anchor锚框
4)生成RPN网络数据集
在上一步已经生成了26188个Anchor锚框,需要借助这些Anchors建立RPN网络训练时的正类和负类,
假设需要的正样本与负样本共计256个Anchor,即RPN_TRAIN_ANCHORS_PER_IMAGE这个参数所指定。源码中这步操作由以下几方面构成:
①先找到所有真实框中那些同时框住了多个物体的框,并排除掉
②计算每个Anchors与该图片上标注的真实框ground truth之间的IOU
如果anchor box与ground truth的IoU值最大,标记为正样本,label=1
如果anchor box与ground truth的IoU>0.7,标记为正样本,label=1
如果anchor box与ground truth的IoU<0.3,标记为负样本,label=-1
剩下的既不是正样本也不是负样本,不用于最终训练,label=0
同时,保证正样本为128个,负样本为128个
除了对anchor box进行标记外,另一件事情就是计算anchor box与ground truth之间的偏移量
令:
ground truth:标定的框也对应一个中心点位置坐标x*,y*和宽高w*,h*
anchor box:中心点位置坐标x_a,y_a和宽高w_a,h_a
所以,偏移量:
△x=(x*-x_a)/w_a △y=(y*-y_a)/h_a
△w=log(w*/w_a) △h=log(h*/h_a)
什么是IoU:
这样,经过这一步,共找到128个Anchor作为正样本和128个Anchor作为负样本, 同时,保存了这256个Anchor与真实框ground truth之间的偏移量
5)RPN网络的分类与回归
①前向传播计算分类得分(概率)和坐标点偏移量
RPN网络在分类和回归的时候,分别将每一层的每一个Anchor分为背景和前景两类,以及回归四个位移量,比如P2层,特征图大小为256*256,即像素点有256*256个,每个像素点有三种长宽比例变换,一共有256*256*3个Anchor,如果是分类则需要分别计算每个Anchor为前景的得分(概率)或为背景的得分(概率),其数组可定义为[256*256*3,2],相应的如果是偏移量的回归则数组对应着形式为[256*256*3,4]
将从P2到P6的所有层进行同样的分类和回归操作,一共得到[261888,2]的分类信息和[261888,4]的回归信息。
②计算RPN网络损失值反向传播更新权重
在‘生成RPN网络数据集’这一步,在261888个Anchors中获得了256个正负样本且与真实框的偏移量。
分类:
从前向传播计算得到的所有Anchors得分数组中即上面所述的[261888,2]数组中找到这256个正样本和负样本所对应的得分,利用得分与正负样本的标签计算交叉熵损失值。
RPN分类使用的是基于Softmax函数的交叉熵损失函数,Softmax函数只要是将前向传播计算的得分归一化到0~1之间的概率值,同时,经过Softmax函数后,也可以保证各个分类的概率不会出现负数
Softmax函数公式:
其中,表示类别j经过网络前向传播计算出来的得分,表示类别j经过Softmax函数后换算得到的概率
基于Softmax的交叉熵公式:
其中,表示的是真实标签,表示概率,下面用代替来表示概率,看下L的求导结果:
因此假设一个5分类任务,一张图像经过Softmax层后得到的概率向量p是[0.1,0.2,0.25,0.4,0.05],真实标签y是[0,0,1,0,0],那么损失回传时该层得到的梯度就是p-y=[0.1,0.2,-0.75,0.4,0.05]。这个梯度就指导网络在下一次forward的时候更新该层的权重参数
回归:
从前向传播计算得到的所有Anchors偏移量数组中即上面所述的[261888,4]数组中找到这128个正样本所在索引对应的偏移量,利用此前向传播计算得到的偏移量与正样本与真实框之间计算的偏移量计算损失值,使用的是SmoothL1Loss
SmoothL1函数:
对应的损失函数:
其中,, ,
分别表示由前向传播计算的预测框的坐标值,Anchor锚框对应的坐标值,真实框对应的坐标值
SmoothL1函数的求导:
将预测框与真实框偏移量之间的差值带入上述公式后可得到损失函数求导后的结果,用此更新权重实现反向传播
6)根据RPN调整生成ROI
这一部分对应着总网络图中的ProposalLayer层,取出一定量的Anchors作为ROI,这个量由源码中参数POST_NMS_ROIS_TRAINING确定,假设这个参数在训练的时候设置为2000,则我们这里需要从261888个Anchors中取出2000个作为ROI
首先,按照Anchors经过RPN网络前向传播计算得出的前景(或称为正样本)的得分从高到低排序,取出前2000个得分最高的Anchors,相对应的将2000个Anchors经RPN网络前向传播计算出的偏移量累加到Anchor box上得到较为准确的box坐标。
其中,红色的A框是生成的anchor box,而蓝色的G’框就是经过RPN网络训练后得到的较精确的预测框,绿色的G是ground truth box
最后在返回前,对2000个框再进行一次非最大值抑制NMS操作
用下图一个案例来对NMS算法进行简单介绍
如上图所示,一共有6个识别为人的框,每一个框有一个置信率。
现在需要消除多余的:
- 按置信率排序: 0.95, 0.9, 0.9, 0.8, 0.7, 0.7
- 取最大0.95的框为一个物体框
- 剩余5个框中,去掉与0.95框重叠率IoU大于0.6(可以另行设置),则保留0.9, 0.8, 0.7三个框
- 重复上面的步骤,直到没有框了,0.9为一个框
- 选出来的为: 0.95, 0.9
进行非最大值抑制的目的主要是需要剔除掉重复的框,如果经过非最大值抑制操作后得到的ROI没有事先代码中设定的2000个,则用0填充。
7)生成RCNN网络数据集
这一部分对应着总网络图中的DetectionTargetLayer层
在经过ProposalLayer层之后得到了2000个经过微调后的ROI,而在DetectionTargetLayer需要对2000个ROI做以下几步:
①首先剔除掉2000个ROI中不符合条件的ROI,主要是在ProposalLayer层最后返回的时候如果不足2000个会用0填充凑足,将这些用0填充的全部排除掉,避免参与不必要的计算
②DetectionTargetLayer中会用到图片中的真实框信息,所以,在使用之前同样将所有真实框中那些同时框住了多个物体的框,并排除掉
③计算每个ROI与真实框之间的IOU值
如果ROI与ground truth的IoU>0.5,标记为正样本
如果ROI与ground truth的IoU<0.5,标记为负样本
假定正样本个数只保留到100个,而负样本一般保持是正样本数的3倍,正负样本总数则就可以达到400个,这个400可有配置文件中TRAIN_ROIS_PER_IMAGE参数确定
④对于每个正样本,进一步计算与其相交最大即最接近的真实框ground truth box,将这个真实框所对应的类别即class_id赋予这个正样本,这样RCNN网络就可以区分具体哪个类别
⑤同样,计算每个正样本ROI与最接近的真实框ground truth box之间的偏移量,这RPN中的计算公式一样
⑥RCNN网络还需要保存与每个正样本ROI最接近的真实框ground truth box的mask掩码信息,并且知道每个mask大小为参数MASK_SHAPE所指定,一般为28*28,同时知道其所属于的类别即class_id,进行保存
最后DetectionTargetLayer层返回400个正、负样本,400个位移偏移量(其中300个由0填充),400个掩码mask信息(其中300个由0填充)
8)ROI 对齐操作
通过DetectionTargetLayer层,在原图上找到400个ROI,因为这些ROI可能是有各个特征层产生的Anchor,所以,现在需要将这些ROI映射回特征图上
第一步,我们需要知道每个ROI如何和特征层对应上,论文中提到的方法是利用下面的公式:
对于公式而言:w,h分别表示ROI宽度和高度;k是这个RoI应属于的特征层level;是w,h=224,224时映射的level,一般取为4,即对应着P4,至于为什么使用224,一般解释为是因为这是ImageNet的标准图片大小,比如现在有一个ROI是112*112,则利用公式可以计算得到k=3,即P3层
第二步,开始讨论对齐的方式
当完成每个ROI能找到其对应的特征层后,就同样可以算出其对应的步长,步长只要用于解释ROI Align的原理,论文中提到的ROI Align,这个方法的思路:
①使用每个ROI的长、宽除以步长,得到ROI映射到特征图上的图片大小,比如ROI为113*113,对应P3层,步长为8,则在特征图上的感兴趣区域则为14.13*14.13
②如果要将特征图上的感兴趣区域对齐到7*7,则需要将14.13*14.13这个区域分成49份,每一份的大小为:2.02*2.02
③再将每个2.02*2.02的小区域,平分四份,每一份取其中心点位置,而中心点位置的像素,采用双线性插值法进行计算,这样,就会得到四个点的像素值,取四个像素值中最大值作为这个小区域(即:2.02*2.02大小的区域)的像素值,如此类推,同样是49个小区域得到49个像素值,组成7*7大小的feature map
以上介绍的是论文中的ROI Align方法,但是在这篇博文开头提供的代码链接中的源码并不是这样处理的。对于ROI映射到特征图上的方法是一样的,但当每个ROI找到对应的特征层厚,直接利用Crop and Resize操作,生成7*7大小的feature map
Mask掩码分支则是对齐成14*14大小的feature map
9)RCNN网络的类别分类、回归、mask掩码分类
①RCNN网络的类别分类和回归与RPN网络中的分类和回归是一样的,损失函数也都是基于Softmax交叉熵和SmoothL1Loss,只是RPN网络中只分前景(正类)、背景(负类),而RCNN网络中的分类是要具体到某个类别(多类别分类)
②mask掩码分类
在ROI 对齐操作中mask分支对齐成14*14大小的feature map,并且在‘生成RCNN网络数据集’操作中知道每个正样本mask掩码区域对应的class_id
i) 前向传播:将14*14大小feature map通过反卷积变换为[28*28*num_class],即每个类别对应一个mask区域,称之为预测mask
ii) 与‘生成RCNN网络数据集’操作中的返回的mask也是28*28,并且知道每个mask区域的真实类别class_id,称之为真实mask
iii) 通过当前得到的真实mask中的类别class_id,遍历所有的预测mask,找到class_id类别所对应的预测mask(前向传播中介绍过每个类别都有一个预测mask),比较真实mask与预测mask每个像素点信息,用的是binary_cross_entropy二分类交叉熵损失函数
iv) binary_cross_entropy是二分类的交叉熵,实际是多分类softmax_cross_entropy的一种特殊情况,当多分类中,类别只有两类时,即0或者1,因为28*28大小的mask中只有0和1,即是像素和不是像素
这个是针对概率之间的损失函数,你会发现只有(预测概率)和(真实标签)是相等时,loss才为0,否则loss就是为一个正数。而且,概率相差越大,loss就越大,根据Loss值更改权重实现反向传播
作为一枚技术小白,写这篇笔记的时候参考了很多博客论文,在这里表示感谢,同时,未经同意,请勿转载....