目标检测需要获取图片中所有目标的位置及其类别,对于图2-1 中的 3 张图而言,当图片中只有一个目标时,“regression head”预测 4 个值,当图片中有 3 个目标时,“regression head”预测 12 个值,那么当图片中有多个目标时,“regression head”要预测多少个值呢?
这时根据读者已经学过的一些知识,可能会尝试用滑窗的方法来解决,如图2-2所示。但是,这里有一个问题,我们需要设计大量的不同尺度和长宽比的“滑窗”使它们通过CNN,然而这个计算量是非常巨大的。有没有什么方法能使得我们快速定位到目标的潜在区域,从而减少大量不必要的计算呢?
学者们在这个方向做了很多研究,比较有名的是selective search 方法,具体方法这里不做详细说明,感兴趣的读者可以看关于selective search 的论文。大家只要知道这是一种从图片中选出潜在物体候选框(Regions of Interest,ROI)的方法即可。有了获取ROI 的方法,接下来就可以通过分类和合并的方法来获取最终的目标检测结果。基于这个思路有了下面的R-CNN 方法。
下面介绍R-CNN[1] 的训练过程,整体训练流程如图2-3 所示:
图2-3 R-CNN 训练过程[9]
(1)选出潜在目标候选框(ROI)
objectness[10], selective search[11], category-independent object proposals[12]等很多论文都讲述了候选框提取的方法,R-CNN 使用selective search 的方法选出2000 个潜在物体候选框。
(2)训练一个好的特征提取器
R-CNN 的提出者使用卷积神经网络AlexNet 提取4096 维的特征向量,实际上使用VGGNet/GoogLeNet/ResNet 等也都可以。细心的读者会发现,AlexNet等网络要求输入的图片尺寸是固定的,而步骤(1)中的ROI 尺寸大小不定,这就需要将每个ROI 调整到指定尺寸,调整的方法有多种,可参见图2-4,其中(a)是原始ROI 图片,(b)是包含上下文的尺寸调整,(c)是不包含上下文的尺寸调整,(d)是尺度缩放。
接下来,为了获得一个好的特征提取器,一般会在ImageNet 预训练好的模型基础上做调整(因为ImageNet 预测的种类较多,特征学习相对完善),唯一的改动就是将ImageNet 中的1000 个类别的输出改为(C+1)个输出,其中C 是真实需要预测的类别个数,1 是背景类。新特征的训练方法是使用随机梯度下降(stochastic gradient descent,即SGD),与前几章介绍的普通神经网络的训练方法相同。
提到训练,就一定要有正样本和负样本,这里先抛出一个用于衡量两个矩形交叠情况的指标:IOU(Intersection Over Union)。IOU 其实就是两个矩形面积的交集除以并集,如图2-5 所示。一般情况下,当IOU>=0.5 时,可以认为两个矩形基本相交,所以在这个任务中,假定两个矩形框中,1 个矩形代表ROI,另一个代表真实的矩形框,那么当ROI 和真实矩形框的IOU>=0.5 时则认为是正样本,其余为负样本。
至此,R-CNN 的第二步特征提取器可以开始训练了,不过在训练过程中要注意,需要对负样本进行采样,因为训练数据中正样本太少会导致正负样本极度不平衡。最终在该步得到的是一个卷积神经网络的特征提取器,其特征是一个4096 维特征向量。
(3)训练最终的分类器
这里为每个类别单独训练一个SVM 分类器。这里面有个小技巧,SVM 的训练也需要选择正负样本,R-CNN 的提出者做了一个实验来选择最优IOU 阈值,最终仅仅选择真实值的矩形框作为正样本。
注意:正负样本的选择比较有讲究,Fast R-CNN 和Faster R-CNN 是根据IOU 的大小选取正负样本,2.2.3 节有详细介绍。
(4)为每个类训练一个回归模型,用来微调ROI 与真实矩形框位置和大小的偏差,如图2-6 所示。
下面是所有检测问题都会用到的一块代码:IOU 的计算。
def bboxIOU (bboxA, bboxB):
A_xmin = bboxA[0]
A_ymin = bboxA[1]
A_xmax = bboxA[2]
A_ymax = bboxA[3]
A_width = A_xmax - A_xmin
A_height = A_ymax - A_ymin
B_xmin = bboxB[0]
B_ymin = bboxB[1]
B_xmax = bboxB[2]
B_ymax = bboxB[3]
B_width = B_xmax - B_xmin
B_height = B_ymax - B_ymin
xmin = min(A_xmin, B_xmin)
ymin = min(A_ymin, B_ymin)
xmax = max(A_xmax, B_xmax)
ymax = max(A_ymax, B_ymax)
A_width_and = (A_width + B_width) - (xmax - xmin) # 宽的交集
A_height_and = (A_height + B_height) - (ymax - ymin) # 高的交集
if ( A_width_and <= 0.0001 or A_height_and <= 0.0001):
return 0
area_and = (A_width_and * A_height_and)
area_or = (A_width
A_height) + (B_width B_height)
IOU = area_and / (area_or - area_and)
return IOU
预测阶段有如下几个步骤:
(1)同样地,使用selective search 方法先选出2000 个ROI。
(2)所有ROI 调整为特征提取网络所需的输入大小并进行特征提取,得到2000个ROI 对应的2000 个4096 维的特征向量。
(3)将2000 个特征向量分别输入到SVM 中,得到每个ROI 预测的类别。
(4)通过回归网络微调ROI 的位置。
(5)最终使用非极大值抑制(Non-Maximum Suppression,NMS)方法对同一个类别的ROI 进行合并得到最终检测结果。NMS 的原理是得到每个矩形框的分数(置信度),如果两个矩形框的IOU 超过指定阈值,则仅仅保留分数大的那个矩形框。
以上就是R-CNN 的全部过程,我们可以从中看出,R-CNN 存在的一些问题:
● 不论是训练还是预测,都需要对 selective search 出来的 2000 个 ROI 全部通过CNN 的forward 过程来获取特征,这个过程非常慢。
● 卷积神经网的特征提取器和用来预测分类的 SVM 是分开的,也就是特征提取的过程不会因SVM 和回归的调整而更新。
● R-CNN 有非常复杂的操作流程,而且每一步都是分裂的,如特征提取器通过softmax 分类获得,最终分类结果由SVM 获得,矩形框的位置通过回归方式获得。
文章来源:阿里云-机器智能技术