Faster R-CNN中Anchor机制的理解
Anchor的本质
RPN回归层是9个单独的回归层,9个box不共享权重,每个回归器负责一个尺度和长宽比,一个回归器对应一个Anchor
什么是Anchor?
Anchor在在特征图上抽取映射回原图计算IOU,以在特征图上滑动窗口,将当前滑动窗口的中心映射到原图的一个区域,以这个区域中心对应不同的Scale和高宽比,获得多个Anchor Box。
以3x3滑动窗口对应原图的位置为中心点,在原图生成9个不同尺度,长宽比的Anchor,每个Anchor都会被分配到对应的类标签(正样本1,负样本0,不参与not used)
为什么提出Anchor Box?
主要有两个原因:
一个窗口只能检测一个目标
无法解决多尺度问题
Anchor Box的选择方式?
- 人为经验选取
- K-means聚类
- 作为超参数进行学习
Anchor的本质是SPP(spatial pyramid pooling)思想的逆向。而SPP本身所做的事就是将不同尺寸的输入resize成为相同尺寸的输出。所以SPP的逆向就是:将相同尺寸的输出,倒推得到不同尺寸的输入。(这个思想是否正确有待商榷????)
Anchor Box的产生
原始图片经过一系列卷积层和池化层以及Relu,得到了这里的 feature:51x39x256(256是层数);在这个特征参数的基础上,使用一个3x3的滑动窗口,在这个51x39的区域上进行滑动(stride=1,padding=2),滑动之后得到51x39个3x3的窗口。
对于每个3x3的窗口,作者就计算这个滑动窗口的中心点所对应的原始图片的中心点。
然后作者假定,这个3x3窗口,是从原始图片上通过SPP池化得到的,而这个池化的区域的面积以及比例,就是一个个的anchor 。换句话说,对于每个3x3窗口,作者假定它来自9种不同原始区域的池化,但是这些池化在原始图片中的中心点,都完全一样。这个中心点,就是刚才提到的池化后的3x3窗口在原始图片中的中心点(3x3窗口中心点所对应的原始图片中的中心点)。
这样,在每个窗口位置,我们都可以根据9个不同长宽比例、不同面积的anchor,逆向推导出它所对应的原始图片中的一个区域,这个区域的尺寸以及坐标,都是已知的。而这个区域,就是我们想要的 proposal。所以我们通过滑动窗口和anchor,成功得到了 51x39x9 个原始图片的proposal。
明确: Anchor是在原图上的区域而不是在特征图上
为什么在特征图上滑动的3x3区域,映射回原图,能得到anchors?这个是基于什么机制?基于SPPnet机制;在SPPnet中,一张原图经过一系列卷积,得到feature map,原图上每个Region Proposal,就可以在这个feature map中找到一个区域,当然这时的区域不一定是2维的,比如773,是77大小区域3通道,然后根据下面图中的机制,把任何大小区域都池化到固定维数。
所以反过来看。上面RPN网络中的feature map中的3x3区域,就可以看成是经过SPPnet机制池化后得到的固定维数区域。这里是假想有这么一个SPPnet模块的作用(即上图中虚线的表示),其实Faster-R-CNN没有这样一个模块。所以原图上,相同中心,不同比例和面积的anchor,经过这样一个假想机制,确实都可以池化成33的区域。假想过程:每个anchor经过一系列卷积,得到feature map,这个feature map经过spp机制池化得到了33n通道维度的特征图。这里的anchors不就相当于SPPnet中原图上的Region Proposals。
参考链接:[https://blog.****.net/tigerda/article/details/86736811](https://blog.****.net/tigerda/article/details/86736811)
https://blog.****.net/as472780551/article/details/81227408
为什么在原图上生成Anchor?
要知道,训练RPN网络是有监督训练,需要有数据、还要有相应的类标签,输入小网络的是512个通道的33滑窗,类标签没有给定,没有类标签就无法计算Loss损失函数,无法训练网络。以33滑窗中心对应原图的位置作为中心点,在原图生成9个不同尺度长宽比的anchor,然后每个anchor都会被分配到相应的类标签,有正样本(1)、负样本(0),也有不参与训练的框(not used),对正样本计算 ,就是回归的类标签,负样本不计算回归loss。0,1是二分类的标签。所以在原图生成anchor的目的之一是得到类标签。这里只得到了分类的标签(0,1),还有正样本的回归标签需要确定,该正样本的回归标签是其对应的ground truth计算出来的t*x, t*y,t*w,t*h。负样本不计算回归损失没有回归标签。
参考地址:https://www.zhihu.com/question/42205480/answer/525212289
RPN网络的处理流程
①经过VGG16卷积生成feature map,576x960——(缩放16倍)——》36x60x512(512个channel)
②使用Sliding window在feature map上滑动,找到每个滑动窗口的中心在原图对应的像素位置,以不同的Scale和宽高比在原图上生成9个Anchor。9个Anchor中心重合且和三维滑动窗口对应的中心一样
3x3x512滑窗(stride=1,padding=2),共有36x60个滑窗,总计36x60x9个原图上的Anchor。
③生成Anchor的同时根据与ground truth的IOU值确定每个Anchor是正样本还是负样本;
为两种Anchor分配正样本:①和一个ground truth的IOU值最大的那些Anchor;②和任意一个ground truth IOU > = 0.7的Anchor
负样本:与ground truth IOU < 0.3
其它的不作为训练样本,忽略。
然后对每个正样本anchor对应的ground truth,打上回归标签,交给Anchor对应的回归器预测
Anchor生成好以后,回归器对应的正样本回归标签t*x,t*y,t*w,t*h
④一张图片随机采样256个Anchor,正负样本比例为1:1,正样本少于128个减少负样本Anchor数量,和正样本Anchor数量相同,这256个Anchor来自不同的3x3sliding window
解决输入不是固定size的问题
- Resize输入成固定大小的input
- 替换FC,对最后的卷积使用global average pooling
- SPP layer:
使用不同的size和stride,对全连接层前的卷积层进行不同池化大小的pooling,然后拼接,最终输出一定是(p1p1+p2p2+……)*channels
从卷积层获得feature map将其分成1x1,2x2,4x4……的小块,接着在每个小块上做max pooling,这样最后得到的结果也就是固定大小的向量
举例:feature map 32x32x256,把每一个32x32的feature map都分成1x1、2x2、4x4的小块,可得到长度为(1+4+16=21)的一维向量,256个feature map串联在一起就得到长度为21x256的一维向量