提到目标检测,我们几乎都是从 R-CNN 开始,这篇文章就对 R-CNN 做一个简单的了解。要内容来自 Paper 《Rich feature hierarchies for accurate object detection and semantic segmentation》
后面也会对 Fast R-CNN、Faster R-CNN 等经典的 Two-Stage 目标检测算法进行介绍。
RCNN Paper 链接: https://arxiv.org/pdf/1311.2524.pdf
- 基本流程 {#title-0} ==================
进行目标检测时,我们输入的是什么?以及我们要得到什么?
最简单的场景,当我们输入一张图片,该图像上可能存在一个、或者多个我们感兴趣的物体,目标检测则是希望能够将感兴趣的物体选中,并且要能够知道被选中的物体是什么类别。即:我们输入一张图片,得到用于框选表示物体的框以及框内物体的类别。
RCNN 实现目标检测的流程如下,图片来自 Paper 的作者:
从上图看来,主要分为四个步骤:
- 输入需要进行目标检测的图像;
- 从原图像上生成可能存在我们感兴趣目标的矩形区域,这个区域我们叫做候选区域,这部分工作也是由相关的算法来完成;
- 例如:我们从原图上提取了 2000 个小区域,并对这 2000 个小区域使用 CNN 网络提取图像特征;
- 接下来,使用提取到的特征、以及候选框来训练分类器和回归器。分类器用来识别候选区的目标的类别,回归器用来修正边框的位置。
接下来,介绍下每一部分大概做了哪些事情。
- 候选框生成器 {#title-1} ====================
在提取可能存在我们感兴趣目标的候选区域时,我们得知道,我们也不清楚目标在图片的那个位置,以及目标的宽高是多少,想能够更加精确的找到候选区域还是难度不小的。我们会通过一定的策略,在原图上尽可能产生可能包含目标的候选区域,那该区域是否真的包含目标,以及包含的目标是什么类别,这个得通过后续的网络来识别。
生成候选区域的方法有很多,作者选择使用的是 Selective Search 算法来实现类别独立的候选区域的构建,该算法的基本过程如下:
-
先将原图分割成一个个的小区域,这些区域不重复,把这些区域放到集合 R 中;
-
然后找到 R 中所有相邻小区域,并根据其颜色、纹理、大小、形状等计算其相似度,并存储到 S 集合中,S 集合中的每个元素是相似度和对应的两个子区域;
-
接下来,从 S 中取出相似度值最大的两个子区域,并把它合并成一个大区域,并从 S 中删除与这两个小区域,以及和这两个区域的相似度;
-
接着,构建一个 \(S_t\),这里面包括了新的大区域与其邻居的相似度;
-
将这个 \(S_t\) 添加到 S 中,并将这个大区域添加到 R 中;
-
S 为空则循环停止,否则重复 3-5 步骤。
-
特征提取器 {#title-2} ===================
RCNN 使用 Selective Search 算法得到 1k~2k 候选区域 size 是不固定的,而 CNN 网络对输入的 size 是有要求的,所以需要先将这些候选框 resize 到符合 CNN 网络的输入。
我们可以用 AlexNet、也可以用 VGGNet 等等作为主干网络,这部分的网络主要作用就是提取每一个候选框的特征向量表示。RCNN 作者使用 AlexNet 作为主干网络提取 4096 维的特征向量。
特征提取器在训练的时候,可以使用在大数据集上已经训练好的预训练模型,再在自己数据集上进行微调。一般会使用在 ImageNet 上预训练好的模型基础上做微调,以便能够获得更好的特征向量表示。
在微调的时候,我们需要需要输入正负样本。我们可以把候选框和 Ground Truth 的 IOU 交並比大于 0.5 的候选框作为正样本,其他作为负样本。我们知道训练的样本类别不平衡的话,会影响到模型的效果,所以需要对这些样本进行采样。
- 分类器 {#title-3} =================
在 RCNN 网络中,使用 SVM(支持向量机)来对每个候选框进行分类。这里需要注意的是,我们需要为每个类别都训练一个 SVM 分类器,我们共有 n + 1 个类别。SVM 的输入就是每个每个候选区域的特征向量,输出是其对应的目标类别。这里注意点:如果目标种类有 10 类,则 SVM 需要对应 10+1 类来进行训练,这是因为有些候选区域可能并不属于任何一个目标,我们要将这类的图像预测为背景图像。
SVM 训练时的正负样本也是很有考究。作者正样本使用 Ground Truth 真实边框作为正样本,IOU 小于一定阈值的边框作为负样本。
- 回归器 {#title-4} =================
对候选框进行分类之后,可能一个目标会有多个候选框,我们不需要这么多,此时使用 NMS(非极大值抑制)算法去除冗余的候选框。
候选框是前面 Selective Search 算法生成的,很多情况下是不精准的,所以训练一个边框回归模型来对候选边框进行修正,注意:这里是为每一个类别都训练一个边框回归模型。
边框回归器首先需要训练 4 个回归器,分别对变量的中心点x坐标、中心点y坐标、边框宽度、边框高度的偏差进行预测,这 4 个回归器对应表示为:\(d_{x}(P)、d_{y}(P)、d_{w}(P)、d_{h}(P) \),这里的 P 表示候选框的特征向量表示,使用回归器的预测结果经过下面公式得到最终的输出边框:
上述同时中,\(P_{x}、P_{y}、P_{w}、P_{h}\) 表示待修正的候选边框的中心坐标以及宽高。从公式可以看到:
- \( d_{x}(P)、d_{y}(P) [latex] 更像是基于 [latex]P_{w}、P_{h}\) 的调整系数,将得到的偏差加到 \(P_{x}、P_{y}\) 上,进行中心点平移,实现修正;
- 边框回归器输出的 \( d_{w}(P)、d_{h}(P) \) 经过 exp 计算得到一个缩放值,对原始边框的缩放。
是否就可以理解为,边框回归器的输出结果是用于平移中心点坐标,缩放宽高的系数或者参数。
既然要进行如此的输出,如何计算损失?由于我们输出的是调整参数,所以拟合的目标也应该是调整参数。我们就看看 Ground Truth 在候选边框的基础上需要如何调整才能得到,如下公式所示:
也就是说,我们希望
- \( d_{x}(P)\) 的输出值能够更加接近\( t_{x}(P) \)
- \( d_{y}(P)\) 的输出值能够更加接近\( t_{y}(P) \)
- \( d_{w}(P)\) 的输出值能够更加接近\( t_{w}(P) \)
- \( d_{h}(P)\) 的输出值能够更加接近\( t_{h}(P) \)
再次注意:\( d_{x}(P)、t_{x}(P) \) 是两个线性函数。损失函数可以用 MSE,如下: