前言:
个人之前只是简单做过人脸检测,只是项目需要,其实真正让我兴趣的,应该是目标检测,不过说实话,人脸检测也只是目标检测的一个小分支。这两年目标检测的快速进步,甚至已经到了落地实用的地步,不得不说前景广阔。嘿嘿,言归正传。
今天我只是把我之前看的目标检测系列论文总结一下,当然也参考了某些大牛的博客,以供参考:
目标检测:简单理解就是给定一张图像,将该图像中的目标位置检测出来,同时给定目标的类别。如下图:
深度学习从14开始,一时风靡了整个学术界,这无疑得益于在图像识别方面的伟大进步,其实说到底应该是卷积神经网络的再次兴起。因此,这篇文章我也是从四个方面来简单叙述一下目标检测的发展:
- 传统目标检测的一般流程和方法(其实也就是模式识别的方法)
- 以R-CNN为代表的基于深度学习的目标检测框架(RCNN,SPP-NET,FAST RCNN, Faster rcnn)
- 以YOLO为代表的将检测为题转换为回归问题的目标检测框架(YOLO,SSD,YOLO9000)
- 最后是做一个简单的总结
1、传统的目标检测方法流程
一般目标检测的传统做法分为三个部分:区域选择,从一张图像中选取目标候选区域。特征提取,即利用人工设计的特征对目标区域进行特征提取,分类器分类,即将抽取到的特征送到分类器中进行训练(比如:SVM)
区域选择:典型的做法就是Sliding Window, 这种穷举的方法虽然能够基本上遍历所有目标可能出现的位置,但是缺点就是复杂度太高,冗余窗口太多,而且目标大小一般是固定比例的,一单是多目标且目标大小比例变化很大,这种方法效果就会很差,当然该方法仍然有可取之处,就是你不在设计复杂的特征找到这些目标窗口了,尤其是当目标图像不是很大的时候,暴力解决反而更方便。
特征抽取:这种方法主要是就是要考虑目标的姿态、场景的影响(光照、遮挡等)、复杂背景等因素,因此设计一种鲁棒性的特征是可取的,比如SIFT,hog,lbp等。
分类器分类:抽取到特征之后,送到训练好的分类器中分类,判断是那种目标,典型做法就是SVM。当然adaboost 也算其中之一,但两者思想是有区别的。
总结:传统做法的缺点就是:1、候选区域选取复杂度高,冗余计算严重,计算资源被严重消耗。2、设计一种复杂的鲁棒性的特征是困难的,没有通用的特征可以直接拿来使用。
针对以上不足,CNN的出现就刚好填补了以上不足。
2、基于DL的目标检测算法的进展
首先是基于候选区域选择部分,region proposal 方法应运而生,相对于滑动窗口枚举的方法来说,RP方法则是利用了图像中纹理、边缘、颜色等信息,选取图像中尽可能是目标的区域,该方法有效地降低了候选区域的枚举数量,而且保证了很高的召回率。典型算法有selective search 和edge boxes。
解决第二个问题就是特征抽取问题,这个才是CNN牛逼的本质,在于其强大的特征抽取能力,当然,这首先要归功于imagenet上的图像识别大赛,cnn方法一举拔得头筹,奠定了cnn在图像处理的地位。因此,从2014年开始,目标检测大牛RBG基于以上两种方法结合传统的SVM,开启的目标检测的新时代。
1、R-CNN
核心思想: selective search + CNN + SVM
方法流程如图所示:
1、输入一张测试图像。
2、利用SS 方法进行候选区域选择,大概抽取2K个候选区域。
3、候选区域归一化,送到CNN当中,抽取特征。
4、将抽取到的特征进行SVM分类。
RCNN提出一举将目标检测中的mAP有了一个质的提升。
缺点不可避免:
1、多阶段训练。fineturn VGG + 训练SVM + 边框回归器。
2、训练耗时。
3、速度慢。尽管map提升了很大,但是距离实时还有很大差距。(一张图像在40s左右)
2、SPP-NET
还是考虑R-CNN的框架设计,为什么速度那么慢呢,选择性搜索实际耗时应该在2s左右,特征抽取基于GPU来说应该是毫秒级的,最后SVM分类,速度上分析不应该慢这么多?
因此,回归到框架当中,提取到候选区域,将每一个候选区域都当做一张图像送进CNN当中,那么2K个候选区域需要2K次特征抽取和SVM分类。实际上这2k个区域都来自同一张图像。因此,考虑能否只对图像抽取一次特征,然后将目标区域映射到卷积特征上,然后在目标区域的卷积特征送到全连接层上进行后续处理,因此,这样就极大减少了重复的计算量。避免了2k次的卷积特征抽取操作。
但是,在实际操作的过程中遇到了一个问题,由于目标候选区域尺度不一样,比如一个cat的目标区域和一个人的目标区域,两种区域比例大小明显差别很大,对于全连接层来说,送到全连接层的卷积特征的维度是统一的,因此,这就产生一个问题,不同区域的卷积特征维度不一致。SPP-NET就刚好解决了这个问题。
如图所示,spp-net网络结构如图所示,任意给定一张图像,进行CNN特征抽取,得到卷积特征,图中window就是原图中一个region proposal 对应的特征区域,将这些不同大小的window的特征映射到同样的维度,然后送到全连接层进行后续操作,这样就保证对图像只进行一次特征抽取操作,SPP-net即图像空间金字塔操作,例如,将图中的window划分成4*4,2*2,1*1的block,对每一个block使用max-pooling操作,就可以得到一个长度为(4*4+2*2 + 1)*output维度的特征向量,然后送到全连接层操作。
总结:SPP-net其实就解决了检测过程中的特征抽取部分的速度瓶颈,但是整体框架仍然有很大的提升空间。
3、FAST R-CNN
框架如下:
如图所示,fast rcnn的框架主要有两点区别:一个是ROI pooling layer的添加,另外就是多任务损失函数的使用。
1、ROI pooling 实际是SPP-NET 的精简版,SPP是构建一个金字塔映射,而ROI layer则是仅仅pooling一个7*7的特征map。这样就对应一个7*7 * output维度的feature vector 作为全连接层的输入。
2、对于多阶段训练问题,fast-rcnn中直接使用softmax代替了SVM进行特征分类,同时加入多任务损失函数到网络当中,这样整个训练过程中是端到端的。当然除了前面region proposal阶段。
3、fast rcnn中在网络fineturn的过程中,将部分卷积也进行了fineturn,使检测精度进一步提高。
缺点:1、fastrcnn的提升主要集中在后端特征处理上面,改进之后完全在GPU上就可以搞定,这样时间就大幅度的降低,但是前面RP阶段,时间耗费2-3s这个过程对于实时来说还是无法满足需要。因此,有没有方法进一步在RP阶段进行提速呢??
因此,faster rcnn 就出现来解决这个问题。
4、faster rcnn
region proposal + cnn 分类这种目标检测框架的根本取决于RP阶段候选区域结果产生的好坏。简单来说,就是前面那些改进直接解决了目标分类问题,而这个问题的前提是能够得到该目标的候选区域,比如说,如果候选区域选择的不好,或者是根本就没有包含目标区域的位置,这样,后面特征提取分类在好,对于最终结果都没有什么用。因此,region proposal 方法仍然在目标检测中占据主要的位置。
前面说道了selective search 方法,该方法能够很好的选择候选区域,同时还有效减少了冗余窗口的产生,但是,缺点有很明显,该方法是是独立于后面的分类系统的,并且时间耗费仍然很严重。为了尽量满足实时,有没有好的方法来替换掉呢??RBG大牛有给我们肯定的答案:即RPN网络。
RPN的框架如图所示:
思路描述:所谓的RPN,重点还是集中在Net上面,即将这部分同样用CNN来完成,但其本质思想仍然sliding Window 的思路,RPN设计相当巧妙,仅仅在最后的卷积层上滑动一次,就可以得到候选区域位置,当然里面加入了anchor机制和边框回归,这样就得到了不同尺度的region proposal。
如上图所示,输入一张图像(假定是600*1000,基于ZF模型),经过卷积操作得到最后一层卷积特征大小为(40*60).在这个特种图上经过使用3*3的卷积核与特征图进行卷积,最后一层卷积共有256个feature map, 最后我们得到一个256维的feature vector,后面接分类层和回归层进行分类(强调,这里分类只有背景和目标两类)和边框回归。3*3滑框对应的每个特征区域同时预测输入图像三种尺度(128,256,512),尺度分别是1:1,1:2,2:1.这种机制称为anchor。这样对于40*60的feature map,大概需要预测40*60*9个author。这样总共大概产生2W个region proposal。
优点总结:1、卷积操作上的滑动窗口,较原始图像来说,明显降低了特征维度。多尺度操作,尽可能的获取region Proposal的实际位置。
当然这个过程同样采用了多阶段训练模式,其最终效果就是在保证mAP的同时,使检测速度达到了5fps。
总结:faster rcnn实际就是将之前的RP和cnn组合起来,真正实现了端到端的检测,使实时目标检测成为了可能,但是距离实际应用还有一段距离。
为了让实时真正成为可能,YOLO的出现则真正成为了可能。
基于回归的目标检测算法
1、YOLO you only look once: untified real-time object detection.
直接打出实时目标检测(嘿嘿,可见对其算法的自信)
流程简介:看上图
1、给定一张图像,将图像划分为7*7的网格
2、对于每个网格,直接预测目标的置信度和目标类别。
3、每个网格负责预测两个边框,那么总共就需要预测7*7*2个目标窗口,然后用NMS去除冗余窗口。
其网络结构如图所示:
从中可以看出,yolo参考了Googlenet,只是在最后两层上,卷积之后接一个全连接层,然后又全连接到7*7*30维的张量上,实际上这个就是7*7的网格数,现在每个网格预测目标的位置以及目标的置信度和类别,也就是每个网格预测两个目标,每个目标信息有4D坐标信息,(center+H+w),1个目标置信度以及类别数,总共就是(4+1)*2+20 = 30D的向量。这样可以利用前面4096D的全图特征直接在每个网格上回归目标检测的信息。(这些都是之前做检测时分析yolo代码得出的,顺带参考了部分其他博客的介绍)
总结:
1、yolo将目标检测转换为了一个回归问题,加快了检测速度,使得可以达到45fps。
2、由于直接使用全图信息,使得误检比例大大降低。
缺点:1、没有了RP操作,定位不准确是必然的。
2、检测目标的数目被限制,这一点从上面网络预测的分析可以看出。
SSD(single shot multibox detector)
如图:SSD框架。
SSD获取目标位置和类别的方法跟yolo一样,都是基于回归直接预测,但是yolo是基于全图特征,而SSD则是借鉴faster rcnn的RPN思想,使用局部特征,最大的改进是引入了特征的多尺度来进行author的回归。其目的就是能更精准的对目标位置进行预测,这样既保证了速度有保证了精度。
最新的应该是今年的yolo9000,且还是CVPR2017的特别展示文章,一张表查看yolo和yolo9000的区别:
YOLO2主要集中在分类的准确率和定位的精度上面的改进。这主要归功于YOLO2网络结构的改进和训练技巧的使用。
比如说:BN层的使用,增大原始图像的分辨率,改进author BOX等以及fine-grained feature使用等等,以及多尺度训练技巧等。详细过程,大家可以参考论文。
总结:目标检测的发展可以简单归结为两个方面:
1、算法上的改进
2、训练技巧上的改进
算法上:
1、CNN卷积图特征使用,使得在目标分类和识别上性能得到了极大的提升。
2、整体检测框架的统一,将检测和识别统一到CNN中,使得端到端学习成为可能,速度和精度都得到了很大提高。
技巧上:
1、硬样本挖掘。这是RBG大牛的训练技巧的改进,却单独成为目标检测的一个工作,足见其可借鉴之处。
2、多层特征融合。这是CNN特征的有效使用,将高层语义特征和底层纹理特征融合一起,提高检测的精度。
3、上下文信息。这个实际上来说,并不是很明显,但是其思想倒是可以借鉴。
[1].
[2].
[3].
[4].
[5].