传统的目标检测算法:
使用穷举法(不同大小比例的滑窗)进行区域选择,时间复杂度高
对提取的区域进行特征提取(HOG或者SIFT),对光照、背景等鲁棒性差
使用分类器对提取的特征进行分类(SVM或Adaboost)
R-CNN的过程:
采用Selective Search生成类别独立的候选区域
使用AlexNet来提取特征,输入是227*227*3,输出是4096
将4096维的特征向量送入SVM来分类
生成候选区域:选择性搜索
相似度计算时采用颜色、纹理、尺寸和空间交叠四种相似度的加权和
提取特征向量:
由于使用AlexNet的输入为227*227,所以文中将第一步得到的候选框强制统一到同样尺度,在统一前,相对候选区域进行膨胀处理,在区域周围添加P=16像素
特征分类:
训练时,使用迁移学习,在 ImageNet 上先进行预训练,然后利用成熟的权重参数在 PASCAL VOC 数据集上进行 fine-tune,使用SGD
测试时,第一步会产生2000多个候选区域,先将这些区域统一尺度,然后送到CNN里提取特征,然后送入SVM计算分数,由于2000多个区域会重叠,针对每个类别,采用NMS剔除重叠区域
空间金字塔池化:在ssp-net之前,传统cnn之所以要固定输入,是因为全连接层的存在
当网络输入的是一张任意大小的图片,这个时候我们可以一直进行卷积、池化,直到网络的倒数几层的时候,也就是我们即将与全连接层连接的时候,就要使用金字塔池化,使得任意大小的特征图都能够转换成固定大小的特征向量
相对于RCNN对每个候选框送入CNN,SPP只对原图进行一次卷积计算,便得到整张图的卷积特征feature map,然后找到每个候选框在feature map上的映射patch,将此patch作为每个候选框的卷积特征输入到SPP layer和之后的层,完成特征提取工作。
文中使用16块,4块,1块三种尺度,从这21个图片块中,分别计算每个块的最大值,从而得到一个输出神经元。最后把一张任意大小的图片转换成了一个固定大小的21维特征
R-CNN的缺陷:
尺度固定,图像畸形;所有候选区都送到CNN里,重复计算耗时
SPP-net解决了R-CNN重复提取候选区域特征的问题,同时允许各种尺寸图像作为输入,解决了图像畸变的问题,但R-CNN的其它问题,如训练步骤繁琐、磁盘空间开销大等依然有待解决。
Fast R-CNN改进:
结合了SPP的优点,将最后一个卷积层的SPP Layer改为RoI Pooling Layer;另外提出了多任务损失函数(Multi-task Loss),将边框回归直接加入到CNN网络中训练,同时包含了候选区域分类损失和位置回归损失。
Fast R-CNN目标检测主要流程如下:
RoI Pooling Layer:
实际上是SPP Layer的简化版,SPP Layer对每个候选区域使用了不同大小的金字塔映射,即SPP Layer采用多个尺度的池化层进行池化操作;而RoI Pooling Layer只需将不同尺度的特征图下采样到一个固定的尺度(例如7*7)
SPP Net不会更新SPP layer之前的层,其将所有的特征图上的roi保存下来,然后随机选择n个进行的网络微调不能共享feature因此反向传播非常低效,而ROI pooling可理解为可共享feature,反向传播比SSP Net高效很多
用SVD(奇异值分解)对全连接层进行变换来提高运算速度
损失函数:
在面对离群点时,如果使用L2 loss,惩罚会很大,离群点的loss占主导。
如果使用L1,在0处导数不唯一,会影响收敛,所以使用Smooth L1
在(-1,1)使用平方函数使它平滑
总的Loss是
其中类别loss是,使用Softmax取代SVM,输出N(类别)+1(背景)类
而坐标loss是,输出的是4*N(类别)
以VGG-16作为conv layers的模型为例:
对于一副任意大小PxQ的图像,首先缩放至固定大小MxN,然后将MxN图像送入网络;而Conv layers中包含了13个conv层+13个relu层+4个pooling层;RPN网络首先经过3x3卷积,再分别生成positive anchors和对应bounding box regression偏移量,然后计算出proposals;而Roi Pooling层则利用proposals从feature maps中提取proposal feature送入后续全连接和softmax网络作classification。
作为一种CNN网络目标检测方法,Faster RCNN首先使用一组基础的conv+relu+pooling层提取image的feature maps。该feature maps被共享用于后续RPN层和全连接层(VGG-16,ZF)。
RPN网络用于生成region proposals。该层通过softmax判断anchors属于positive或者negative,再利用bounding box regression修正anchors获得精确的proposals。
该层收集输入的feature maps和proposals,综合这些信息后提取proposal feature maps,送入后续全连接层判定目标类别。
利用proposal feature maps计算proposal的类别,同时再次bounding box regression获得检测框最终的精确位置。
对于固定维度的输入M*N,经过13层conv,每层后边跟Relu,还有4层Pooling
Conv层的参数:kernel_size=3, padding=1, stride=1, 所以卷积前后维度不变
Pooling层的参数:kernel_size=2, padding=0, stride=2, 所以池化后维度减半
所以得到的feature map的每个像素对应原图的4*4区域,大小是(M/16)*(N/16)
Adaboost使用滑动窗口+图像金字塔生成检测框
R-CNN使用SS(Selective Search)方法生成检测框
而Faster RCNN则抛弃了传统的滑动窗口和SS方法,直接使用RPN生成检测框
RPN网络实际分为2条线,上面一条通过softmax分类anchors获得positive和negative分类,下面一条用于计算对于anchors的bounding box regression偏移量,以获得精确的proposal。而最后的Proposal层则负责综合positive anchors和对应bounding box regression偏移量获取proposals,同时剔除太小和超出边界的proposals。
Faster R-CNN中Anchor的理解、Anchor大小和输入大小、目标大小的关系?
Faster R-CNN采用了三种大小和三种比例的anchor(1:1, 1:2, 2:1),一共九个,anchors size是根据检测图像设置的,尽量让anchor覆盖整张图像上的各种尺度和比例。
为每一个点都配备这9种anchors作为初始的检测框
原文提到ZF模型,其Conv的输出的feature map是256通道的,所以FM的每个位置对应的256长度的(VGG-16中是512的),每个像素点有K个anchor,此时需要对每个anchor分成正负,输出是2*K scores,同时,每个anchor有XYWH四个偏移量,输出是4*K coordinates。
并非所有的anchor都拿去训练,所以在合适的anchor中随机选择128个positive anchor和128个negative anchor
对于输入M*N=800*600,四次下采样缩小16倍,整个FM上的anchor数量是:
Ceil (800 / 16) * Ceil (600 / 16) * 9 = 50 * 38 * 9 = 17100,W=50,H=38
对于50*38FM,采用0.5,1,2三种比例,8,16,32三种大小
怎么筛选正负Anchor?
首先Conv得到的FM(W/16, H/16)在经过3*3卷积后,在做1*1卷积降维,输出是18 channel,W*H*18,对应了feature maps每一个点都有9个anchors,同时每个anchors又有可能是positive和negative,所有这些信息都保存WxHx(9*2)大小的矩阵
为何这样做?
后面接softmax分类获得positive anchors,也就相当于初步提取了检测目标候选区域box(一般认为目标在positive anchors中)
那么为何要在softmax前后都接一个reshape layer?
为了便于softmax分类,caffe blob中的存储形式为[1, 2x9, H, W]。而在softmax分类时需要进行positive/negative二分类,所以reshape layer会将其变为[1, 2, 9xH, W]大小,即单独“腾空”出来一个维度以便softmax分类,之后再reshape回复原状。
至此,RPN网络中利用anchors和softmax初步提取出positive anchors作为候选区域
Box如何回归?
回归的目标是
而F的过程就是平移和缩放:
先平移:
再缩放:
此时需要学习的参数是dx,dy,dw,dh,当输入的anchor A与GT相差较小时,可以认为这种变换是一种线性变换(只有当anchors A和GT比较接近时,才能使用线性回归模型,否则就是复杂的非线性问题了)线性回归就是给定输入的特征向量X, 学习一组参数W, 使得经过线性回归后的值跟真实值Y非常接近
所以回归的Loss是预测值和GT的L1loss,一般情况下是用Smooth L1:
所以四个要预测的平移量是:
对于RPN的第二条线:
VGG-16 的Conv的输出是50*38*512,3*3卷积后尺度不变,第一条路的1*1卷积之后输出是positive/negative softmax分类特征矩阵50*38*(2(+/-)*9(anchor)),第二条路的1*1卷积之后输出是regression坐标回归特征矩阵50*38*(4(X,Y,W,H)*9(anchor))
这两个输出作为后边proposal layer的输入。
另外还将im_info也输入。
Proposal layer
三个输入:第一条路的50*38*(2*9)和第二条路的50*38*(4*9),以及im_info
Im_info保存的是(缩放后的长宽和预处理的缩放因子),另外feature_stride=16
代码中Proposal layer的操作:
所以整个RPN的过程是:
输入是conv layers的feature map和RPN的输出的proposal boxes
为什么需要ROI pooling?
传统CNN的输入是固定的,所以需要从原图crop部分或者强制缩放原图到目标尺寸,这样就丢失了很多信息,而RPN得到的box的形状也各不相同,因次从SPP发展了ROI pooling来解决问题
根据源码,ROI pooling的参数有池化后的宽高(即将FM分成多少部分)和上面提到的缩放因子(因为RPN输出的proposal是根据原图来的)
所以先将输入的FM映射回原图,在根据宽高参数(7*7)均匀划分块,然后对每一块做Max pooling,这样不管box是什么尺寸,都会得到7*7=49长度的固定输出proposal feature maps。
对于ROI pooling得到的49长度的输出:(紫色的是全连接)
Lcls使用二分类log loss,Lreg使用Smooth L1,而前面的P*表示只有正anchor的reg loss才会被计算
由于两部分loss差距比较大,所以λ=Nreg/Ncls≈10
为什么Anchor坐标中有负数?
一部分边缘anchors会超出图像边界,而真实中不会有超出图像的目标,所以会有clip anchor步骤
Anchor到底与网络输出如何对应?