rcnn学习笔记
前提知识
rcnn作者rbg大神(Ross Girshick)在读博士的时候就因为dpm获得过pascal voc 的终身成就奖,博士后期间提出rcnn,可以说rcnn是用RegionProposal+CNN完成目标检测任务的开山之作。
学习rcnn之前,首先我们要明白它是什么。为什么把这个模型起名叫rcnn呢?论文里面给的定义是R-CNN: Regions with CNN features,也就是说这个模型利用cnn来提取Regions的特征,rcnn是一个基于候选区域的目标检测的模型。
那目标检测又是什么呢?目标检测实际上就是对图片中的对象(有可能是多个甚至是多类)定位加分类,我们不仅要用算法判断是不是我们关心的对象,还要在图片中标记出它们的位置(经常是用边框把我们关心的对象框起来)。
大致检测流程
整个算法可以划分为4步:
(1) 候选区域选取,rcnn选择用SelectiveSearch的方法从一张图片中生成大概2000个候选区域。
(2) 对每个候选区域用CNN提取特征。
(3) 用SVM分类器对特征进行分类,判断候选区域属于的类别。
(4) 边框回归修正候选框位置。
算法怎么实现检测的呢?我们从图片中提取出候选区域,判断出候选区域是前景还是背景,如果是前景还要判断其类别,然后候选区域就可以当成对象在图片的大致位置。当然直接把候选区域当做检测框会不是很准确,所以最后还要有一个边框回归的操作,把边框修正到一个更加准确的位置。所以上面的检测流程示意图还需要在后面加上边框回归才是算法的正确检测流程。
模型细节
首先,不管是模型在训练阶段还是测试阶段,我们把一张图片放入模型,用SelectiveSearch的方法在图片中提取出大概2000个候选区域,就比如说像下面这张图片,当然下面的图也只有几个候选区域。
提取出候选区域以后,我们就需要把候选区域输入CNN提取图像特征。但是我们知道普通CNN的训练是有监督训练,所以我们在把图片送入CNN之前还需要对候选区域进行标注,这就需要我们定义出正负样本了。
如果候选区域像上面的第一张图把我们关心的对象给完整的圈起来了,那么我们肯定知道把这个候选区域定义为正样本;如果候选区域像第二张图完全没有圈住我们关心的对象,那么我们肯定也知道把这个候选区域定义为负样本;但是问题来了,如果候选区域像第三张图一样圈住我们关心的对象一部分,但是又没有完全圈住,那我们怎么定义我们的样本,这就需要引出IOU的概念。
IOU
IOU定义的是两个框之间的重合度,我们可以利用IOU来得出图片中物体的真实检测框和候选区域的重合度,我们给IOU设置一个阈值来定义正负样本。就比如真实检测框和候选区域的IOU小于0.3,我们就把这个候选区域定义为负样本,也就是说认为这个候选区域并没有包含我们关心的对象,真实检测框和候选区域的IOU大于0.7,我们就把这个候选区域定义为正样本。而IOU在0.3到0.7之间的候选区域我们选择舍弃,因为如果我们不是极度缺乏数据用这些候选区域训练CNN得到的模型效果也不是很好。
尺度变换
虽然现在有了正负样本,但是也还是不能把它们直接送进CNN中训练,因为我们的CNN最后是全连接层,网络结构定义好的时候全连接的神经元数目就已经是确定的了,最后一层卷积层和全连接层的连接方式也已经确定,所以CNN的输入图片的尺寸也已经固定了,然而SelectiveSearch生成的候选区域尺寸是不一样的,所以在把候选区域送进CNN训练之前需要对候选区域的尺寸变换成合适CNN的输入尺寸。
把候选区域缩放成CNN能输入的尺寸也有很多种方法。如上图,左边的人的图是候选区域,第一列是把候选区域按CNN能输入的尺寸扩展,把候选区域旁边的图像内容也扩展进来;第二列是候选区域裁剪出来,然后用填充的方式把候选区域转换成能输入的尺寸;第三列是直接拉伸成能输入的尺寸。下面一行是用了padding=16的结果。
CNN提取特征
CNN提取图像特征其实就是把图片做卷积的处理,具体理论参考《神经网络基础及卷积神经网络》。在我们具体实现的时候使用的CNN可以是不一样的,就比如说我们的数据集要是很小我们就用浅层的CNN来作为架构,如果我们数据集很大并且硬件也足够支持我们训练,那我们可以选择较深层的CNN。论文里面使用的是T-Net和O-Net做的对比试验,然而我在github上找到的程序是用alexnet作为网络架构。
微调
图像分类的标注数据集有很多,目标检测的标注数据集很少,但是深层神经网络的训练又需要很大的数据集。为了用少量的标注数据,训练出高质量的模型,rcnn用了迁移学习的思想。
CNN的前几层卷积层记住的是数据集的一些共性特征(也可以说是浅层特征),所以就算目标检测任务的数据集比较少,我们也可以用相似的分类任务的数据集来预训练CNN,之后再根据我们的任务用目标检测数据集来微调CNN,这样也可以训练一个比较好的网络。
论文中直接用ILSVRC2012分类数据集(有1000个类别)来预训练CNN,然后用生成的候选区域微调CNN,因为分类数据集的类别数和候选区域数据集的类别数不一样,所以在微调的时候还要改变CNN分类层(也就是最后的一层)的神经元数目,把分类层的神经元数目改变成候选区域的类别数。
SVM训练
rcnn模型中的SVM的作用主要是对CNN提取的特征进行分类,但是要完成这个任务SVM也要经过训练,训练数据集也是图片生成的候选区域。具体训练可以参考SVM的资料。
边框回归
用SVM进行分类之后可以得到候选区域的分类结果,候选区域在图片的位置也可以作为大概的检测框,但是因为候选区域是SelectiveSearch算法生成的,直接当成物体的检测框也会有一些偏差,所以我们需要边框回归把这个大概的检测框修正一下, 使得经过修正后的窗口跟Ground Truth 更接近。
边框回归是训练一个回归器,用回归映射关系把候选区域在图片的位置映射到更接近Ground Truth的框。具体参考边框回归(Bounding Box Regression)详解。
非极大值抑制
如果边框回归之后,立刻把候选区域在图片中显示出来,我们会发现图片中的会出现大量的检测框,并不是我们想要的那种每一个对象只用一个检测框框处的那种情况。因为模型把所有认为框有我们关心的对象的候选区域都给显示出来了。解决这个问题可以用非极大值抑制(nms)。
比如说上面的左图是我们需要测试的图片,我们关心的对象是图片上的两辆车,经过系统检测出来的可能是右图这种情况,每辆车可能会有多个候选框把它们框出来。SVM分类对象的时候,是可以做到预测检测框的概率的,也就是说检测框越接近Ground Truth概率越高。
非极大值抑制的思想是想找出图中最高的概率的检测框,也就是右图中概率为0.9的检测框,把它当成最可靠得到检测框,然后把和这个检测框有很高IOU的其他检测框抑制,也就是图右边概率为0.6和0.7的两个框。接下来,从剩下的检测框中再找出最高概率的检测框,也就是图坐标概率为0.8的检测框,把和这个检测框有很高IOU的其他检测框抑制,也就是图左边概率为0.7的检测框。直到不剩下检测框,非极大值抑制算法就完成了。
注意:有一些代码是没有边框回归和非极大值抑制的,只要我们能了解代码为什么得到它那样的输出结构就行了。
参考:1、论文《Rich feature hierarchies for AccurateObject Detection and Segmentation》
2、博客https://blog.****.net/u011534057/article/details/51218250
3、博客https://blog.****.net/zijin0802034/article/details/77685438
(版权所有,转载时请注明作者和出处)