深度学习在目标检测中的应用及其tensorflowAPI实践(一)

近些年深度学习在图像领域大放光彩,这篇文章先对目标检测领域深度学习的发展做一个总结,再结合一个例子对tensorflow model zoo中的目标检测API使用做一个说明。
本文内容如下(会分几次发出来):

  • 目标检测的任务

  • 深度学习在目标检测中的应用

    • RCNN
    • fast RCNN
    • faster RCNN
    • RFCN
    • yolo
    • yolo V2
    • SSD
  • tensorflow目标检测API的使用

(一)目标检测的任务

为了说明什么是目标检测任务,我举两个例子来说明。
第一个VOC数据集,VOC2007数据集是一个训练目标检测的数据集,其图片中一共有二十个种类的物体,包括 ‘aeroplane’, ‘bicycle’, ‘bird’等一共20个种类的物体,我们的任务就是在图中把这些物体给找到,框出这些物体,并说明框住的物体是这二十个类别里的哪一类,就像下面这样:
深度学习在目标检测中的应用及其tensorflowAPI实践(一)_第1张图片深度学习在目标检测中的应用及其tensorflowAPI实践(一)_第2张图片
对照上面的图片,可以看出目标检测主要是在做两件事,一是确定图片中有没有你要找的东西,二是这东西在哪。
下面还有另外一个例子,数据集在这http://www.robots.ox.ac.uk/~vgg/data/scenetext,是一份场景文字数据集,这个数据集一共有80万的图片,每张图片中都嵌入了文字,任务是找到图片中的文字,把文字框出来,如下:
深度学习在目标检测中的应用及其tensorflowAPI实践(一)_第3张图片深度学习在目标检测中的应用及其tensorflowAPI实践(一)_第4张图片
对于这样的目标识别任务,训练数据集的输入是一张图片,加上图片中每个物体框的左上角坐标以及右下角坐标。

(二)深度学习在目标检测中的应用

深度学习在目标检测中的应用主要分为两个路子的方法:

  • RCNN,fast RCNN,fasterRCNN,RFCN这四种都属于两步走的方法,先找到图片中有可能是物体的框子,然后再确定框子里是什么,并且精修框子的位置
  • yolo,yolo V2,SSD都属于一步到位,通过一个神经网络一次性给出框子的坐标和框子里的东西是什么

相对来说faster RCNN和RFCN的精度是比较高的,但因为分两步走,所以检测的耗时偏长,yoloV2和SSD的精度较faster RCNN和RFCN略微偏低,但可以速度快,可以满足实时性要求。
关于几种方法的对比,可以参考谷歌最近出的一篇论文,里面详细比较了faster RCNN,RFCN和SSD的精度和性能,链接:https://arxiv.org/abs/1611.10012
下面我们一一说明每种方法的步骤和原理,这部分会假设读者已经了解像VGG,ResNet这样的卷积神经网络,不然就会云里雾里了。此外这是一份总结,会给出每个算法的框架和其中一些不易理解的点,但不会详细描述具体的网络细节,关于网络细节在网上已经有很多很好的博客可以参考。

先从把深度学习带入目标检测的开山之作RCNN系列开始。

RCNN,fast RCNN,faster RCNN这三种方法是一脉相承的,从名字就可以看出,速度越来越快,同时准确度也越来越高。
下面是一张RCNN的整体架构图:
这里写图片描述
VOC数据集中的图片是大小不一的,所以在RCNN中首先会把图片缩放到固定尺寸(227x227),接着通过selective search的方法找到图片中有可能是物体的2K个候选框(ROI),再把这些候选框依次送入CNN进行特征提取输出固定长度的向量,把这些向量输入SVM分类器,注意这里有20个SVM的二分类器,用来判断这个ROI是某一类还是背景,并且会对这个ROI的bbox进行回归,以精修位置(下面细说),最后通过非极大抑制去除重复框住物体的框,留下最准确的框。
RCNN的步骤十分清晰,每一步要做什么也很明白。
对selective search感兴趣的话可以查看相关论文,这里不做解释,因为这个方法在faster RCNN中就已经不用了。这里只要知道它输入是一张图片,输出是一堆这张图片中有可能是物体的候选框。
CNN提取特征部分是把每个ROI作为输入,经过一系列卷积+pooling后接一个全连接层把不同大小的ROI计算成一个固定长度的向量。
对每个ROI使用SVM进行分类时,这里SVM的训练数据和前面CNN的训练数据是不一样的,因为训练CNN需要大量数据,所以对候选框的选择设定了一个比较宽泛的范围,比如把和真实框(GT:ground truth)IOU大于0.3的都设定为正样本,而在训练SVM分类器时,由于传统算法对数据中的噪音比较敏感,所以把和GT的IOU大于0.5的作为正样本,设定了一个更严格的阈值。
至于为什么用SVM而不用softmax,作者认为这样准确率更高,但在后续的算法中都不再使用SVM了。
对于边界回归(bbox-rg),可以看下面这张图,图中P框(蓝色)为经过selective search输出的一个预测框,G为真实框(红色), G^ 为经过回归后更接近真实框的最终预测输出框(黑色)。
深度学习在目标检测中的应用及其tensorflowAPI实践(一)_第5张图片
边界回归就是要把P框回归到 G^ 框。要做到这样的变换,只需要两步:平移和缩放,操作如下:
记这三个框为: P:(Px,Py,Pw,Ph) , G:(Gx,Gy,Gw,Gh) , G^:(G^x,G^y,G^w,G^h) ,这里的下标x,y表示目标框中点的坐标,w,h表示目标框的宽度和高度,对于G需要根据数据集中的label给定的顶点坐标做转换。
第一步平移,记横向和纵向的平移量分别为 Δx Δy ,可以用如下公式来表示:

Δx=Pwdx(p),Δy=Phdy(p)

这样可以得到 (G^x,G^y) :
G^x=Pwdx(p)+Px,G^y=Phdy(p)+Py

第二步尺寸缩放,可以按照如下操作:
G^w=Pwedw(p),G^h=Phedh(p)

从上面的变换公式可以看出,只要学习 dx(p),dy(p),dw(p),dh(p) 这四个参数即可确定回归后的box.
因此在做bbox-rg时,只需要将前面CNN提取出的固定长度向量作为输入,来学习 dx(p),dy(p),dw(p),dh(p) 即可。
RCNN在训练时,由于selective search输出的2000个框有大量的框都是没有目标的,即为负样本,所以在实际训练时会通过抽样的方式保持正负样本的比例在1:3,同时训练使用的CNN网络为在ImageNet上预训练过的分类网络。

RCNN的步骤很繁琐,但每一步要做的事很简单。这里面在用selective search生成2K个候选框后,里面会有大量的重叠,这样的话在CNN部分就会有很多重复的操作,极大的浪费了时间,于是fast RCNN在这方面做了优化。

fast RCNN的第一步生成候选区和RCNN一样,使用了selective search的方法,和RCNN不一样的是CNN部分不是把每个ROI依次输入网络,而是把整张图片一次性输入网络,这样重叠的ROI只会进行一次卷积操作,节省了时间,整体架构如下图:
深度学习在目标检测中的应用及其tensorflowAPI实践(一)_第6张图片
从以上流程图可以看出,理解fast RCNN的关键就在第三个框,经过第二步后我们得到的是图片经过卷积的feature map,此时根据selective search输出的2K个ROI,找到feature map上对应的区域,这部分ROI的大小是不一样的,而后面要连接的是全连接层,因此必须把尺寸做到一样大,所以使用了ROI pooling技术。
先看ROI pooling,稍后会解释每个ROI传递给后面的全连接层这部分的反向传播是怎么做的。
ROI pooling 一点都不神秘,pooling的过程和常规的2x2 pooling或者3x3 pooling是一样的,只不过这个2和3在变,比如说pooling后你要得到7x7xchannel的尺寸,当前这个ROI对应到feature map上的尺寸为14x14xchannel,那么就对这个ROI做2x2的pooling,如果是21x21xchannel就是3x3的pooling,依次类推。
对比RCNN,RCNN把一个ROI编码到一个固定长度的向量,送入SVM做分类,并作box-rg,fast RCNN也有这样的操作,只不过是通过ROI pooling把一个ROI做成一个固定大小的feature map,接下来的操作类似,在这个固定大小的feature map后连接全连接层。这个全连接网络是一个学习多任务的网络,输出当前ROI中的类别并作bbox-rg。
这里的多任务学习最后分出两个任务,一个softmax,用以区别当前这个ROI是什么东西,另一个任务是box-rg.
多任务的学习就要用到多任务的损失函数,我们用损失函数来解释这个多任务是怎么做的,fast RCNN的损失函数设置如下:

L(p,u,tu,v)=Lcls(p,u)+λ[u1]Lloc(tu,v)

上式中,前半部分表示softmax损失,后半部分表示box-rg损失,其中 u=0 表示为背景,因此背景ROI不参与box-rg的损失。
两个任务的输出层分别为: p=(p1,p2...pK+1) K 表示分类个数,因此是一个K+1的softmax多分类,其中1为背景 , tk=(tkx,tky,tkw,tkh) (x,y,w,h) 和RCNN中的定义一样,上面的损失函数拆解开就是:
Lcls(p,u)=log(Pu)

Lloc(tu,v)=i(x,y,w,h)smoothL1(tuivi)

式中, v=(vx,vy,vw,vh) 是真实的平移缩放参数, tu=(tux,tuy,tuw,tuh) 是预测的平移缩放参数,
smoothL1(tuivi)={0.5x2|x|0.5 if |x|1 if other

现在fast RCNN从头到尾似乎都顺了,从selective search到CNN提取特征,再到ROI pooling 后接全连接网络,多任务学习,但有个地方似乎还有点问题,从ROI pooling到全连接的前向传播好理解,但训练时的反向传播是如何进行的呢?
要知道 ROI pooling的反向传播是怎么做的,首先要知道一般的kxk pooling反向传播是怎么做的,以2x2 maxpooling为例,反向传播时,如下图,左边是pooling前的feature map,右边是pooling后的feature map(因为是maxpooling所以就是选择最大的),那么在反向传播时,左边feature map中最大值(黄色)的那个位置梯度为1,其余为0。
深度学习在目标检测中的应用及其tensorflowAPI实践(一)_第7张图片
这里可能会有人有疑问,如果只有一个格子的梯度是1,其余都是0的话,那不是其余格子前面的层参数都不更新了?在这次迭代中,前面那些参数确实是不更新了,但要注意每次迭代黄色那个最大值的位置都是会发生变化的。
接下来再说ROIpooling时的梯度是如何传播的,如下图所示,由于两个ROI(红色圈出的做2x2 maxpooling,蓝色圈出的做3x3 maxpooling)在做pooling时最大值都在黄色的点上,所以对于一张图片在一次反向传播时,就会把这个点对两个ROI的梯度相加后再传回去,对其他点也是一样的道理。
深度学习在目标检测中的应用及其tensorflowAPI实践(一)_第8张图片
fast RCNN相较RCNN,对整张图片只进行了一次卷积操作,避免了大量的重复计算,速度和精度都有了很大的提高,但仍然很慢,并且第一步的selective search属于传统方法。
接下来的faster RCNN把目标检测完全带入了深度学习,提出RPN网络通过深度学习的方法取代了selective search。
关于faster RCNN及后续内容在下一篇博客里继续写。 戳这里>>>
持续更新中~

你可能感兴趣的