目标检测算法(1)目标检测中的问题描述和R-CNN算法

目标检测(object detection)是计算机视觉中非常具有挑战性的一项工作,一方面它是其他很多后续视觉任务的基础,另一方面目标检测不仅需要预测区域,还要进行分类,因此问题更加复杂。最近的5年使用深度学习方法进行目标检测取得了很大的突破,因此想写一个系列来介绍这些方法。这些比较重要的方法可以分成两条主线,一条是基于区域候选(region proposal)的方法,即通过某种策略选出一部分候选框再进行后续处理,比如RCNN-SPP-Fast RCNN-Faster RCNN-RFCN等;另一条是直接使用卷积神经网络将图像变换到一个小的尺度,在新的尺度上使用anchor box来预测目标区域,这一类方法包括SSD以及Yolo的各个版本等;另外这个系列中也会穿插一些其他的算法如OverFeat、DPM等。本文是目标检测系列的第一篇,主要提及目标检测中的基本问题,并详细地介绍了RCNN算法。

一 目标识别问题的基本描述

目标检测是计算机视觉中非常具有挑战性的一项工作,它是其他很多后续视觉任务的基础,比如我们通常所说的识别(分类)问题,以人脸识别为例,通常其不是一个完全的端到端(end to end)的过程,如果想要获得很好的识别精度,一般情况下需要首先进行人脸检测,然后对检测得到的区域进行人脸定位(face landmark),然后再进行人脸对齐(face alignment),最后才进行分类或者验证,好的人脸检测算法对最后的识别精度提升很大,而有的算法会把检测和定位一步做出来;另一方面,目标检测是一项相对比较有难度的工作,其考虑的问题比较多,比如我们怎样合理选择定位区域?怎样对定位区域的图像内容进行分类?如果框柱的区域有误差我们怎么修正?

1. 目标检测中的一些基本概念

在回答上面几个问题之前,这里首先介绍目标识别过程中经常提及的一些概念。我们可以把分类任务和检测任务做一个比较(这几张图片都来源于\(RBG\)大神RCNN的ppt,戳这里):

目标检测算法(1)目标检测中的问题描述和R-CNN算法

图1 classification vs detection

左边一张是分类,右边一张是检测。可以看出分类只需要判断给定的图像属于哪一类,但很明显由于其他物体或者背景的干扰,直接这么做肯定效果不好。相比较而言,检测则是判断某个固定的区域中是否包含物体,并且判断其中的物体属于哪一类,我们把框住这个区域的矩形框叫做bounding box,那么目标检测的问题可以看成是:给定目标类别集合比如\(\left \{ airplane, bird, motorbike, person, sofa \right \}\),判断这些bounding box中是否包含目标,如图2所示:

目标检测算法(1)目标检测中的问题描述和R-CNN算法图2 目标检测示例:左图是输入,右图是输出

另外,对于这些预测的bounding box是否真实包含物体,通常会有预测的置信度,也就是这个框出来的区域有多大概率属于某类的物体,所以目标检测实际的输出会包含三个内容:预测的bounding box,bounding box中物体的类别,以及属于这个类别的置信度。

目标检测算法(1)目标检测中的问题描述和R-CNN算法

图3 'person' detector predictions 和 ground truth 'person' boxes

图3中橙色的区域是我们预测时的bounding box,而紫色的是真实物体包含的区域,通常叫做ground truth(GT),训练的目的是让我们预测到的bounding box和GT的交并比(即两个区域的重叠部分除以相并的部分, Intersection over Union,简称IoU)的值比较高。那在测试阶段我们到底应该怎样衡量预测的好坏呢?这里用到一个非常重要的概念mAP,即平mean Average Precision(平均AP)的值,注意这里的AP是针对每个类别求出的,那每个类的AP值到底是怎样计算的呢?

首先在进行预测后,我们可以按照置信度大小排序并且选择一个阈值作为预测的正负类的评判标准,大于阈值预测为正类否则为负类,如下图所示:

目标检测算法(1)目标检测中的问题描述和R-CNN算法

图4 置信度排序及precision和recall的计算方式

假如我们选择置信度\(t=0.5\)为正负类的阈值,那么小于\(t\)的全部预测为负类,这里引出两个机器学习中非常常见的概念,也就是查准率(precision)值和查全率(recall)值,二者的计算方式如下

\(precision=\frac{true positive}{true positive+false positive}\)

\(recall=\frac{true positive}{ground truth}\)

(1) true positive表示正确的预测为正类,在目标检测中就是指预测的bounding box和ground truth的IoU超过0.5的box的个数;

(2) false positive表示错误的预测为正类,对应于bounding box和ground truth的IoU小于等于0.5的box的个数,还有那些重复预测同一个ground truth的box的个数。

还有两种预测行为true negative和false negative也很容易根据(1)、(2)推断出来,这里的AP值重点考察(1)和(2)所以没列出来。从precision和recall值的定义来看,它们衡量分类性能的角度不一样,precision侧重于考察预测的结果为正类样本中的准确程度,而recall侧重于考察真实的正类样本是被预测正确的全面程度。现在我们知道怎样计算precision和recall的值,那么对于每一类样本我们可以依照某个采样规则画出precision和recall关系的序列图,如下图所示,横坐标为recall值,纵坐标为precision值,根据采样的recall值的不同来得到不同的precision值,然后画出相应的点连成曲线,这里的曲线下方面积就是这个类的AP值,AP值越高表明在给定recall的情况下precision的值也比较高。注意到我们选取不同的阈值\(t\)可以得到不同的曲线,此时的AP值也不同。

目标检测算法(1)目标检测中的问题描述和R-CNN算法

图5 mAP计算示意图

以上是关于目标检测的基本概念,在实际应用中到底怎样进行检测,又有哪些难点呢?我们接下来要讲的RCNN主要会解决一下三个问题:

(1) 怎样找出这些预测的bounding box?

容易想到的很笨的方法是选择大小、比例不同的滑窗,让这个滑窗遍历整个图像,对每个滑过的位置都进行预测分类,判断是否有物体存在,像下图一样:

目标检测算法(1)目标检测中的问题描述和R-CNN算法

图6 使用大小比例不同的bounding box滑窗经过每个图像的位置进行预测,导致需要检测很多个窗口

这样操作的缺点十分明显:选区的滑窗的大小和比例不同以及需要滑过图像中每一个位置,导致需要检测的窗口数量巨大。那么我们是否能想出一个间接的方法,即并不是一步处理所有的窗口,而是首先通过相对比较“粗糙”的方法过滤那些肯定不包含物体的区域?

(2) 假如我们已经找到了一个bounding box,怎样判断属于哪一个类?

这个问题可以看成是一个分类的问题,对于指定区域的图像,我们可以用传统的手工特征提取方法,比如LBP、HOG、Haar特征等等,更好的方法是通过卷积神经网络可以自动选择特征,并且效果非常好,提取到特征之后再进行分类。

(3) 是否需要对找到的包含物体的box进行修正?

由于选择的bounding box的位置通常会有一定程度的偏差,那么需要对这个位置进行修正,此问题可以看成是一个回归的问题,回归预测的值通常是这个box左上角的坐标,区域的宽和高。

带着这三个问题,这篇文章主要介绍目标检测领域一个里程碑的算法RCNN,即基于区域的卷积神经网络方法。

二 R-CNN算法

R-CNN(region with CNN feature)于13年被Ross Girshick(江湖人称RBG大神)提出,是使用深度学习进行目标检测的里程碑式的工作,RBG主页:http://www.rossgirshick.info,主页中列出的关于目标检测及相关领域的工作都非常经典,可以说这些工作很大程度推动了深度学习在目标检测中的应用。废话不多说,首先我们看看RCNN算法的动机。

1. 动机及解决的问题

(1) 与分类任务不同,目标检测需要框出指定的区域,有相关paper直接使用回归的方法得到区域的位置,但实际应用起来效果并不好;另外,有方法直接使用滑窗加深度学习的方法,不过这一类方法通常网络层次并不深,主要考虑到的是一旦网络层次加深,最后输出的特征图对应的原始图像的感受野太大,造成检测精度不高;

(2) 一个更好地解决方案是是使用所谓“区域建议(region proposal)”的方法给出一堆候选区域,这些候选区域能够先过滤掉那些大概率不包含物体的区域,然后选择一个深度神经网络抽取特征;

(3) 一旦抽取特征之后可以设计一个SVM分类器,即对每一个类别的物体都看成是一个单独的二元分类问题;

(4) 最后使用回归的方法对包含物体的bounding box进行回归,回归的目的是修正bounding box的偏差。

值得一提的是,RCNN论文中的细节很多,怎样得到region proposal,怎样把候选得到的区域缩放到统一尺寸以使其适配CNN网络的输入大小,怎样进行多阶段的训练(CNN网络的“pre-training”和“fine-training”,SVM分类器的训练以及回归器的训练)等等,CNN网络为什么不直接接入一个softmax层转而使用SVM进行分类,等等这些会在下文中介绍。

2. 算法架构

目标检测算法(1)目标检测中的问题描述和R-CNN算法

图7 RCNN算法框架

RCNN的算法框架如图7所示,算法过程描述如下:

(1) 第一步,即图7中的1~2,对于给定的输入图像,使用选择性搜索(selective search)的区域建议方法提取出大约2000个候选区域,即首先过滤掉那些大概率不包含物体的区域,通过这一阶段将原始图像中需要处理的区域大大减少;

(2) 第二步,分为两个小步:

  • 第一小步,需要对第一阶段中抽取得到的候选区域,经过一个叫做"warp"的过程,这个warp实际就是一个缩放的过程,因为第一步我们提取出的候选区域大小不一,但是后续接入的深度网络的输入是固定的,因此这些区域的大小需要适配CNN网络固定大小的输入;
  • 第二小步,把第一小步中warp之后的候选区域接入到卷积神经网络,抽取一个相对低维的特征;

(3) 第三步,对应图中的3~4,对每个类都训练一个二元的线性SVM,然后判断上一步抽取的特征是否包含物体。

(4) 第四步,这一步图上并没有画出,这一步用于对包含物体的候选区域位置进行回归,以修正偏差。

3. 算法具体流程

通过算法框架我们能够大致了解RCNN运作的流程,但真正实施起来会包含很多问题,我们一一来看。

(1) 怎样使用selective search方法提取候选区域

RCNN一大创新点是对原始图像抽取一些候选区域,再使用深度学习进行特征抽取,文中列举了一些区域建议的方法,最后使用的是selective search的方法:“Selective Search for Object Recognition”。selective search是一种“hierarchical bottom-up grouping”的方法,即层次、自底向上的分组方法,简单来说就是先找出图像中的相邻区域,然后定义一个领域相识度的计算规则,使用这些规则一直合并相似度较高的区域并且更新,最后知道覆盖至整张图像,完成处理的图像中不同的区域就是这些“region proposal”。以下是示意图:

目标检测算法(1)目标检测中的问题描述和R-CNN算法

图8 selective search算法示意图

了解一个算法最好的方法就是看原始的paper,原始的paper对算法的描述步骤如下:

输入:一张图像(彩色) 输出:候选的box区域

算法开始需要初始化一些区域的集合:\(R=\left \{ r_{1},r_{2},...r_n{} \right \}\),文章中使用paper:“Efficient graph-based image segmentation”来做这件事;同时还初始化一个空的相似度区域的集合\(S=\varnothing \)

a. 对于所有的相邻区域\((r_{i},r_{j})\),按照相似度规则计算相似度\(s(r_{i},r_{j})\),并且计算\(S=S\cup s(r_{i},r_{j})\),即计算所有领域的相似度集合;

b. 假如\(S\neq \varnothing \):

  • 获取\(S\)中相似度最高的一对区域\(s(r_{i},s_{j})=max(S)\);
  • 对最相似的两个区域进行合并\(r_{t}=r_{i}\cup r_{j}\);
  • 从\(S\)集合中去除和\(r_{i}\)及\(r_{j}\)相邻的相似区域;
  • 计算合并后的区域和其邻域的相似度集合\(S=S\cup S_{t}\)及\(R=R\cup R_{t}\)
  • 重复以上步骤直至\(S= \varnothing \)

c. 从集合\(R\)中提取出所有的boxes,即定位的矩形区域

对于相似度的计算方法selective search的原始论文中定义为颜色、纹理、尺寸等几种不同度量方式的叠加之和:

\(s(r_{i},r_{j})=a_{1}s_{colour}(r_{i},r_{j})+a_{2}s_{texture}(r_{i},r_{j})+a_{3}s_{size}(r_{i},r_{j})+a_{4}s_{fill}(r_{i},r_{j})\)    \(a\in \left \{ 0,1 \right \}\)

对每种具体的计算方式这里就不多提了。

(2) CNN网络输入

使用选择性搜索提取出大小不一的候选区域之后,然后经过卷积神经网络提取特征,文中提到的是使用12年的AlexNet,此网络的输入是固定大小的\(227\times 227\),输出是\(4096\)维的特征向量,由于输出的尺寸固定,而RCNN第一步抽取的候选区域大小不一,因此给出了几种方法对候选区域的大小进行变换以适配网络输入:

a. 各向异性(anisotropically)缩放,即对候选区域缩放的高和宽的倍数不同,直接拉成CNN中输入大小的形式,这种变换在文中称为“warp”;

b. 各向同性(isotropically)缩放,即缩放的高和宽的比例倍数相同,这里又分为两种:一种对原始的图像按等比例缩放后的灰色区域进行填充,另一种不进行填充。

如下图所示,其中(A)为原始图像;(B)、(C)分别对应各向同性的两种方法;(D)对应的是各向异性的方法。另外每种方法在下图中有两行,上面的一行表示缩放之后如果候选区域超出了边界不进行padding,即不使用周围的像素进行填充,下一行是进行16像素的padding。文中进行的实验表明使用padding为16像素的“warp”方法效果最好。

目标检测算法(1)目标检测中的问题描述和R-CNN算法

图9 几种候选区域缩放的方法对比

(3) CNN网络训练

训练分成“pre-training”+“fine-tuning”:首先选用caffe中已经训练好的模型在大的数据集上进行预训练(ILSVRC2012图像分类的数据集 )得到一个初始的网络,然后在此网络的基础上细调:替换网络最后的输出层,因为ImageNet分类数据集的输出层包含1000个类,这里进行目标检测的类别不一致,比如VOC使用的是20个类,而ILSVRC2013 的目标检测使用的是200个类,把背景也当成一类的话,实际的网络输出层的个数应该是\(N+1\),\(N\)为目标的类别。在细调的时候考虑与ground truth(也就是真实的包含物体的区域)的IoU超过0.5的为正类,其余的均为负类,迭代的时候使用SGD方法,选取0.001的学习率,使用包含32个正类样本和96个负类样本组成mini-bacth。

(4) SVM分类器的训练

一旦CNN网络训练完成,去除网络中的最后的输出层,以全连接层的输出得到新的特征向量,以供训练SVM。这里文中提到了SVM训练阶段正负样本的划分,注意的是这里的正负类的选择和CNN网络训练时的不同,训练SVM时正类定义为ground truth,候选区域中与ground truth的IoU小于0.3的定义为负类,其余的候选区域忽略;文中附录探讨了为什么这样做的两个问题:一个是为什么不直接在CNN网络后面用softmax进行分类,而使用SVM;一个是正负类样本的定义方式,我们放在第(8)点专门介绍。

(5) 非极大值抑制过滤重叠的bounding box

在test阶段,候选区域经过CNN提取特征之后最后使用SVM进行分类评分,得到很多的bounding box,由于这些bounding box包含很多重叠的部分,如下:

目标检测算法(1)目标检测中的问题描述和R-CNN算法

图8 左图是预期的bounding box,右图是实际得到的bounding box

文中使用非极大值抑制(non-maximum suppression,NMS)方法去除那些输出的重叠程度比较高的bounding box,NMS是目标检测中用的非常频繁的一种算法,大致的步骤是:

首先对输出的bounding box进行打分,找出评分最高的bounding box,计算其他的bounding box和它的IoU值,选取一个阈值,从输出的bounding box中移除那些IoU小于这个阈值的box,然后重复这个步骤,直至仅存在保留的bounding box。文中使用NMS基于每个单独的类。

(6) 检测时间分析

整个检测阶段的时间包含:选择性搜索得到一系列region proposal,然后通过CNN抽取这些region proposal的特征,使用SVM分类打分,最后使用NMS去除重叠部分;作者认为有两个特性让检测比较有效,其一是网络共享,其二是使用CNN进行了降维;主要的时间开销时间在计算候选区域和特征(GPU上13s一张,CPU上53秒一张,现在看来真的是非常慢。。。);作者也提到了和DPM算法的比较,精度和速度都有大幅度提升。可想而知,别看现在我们能做到实时高精度的检测,前几年这些深度学习方法在目标检测中的突破真的是巨大。

(7) 回归器修正box偏差

候选区域经过SVM打分之后,需要经过回归器进行修正,修正的目的是得到一个新的bounding box,新的bounding box预测的偏差减小,文中使用的回归器修正启发于deformable part models(DPM,深度学习火热之前比较重要的一种目标检测方法,在以后的blog中有时间会详细解释这种方法),而且回归是基于每个特定类的。具体来说给定预测的bounding box和ground truth的集合\({(P^{i},G^{i})}_{i=1,...,N}\),其中\(P^{i}=(p_{x}^{i},p_{y}^{i},p_{w}^{i},p_{h}^{i})\),\(G^{i}=(g_{x}^{i},g_{y}^{i},g_{w}^{i},g_{h}^{i})\),\(x,y,w,h\)分别表示左上角的坐标以及box的宽和高,修正的目的是把\(P\)变换到预测的ground truth\(\hat{G}\),变换的的函数有四个分别是\(d_{x}(P),d_{y}(P),d_{w}(P),d_{h}(P)\),变换的具体公式如下:

\(\hat{G}_{x}=P_{w}d_{x}(P)+P_{x}\)

\(\hat{G}_{y}=P_{h}d_{y}(P)+P_{y}\)

\(\hat{G}_{w}=P_{w}exp(d_{w}(P))\)

\(\hat{G}_{h}=P_{h}exp(d_{h}(P))\)

这里的四个\(d_{x}(P)\),\(d_{y}(P)\),\(d_{w}(P)\),\(d_{h}(P)\)由CNN最后一层的pooling层的特征经过线性变换得到:\(d_{*}(P)=w_{*}^{T}\varnothing (P)\),因此这里我们需要学习的参数变成\(w_{*}\),此问题可以看成是一个标准的岭回归问题:

\(w_{*}=\underset{\hat{w}_{*}}{argmin}\sum_{i}^{N}(t_{*}^{i}-\hat{w}_{*}\varnothing(P^{i}) )+\lambda \left \| \hat{w}_{*} \right \|^{2}\)

而上式中回归的目标\(t\)可以由给定的\(P\)和\(G\)及公式(1)~(4)反推得到:

\( t_{x}=(G_{x}-P_{x})/P_{w}\)

\( t_{y}=(G_{y}-P_{y})/P_{h}\)

\(t_{w}=log(G_{w}/P_{w})\)

\(t_{h}=log(G_{h}/P_{h})\)

这里带正则项的标准回归问题很容易得到封闭解。

(8) 为什么RCNN使用SVM替代softmax层进行分类?

对于这个问题作者分两点进行了解释:

其一,作者做过实验表明,在微调阶段尝试使用和SVM相同定义的正负类样本数,效果比较差,对此作出假设:怎样定义正负类样本数并不重要,重要的是造成这种结果的差异源于微调中数据的有限,当使用IoU0大于0.5的样本作为正类时(文中用“jittered”形容这些数据),样本增加了接近30倍,避免了过拟合;并且,这些jittered的数据导致了fine-tuning阶段的结果并不是最优的,因为现在选的正类样本并不是“精准定位”的(显然这是由于IoU阈值变高导致正类样本的门槛变“低”了);

其二,根据第一点解释恰好引出了第二个点,即为什么使用SVM而不是直接使用softmax层进行分类,作者认为按照刚才的解释,微调阶段CNN并不能进行“精准定位”,并且softmax训练的时候只是随机采样负类样本,而SVM训练阶段可以考虑那些“hard negative”的样本。这里使用了“hard negative mining”的思想,以目标检测为例,第一轮训练的时候先按照预先定义好的正负类样本进行分类;第二轮对于那些本身是负类却被误判为正类的样本,即通常我们所说的“false positive”样本,计入负类样本重新进行训练,这个过程重复几次最终得到的效果会比较好。

基于以上两点考虑,作者认为有必要在CNN后面接上SVM进行分类。

三 RCNN中的对比实验分析、特征可视化、“Ablation studies”、误差分析等工作

除了这篇博客第二节中分析的模型架构流程外,作者在实验分析、数据可视化以及“Ablation studies”、误差分析等多个方面都进行了很详尽的分析,这里的内容太多不细说,而是稍微提及。

1. 在Pascal VOC10-12以及ILSVRC2013 detection 的实验结果
在VOC10上作者主要和DPM类方法(DPM以及SegDPM)以及UVA系统(主要是selective search方法,使用四层空间金字塔的sift方法+核SVM)进行了对比,RCNN在实验精度上从35.1mAP提升到了53.7mAP,并且速度上也有一定程度提高,而在VOC12上也获得了53.3的mAP;在ILSVRC2013数据集上和OverFeat方法进行对比(实际列举的对比方法比较多)从24.3mAP提升到31.4mAP。

2. 特征学习可视化

作者使用了一种非参数的方法来显示网络到底学习到了什么,重点分析了最后一个pooling层的激活值的可视化。

3. Ablation studies
Ablation studies 可以看成是去除算法中的某些结构,然后进行实验并比较分析实验的对比效果,比较了没有fine-tuning和有fine-tuning的效果对比;同时还分析了RCNN和两种不同的DPM方法(HOG+DPM和稀疏编码直方图+DPM,简称HSC+DPM),得出的结论是RCNN的性能也要好于二者。

4. 关于网络结构

作者除了使用AlexNet以外,还使用了VGG代替进行实验,结果从58.5%mAP提升到66.0%mAP,代价是由于网络变深不少导致计算时间提升。

5. 关于误差分析

这里的误差分析使用了paper“Diagnosing error in object detector”的方法,而减小误差的方法就是之前提到的DPM中使用的回归修正偏差。

除以上外作者还详细地讨论了在ILSVRC2013上从训练、验证、Ablation studies等等非常详细的实验对比和讨论,工作量非常的丰富,有兴趣的同学可以直接看原始paper。

四 RCNN算法总结及其缺点

RCNN是使用深度学习进行目标检测中非常有意义的一项工作,它首先利用选择性搜索选取一些区域候选框,然后通过CNN抽取特征并使用SVM进行分类,然后使用NMS排除重叠的bounding box,最后使用回归器对box的位置进行修正。一方面,RCNN在精度上和速度上相比较传统方法均有很大的提升,是一个有里程碑意义的研究;另一方面我们应该也可以看到,RCNN这篇论文中的工作量非常大,了解其中的细节便于我们理解目标识别领域的关键问题,同时RCNN也结合或借鉴了之前的算法,比如选择性搜索进行区域候选、使用NMS筛选窗口、DPM中的回归修正的思想等等,可以说是“站在前人的肩膀上”。通过分析我们可以得出RCNN的一些缺点:

(1) RCNN的耗时体现在两个阶段,一个是区域候选需要一定时间,另一个是对于每一个区域候选框都需要重新丢进网络里才能抽取特征,特别是后者导致RCNN非常的慢;

(2) RCNN在网络的输入是使用的warp方法,这种缩放会不会对最终的精度有影响?

(3) RCNN显然并不是一个端到端的工作,通常情况下我们认为端到端的工作可以达到更好的效果,因为不同模块之间的衔接可能会存在一定的信息损失。

本文是目标检测系列的第一篇,主要介绍目标检测中的基本问题以及RCNN算法,下篇将介绍SPP算法。

上一篇:【Linux】进程控制--进程的等待与替换


下一篇:215. 数组中的第K个最大元素