3.3. 分类和定位
faster r-cnn中的roi pooling layer与 fast r-cnn中原理一样。在roi pooling layer之后,就是faster r-cnn的分类器和roi边框修正训练。分类器主要是分这个提取的roi具体是什么类别(人,车,马等),一共c 1类(包含一类背景)。roi边框修正和rpn中的anchor边框修正原理一样,同样也是smoothl1 loss,值得注意的是,roi边框修正也是对于非背景的roi进行修正,对于类别标签为背景的roi,则不进行roi边框修正的参数训练。对于分类器和roi边框修正的训练,可以损失函数描述如下:
上式中u>=1表示roi边框修正是对于非背景的roi而言的,实验中,上式的λ取1。在训练分类器和roi边框修正时,步骤如下所示:1) 首先通过rpn生成约20000个anchor(40×60×9)。 2) 对20000个anchor进行第一次边框修正,得到修订边框后的proposal。 3) 对超过图像边界的proposal的边进行clip,使得该proposal不超过图像范围。 4) 忽略掉长或者宽太小的proposal。 5) 将所有proposal按照前景分数从高到低排序,选取前12000个proposal。 6) 使用阈值为0.7的nms算法排除掉重叠的proposal。 7) 针对上一步剩下的proposal,选取前2000个proposal进行分类和第二次边框修正。 总的来说,faster r-cnn的loss分两大块,第一大块是训练rpn的loss(包含一个softmaxloss和smoothl1loss),第二大块是训练faster r-cnn中分类器的loss(包含一个softmaxloss和smoothl1loss),faster r-cnn的总的loss函数描述如下:
4. mask r-cnn
mask r-cnn可以分解为如下的3个模块:faster-rcnn、roi align和mask。算法框架如下:
图6 mask r-cnn算法框架
算法步骤:
首先,输入一幅你想处理的图片,然后进行对应的预处理操作,或者预处理后的图片;
然后,将其输入到一个预训练好的神经网络中(resnext等)获得对应的feature map;
接着,对这个feature map中的每一点设定预定个的roi,从而获得多个候选roi;
接着,将这些候选的roi送入rpn网络进行二值分类(前景或背景)和bb回归,过滤掉一部分候选的roi;
接着,对这些剩下的roi进行roialign操作(即先将原图和feature map的pixel对应起来,然后将feature map和固定的feature对应起来);
最后,对这些roi进行分类(n类别分类)、bb回归和mask生成(在每一个roi里面进行fcn操作)。 mask r-cnn是一个非常灵活的框架,可以增加不同的分支完成不同的任务,可以完成目标分类、目标检测、语义分割、实例分割、人体姿势识别等多种任务,如下图所示。
4.1. roi align
mask r-cnn使用roialign取代了faster rcnn中的roipooling,故下文对roipooling和roialign进行分析与比较
如上图所示,roi pooling和roialign最大的区别是:前者使用了两次量化操作,而后者并没有采用量化操作,使用了线性插值算法,具体的解释如下所示。
roi pooling
如上图所示,为了得到固定大小(7x7)的feature map,我们需要做两次量化操作:1)图像坐标 — feature map坐标,2)feature map坐标 — roi feature坐标。我们来说一下具体的细节,如图我们输入的是一张800x800的图像,在图像中有两个目标(猫和狗),狗的bb大小为665x665,经过vgg16网络后,我们可以获得对应的feature map,如果我们对卷积层进行padding操作,我们的图片经过卷积层后保持原来的大小,但是由于池化层的存在,我们最终获得feature map 会比原图缩小一定的比例,这和pooling层的个数和大小有关。在该vgg16中,我们使用了5个池化操作,每个池化操作都是2x2pooling,因此我们最终获得feature map的大小为800/32 x 800/32 = 25x25(是整数),但是将狗的bb对应到feature map上面,我们得到的结果是665/32 x 665/32 = 20.78 x 20.78,结果是浮点数,含有小数,但是我们的像素值可没有小数,那么作者就对其进行了量化操作(即取整操作),即其结果变为20 x 20,在这里引入了第一次的量化误差;然而我们的feature map中有不同大小的roi,但是我们后面的网络却要求我们有固定的输入,因此,我们需要将不同大小的roi转化为固定的roi feature,在这里使用的是7x7的roi feature,那么我们需要将20 x 20的roi映射成7 x 7的roi feature,其结果是 20 /7 x 20/7 = 2.86 x 2.86,同样是浮点数,含有小数点,我们采取同样的操作对其进行取整吧,在这里引入了第二次量化误差。其实,这里引入的误差会导致图像中的像素和特征中的像素的偏差,即将feature空间的roi对应到原图上面会出现很大的偏差。原因如下:比如用我们第二次引入的误差来分析,本来是2,86,我们将其量化为2,这期间引入了0.86的误差,看起来是一个很小的误差呀,但是你要记得这是在feature空间,我们的feature空间和图像空间是有比例关系的,在这里是1:32,那么对应到原图上面的差距就是0.86 x 32 = 27.52。这个差距不小吧,这还是仅仅考虑了第二次的量化误差。这会大大影响整个检测算法的性能,因此是一个严重的问题。
roialign
如上图所示,为了得到为了得到固定大小(7x7)的feature map,roialign技术并没有使用量化操作,即我们不想引入量化误差,比如665 / 32 = 20.78,我们就用20.78,不用什么20来替代它,比如20.78 / 7 = 2.97,我们就用2.97,而不用2来代替它。这就是roialign的初衷。那么我们如何处理这些浮点数呢,我们的解决思路是使用“双线性插值”算法。双线性插值是一种比较好的图像缩放算法,它充分的利用了原图中虚拟点(比如20.56这个浮点数,像素位置都是整数值,没有浮点值)四周的四个真实存在的像素值来共同决定目标图中的一个像素值,即可以将20.56这个虚拟的位置点对应的像素值估计出来。如下图所示,蓝色的虚线框表示卷积后获得的feature map,黑色实线框表示roi feature,最后需要输出的大小是2x2,那么我们就利用双线性插值来估计这些蓝点(虚拟坐标点,又称双线性插值的网格点)处所对应的像素值,最后得到相应的输出。这些蓝点是2x2cell中的随机采样的普通点,作者指出,这些采样点的个数和位置不会对性能产生很大的影响,你也可以用其它的方法获得。然后在每一个橘红色的区域里面进行max pooling或者average pooling操作,获得最终2x2的输出结果。我们的整个过程中没有用到量化操作,没有引入误差,即原图中的像素和feature map中的像素是完全对齐的,没有偏差,这不仅会提高检测的精度,同时也会有利于实例分割。
下一篇:父母“婴语”好 孩子更健谈