图像识别之目标检测
Posted 人工智能与算法学习
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图像识别之目标检测相关的知识,希望对你有一定的参考价值。
目标检测可以理解为是物体识别和物体定位的综合,不仅仅要识别出物体属于哪个分类,更重要的是得到物体在图片中的具体位置。
为了完成这两个任务,目标检测模型分为两类。一类是two-stage,将物体识别和物体定位分为两个步骤,分别完成,这一类的典型代表是R-CNN, fast R-CNN, faster-RCNN家族。前面两章已经介绍了,他们识别错误率低,漏识别率也较低,但速度较慢,不能满足实时检测场景。为了解决这一问题,另一类方式出现了,称为one-stage, 典型代表是Yolo, SSD, YoloV2等。他们识别速度很快,可以达到实时性要求,而且准确率也基本能达到faster R-CNN的水平。下面针对one-stage进行详细的分析。
Yolo:you only look once
针对于two-stage目标检测算法普遍存在的运算速度慢的缺点,yolo创造性的提出了one-stage。也就是将物体分类和物体定位在一个步骤中完成。yolo直接在输出层回归bounding box的位置和bounding box所属类别,从而实现one-stage。通过这种方式,yolo可实现45帧每秒的运算速度,完全能满足实时性要求(达到24帧每秒,人眼就认为是连续的)。它的网络结构如下图
主要分为三个部分:卷积层,目标检测层,NMS筛选层
卷积层
采用Google inceptionV1网络,对应到上图中的第一个阶段,共20层。这一层主要是进行特征提取,从而提高模型泛化能力。但作者对inceptionV1进行了改造,他没有使用inception module结构,而是用一个1x1的卷积,并联一个3x3的卷积来替代。(可以认为只使用了inception module中的一个分支,应该是为了简化网络结构)
目标检测层
先经过4个卷积层和2个全连接层,最后生成7x7x30的输出。先经过4个卷积层的目的是为了提高模型泛化能力。yolo将一副448x448的原图分割成了7x7个网格,每个网格要预测两个bounding box的坐标(x,y,w,h)和box内包含物体的置信度confidence,以及物体属于20类别中每一类的概率(yolo的训练数据为voc2012,它是一个20分类的数据集)。所以一个网格对应的参数为(4x2+2+20) = 30。如下图
bounding box坐标: 如上图,7x7网格内的每个grid(红色框),对应两个大小形状不同的bounding box(黄色框)。每个box的位置坐标为(x,y,w,h), x和y表示box中心点坐标,w和h表示box宽度和高度。通过与训练数据集上标定的物体真实坐标(Gx,Gy,Gw,Gh)进行对比训练,可以计算出初始bounding box平移和伸缩得到最终位置的模型。
bounding box置信度confidence:这个置信度只是为了表达box内有无物体的概率,并不表达box内物体是什么。
其中前一项表示有无人工标记的物体落入了网格内,如果有则为1,否则为0。第二项代表bounding box和真实标记的box之间的重合度。它等于两个box面积交集,除以面积并集。值越大则box越接近真实位置。
分类信息:yolo的目标训练集为voc2012,它是一个20分类的目标检测数据集。常用目标检测数据集如下表
| Name | # Images (trainval) | # Classes | Last updated |
| ---------- | ------------ | -------| -------|
| ImageNet | 450k | 200 | 2015 |
| COCO | 120K | 90 | 2014 |
| Pascal VOC | 12k | 20 | 2012 |
| Oxford-IIIT Pet | 7K | 37 | 2012 |
| KITTI Vision | 7K | 3 | |
每个网格还需要预测它属于20分类中每一个类别的概率。分类信息是针对每个网格的,而不是bounding box。故只需要20个,而不是40个。而confidence则是针对bounding box的,它只表示box内是否有物体,而不需要预测物体是20分类中的哪一个,故只需要2个参数。虽然分类信息和confidence都是概率,但表达含义完全不同。
NMS筛选层
筛选层是为了在多个结果中(多个bounding box)筛选出最合适的几个,这个方法和faster R-CNN 中基本相同。都是先过滤掉score低于阈值的box,对剩下的box进行NMS非极大值抑制,去除掉重叠度比较高的box(NMS具体算法可以回顾上面faster R-CNN小节)。这样就得到了最终的最合适的几个box和他们的类别。
yolo损失函数
yolo的损失函数包含三部分,位置误差,confidence误差,分类误差。具体公式如下
误差均采用了均方差算法,其实我认为,位置误差应该采用均方差算法,而分类误差应该采用交叉熵。由于物体位置只有4个参数,而类别有20个参数,他们的累加和不同。如果赋予相同的权重,显然不合理。故yolo中位置误差权重为5,类别误差权重为1。由于我们不是特别关心不包含物体的bounding box,故赋予不包含物体的box的置信度confidence误差的权重为0.5,包含物体的权重则为1。
yolo算法开创了one-stage检测的先河,它将物体分类和物体检测网络合二为一,都在全连接层完成。故它大大降低了目标检测的耗时,提高了实时性。但它的缺点也十分明显
每个网格只对应两个bounding box,当物体的长宽比不常见(也就是训练数据集覆盖不到时),效果很差。
原始图片只划分为7x7的网格,当两个物体靠的很近时,效果很差
最终每个网格只对应一个类别,容易出现漏检(物体没有被识别到)。
对于图片中比较小的物体,效果很差。这其实是所有目标检测算法的通病,SSD对它有些优化,我们后面再看。
SSD: Single Shot MultiBox Detector
Faster R-CNN准确率mAP较高,漏检率recall较低,但速度较慢。而yolo则相反,速度快,但准确率和漏检率不尽人意。SSD综合了他们的优缺点,对输入300x300的图像,在voc2007数据集上test,能够达到58 帧每秒( Titan X 的 GPU ),72.1%的mAP。
SSD网络结构如下图
和yolo一样,也分为三部分:卷积层,目标检测层和NMS筛选层
卷积层
SSD论文采用了VGG16的基础网络,其实这也是几乎所有目标检测神经网络的惯用方法。先用一个CNN网络来提取特征,然后再进行后续的目标定位和目标分类识别。
目标检测层
这一层由5个卷积层和一个平均池化层组成。去掉了最后的全连接层。SSD认为目标检测中的物体,只与周围信息相关,它的感受野不是全局的,故没必要也不应该做全连接。SSD的特点如下
多尺寸feature map上进行目标检测
每一个卷积层,都会输出不同大小感受野的feature map。在这些不同尺度的feature map上,进行目标位置和类别的训练和预测,从而达到多尺度检测的目的,可以克服yolo对于宽高比不常见的物体,识别准确率较低的问题。而yolo中,只在最后一个卷积层上做目标位置和类别的训练和预测。这是SSD相对于yolo能提高准确率的一个关键所在。
如上所示,在每个卷积层上都会进行目标检测和分类,最后由NMS进行筛选,输出最终的结果。多尺度feature map上做目标检测,就相当于多了很多宽高比例的bounding box,可以大大提高泛化能力。
多个anchors,每个anchor对应4个位置参数和21个类别参数
和faster R-CNN相似,SSD也提出了anchor的概念。卷积输出的feature map,每个点对应为原图的一个区域的中心点。以这个点为中心,构造出6个宽高比例不同,大小不同的anchor(SSD中称为default box)。每个anchor对应4个位置参数(x,y,w,h)和21个类别概率(voc训练集为20分类问题,在加上anchor是否为背景,共21分类)。如下图所示
另外,在训练阶段,SSD将正负样本比例定位1:3。训练集给定了输入图像以及每个物体的真实区域(ground true box),将default box和真实box最接近的选为正样本。然后在剩下的default box中选择任意一个与真实box IOU大于0.5的,作为正样本。而其他的则作为负样本。由于绝大部分的box为负样本,会导致正负失衡,故根据每个box类别概率排序,使正负比例保持在1:3。SSD认为这个策略提高了4%的准确率
另外,SSD采用了数据增强。生成与目标物体真实box间IOU为0.1 0.3 0.5 0.7 0.9的patch,随机选取这些patch参与训练,并对他们进行随机水平翻转等操作。SSD认为这个策略提高了8.8%的准确率。
筛选层
和yolo的筛选层基本一致,同样先过滤掉类别概率低于阈值的default box,再采用NMS非极大值抑制,筛掉重叠度较高的。只不过SSD综合了各个不同feature map上的目标检测输出的default box。
SSD基本已经可以满足我们手机端上实时物体检测需求了,TensorFlow在android上的目标检测官方模型ssd_mobilenet_v1_android_export.pb,就是通过SSD算法实现的。它的基础卷积网络采用的是mobileNet,适合在终端上部署和运行。
YoloV2, Yolo9000和其他模型
针对yolo准确率不高,容易漏检,对长宽比不常见物体效果差等问题,结合SSD的特点,提出了yoloV2。它主要还是采用了yolo的网络结构,在其基础上做了一些优化和改进,如下
网络采用DarkNet-19:19层,里面包含了大量3x3卷积,同时借鉴inceptionV1,加入1x1卷积核全局平均池化层。结构如下
去掉全连接层:和SSD一样,模型中只包含卷积和平均池化层(平均池化是为了变为一维向量,做softmax分类)。这样做一方面是由于物体检测中的目标,只是图片中的一个区块,它是局部感受野,没必要做全连接。而是为了输入不同尺寸的图片,如果采用全连接,则只能输入固定大小图片了。
batch normalization:卷积层后加入BN,对下一次卷积输入的数据做归一化。可以在增大学习率的前提下,同样可以稳定落入局部最优解。从而加速训练收敛,在相同耗时下,增大了有效迭代次数。
使用anchors:借鉴faster R-CNN和SSD,对于一个中心点,使用多个anchor,得到多个bounding box,每个bounding box包含4个位置坐标参数(x y w h)和21个类别概率信息。而在yolo中,每个grid(对应anchor),仅预测一次类别,而且只有两个bounding box来进行坐标预测。
pass through layer:yolo原本最终特征图为13x13x256。yoloV2还利用了之前的26x26的特征图进行目标检测。26x26x256的feature map分别按行和列隔点采样,得到4幅13x13x256的feature map,将他们组织成一幅13x13x2048的feature map。这样做的目的是提高小物体的识别率。因为越靠前的卷积,其感受野越小,越有利于小物体的识别。
高分辨率输入Training:yolo采用224x224图片进行预训练,而yoloV2则采用448x448
Multi-Scale Training:输入不同尺寸的图片,迭代10次,就改变输入图片尺寸。由于模型中去掉了全连接层,故可以输入不同尺寸的图片了。从320x320,到608x608
yolo和yoloV2只能识别20类物体,为了优化这个问题,提出了yolo9000,可以识别9000类物体。它在yoloV2基础上,进行了imageNet和coco的联合训练。这种方式充分利用imageNet可以识别1000类物体和coco可以进行目标位置检测的优点。当使用imageNet训练时,只更新物体分类相关的参数。而使用coco时,则更新全部所有参数。
当前目标检测模型算法也是层出不穷。在two-stage领域,2017年Facebook提出了mask R-CNN。CMU也提出了A-Fast-RCNN 算法,将对抗学习引入到目标检测领域。Face++也提出了Light-Head R-CNN,主要探讨了 R-CNN 如何在物体检测中平衡精确度和速度。
one-stage领域也是百花齐放,2017年首尔大学提出 R-SSD 算法,主要解决小尺寸物体检测效果差的问题。清华大学提出了 RON 算法,结合 two stage 名的方法和 one stage 方法的优势,更加关注多尺度对象定位和负空间样本挖掘问题。
总结
目标检测领域的深度学习算法,需要进行目标定位和物体识别,算法相对来说还是很复杂的。当前各种新算法也是层不出穷,但模型之间有很强的延续性,大部分模型算法都是借鉴了前人的思想,站在巨人的肩膀上。我们需要知道经典模型的特点,这些tricks是为了解决什么问题,以及为什么解决了这些问题。这样才能举一反三,万变不离其宗。综合下来,目标检测领域主要的难点如下
检测速度:实时性要求高,故网络结构不能太复杂,参数不能太多,卷积层次也不能太多。
位置准确率:(x y w h)参数必须准确,也就是检测框大小尺寸要匹配,且重合度IOU要高。SSD和faster RCNN通过多个bounding box来优化这个问题
漏检率:必须尽量检测出所有目标物体,特别是靠的近的物体和尺寸小的物体。SSD和faster RCNN通过多个bounding box来优化这个问题
物体宽高比例不常见:SSD通过不同尺寸feature map,yoloV2通过不同尺寸输入图片,来优化这个问题。
靠近的物体准确率低。
小尺寸物体准确率低:SSD取消全连接层,yoloV2增加pass through layer,采用高分辨率输入图片,来优化这个问题。
文章转载资云栖社区,版权归属作者。如涉版权,请联系删。
以上是关于图像识别之目标检测的主要内容,如果未能解决你的问题,请参考以下文章
深度学习和目标检测系列教程 4-300:目标检测入门之目标变量和损失函数