This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
高能预警,前方将会有大量图片来袭!
根据 YOLO官网 对它的解释,YOLO:Real-Time Object Detection. You Only Look Once(YOLO)是一个最先进的实时的目标检测系统。在Pascal Titan X上面处理图像能够达到30FPS,在COCO test-dev上具有57.9%的 mAP。
说起目标检测系统,就要先明白,图像识别、目标定位和目标检测的区别。图像识别也可以说成是目标分类,顾名思义,目的是为了分类出图像中的物体是什么类别。目标定位是不仅仅要识别出是一种什么物体,还要预测出物体的位置,并使用bounding box框出。目标检测就更为复杂,它可以看作是图像识别+多目标定位,即要在一张图片中定位并分类出多个物体。
目标检测对于人类来说极为简单,经过上万年的进化,人类天生具有复杂的感知与视觉系统,这是机器无可比拟的,我们可以只对图片看一眼,即分辨出物体的种类和它相应的位置,根据先前的知识进行归纳,适应不同图像环境都是人类专属技能。但是对于计算机来说,一张图片只是具有无数RGB像素点的矩阵,它本身并不知道猫狗动物,大小形状的概念,如果再给它一张具有复杂自然场景背景的图片,想要检测出物体更是难上加难。但是是问题,总会有解决的办法。问题是由人类提出来的,当然还要靠人类的智慧来处理。面对这样的计算机难题,很多研究学者蜂拥而至,从此目标检测领域变成了非常热门的研究方向,当然也诞生出了许多的解决方法。
传统的目标检测方法大致分为三个步骤,先使用不同的方法(滑动窗口,区域候选)提取区域的特征图,然后再使用分类器进行识别,最后回归预测。大多数方法都较为复杂,速度较慢,训练耗时。
传统的方法可以按照检测系统分为两种:1
目前深度学习相关的目标检测方法大致可以分为两派:2
1、基于区域提名的(regin proposal)的,比如R-CNN、SPP-Net、Fast R-CNN、Faster R-CNN、R-FCN。
2、基于端到端(end to end)的,无需候选区域,如YOLO、SSD。
二者发展都很迅速,区域提名准确率较好、端到端的方法速度较快。
本文着重于介绍一下目标检测系统:YOLO
按照 YOLO:Unified,Real-Time Object Detection 中所说,YOLO检测系统简单直接,可以看做只有三步:
1、将一幅图像分成 S×S 个网格(Grid Cell),如果某个object的中心落在某个网格中(通过ground-truth框确定),则这个网格就负责预测这个object。
2、每个网格要预测B个bounding box,每个box除了要回归自身的位置之外,还要附带预测一个confidence值。这个值代表了所预测的bounding box中是否含有object和若有object,这个object预测得有多准的两重信息,计算方式:
P r ( O b j e c t ) ∗ I o U t r u t h p r e d Pr(Object) * IoU \frac{truth}{pred} Pr(Object)∗IoUpredtruth
如果有object的中心落在一个网格里面,*
的前第一项取1,否则取0。第二项是预测的边界框和ground-truth之间的IoU值。
3、每个网格单元针对20种类别预测bboxes属于单个类别的条件概率 P r ( C l a s s i ∣ O b j e c t ) Pr(Class_i | Object) Pr(Classi∣Object),属于同一个网格的B个bboxes共享一个条件概率。在测试时,将条件概率分别和单个的bbox的confidence预测相乘:
P r ( C l a s s i ∣ O b j e c t ) ∗ P r ( O b j e c t ) ∗ I o U t r u t h p r e d = P r ( C l a s s i ) ∗ I o U t r u t h p r e d Pr(Class_i | Object) * Pr(Object) * IoU \frac{truth} {pred} = Pr(Class_i) * IoU \frac{truth}{pred} Pr(Classi∣Object)∗Pr(Object)∗IoUpredtruth=Pr(Classi)∗IoUpredtruth
4、在Pascal VOC中,YOLO检测系统的图像输入为448×448,S=7,B=2,一共有20个class(C=20),输出就是7×7×30的一个tensor。这个是怎么算出来的呢?看下面详解。
YOLO使用了24个级联卷积层和最后2个全连接层,交替的1×1卷积层降低了前面层的特征空间。在ImageNet分类任务上使用分辨率的一半(224×224输入图像)对卷积层进行预训练,然后将分辨率加倍进行目标检测。
YOLO网络借鉴了GoogleNet的思想,但与之不同的是,为了更好的性能,它增加额外的4层卷积层(conv)。YOLO一共使用了24个级联的卷积层和2个全连接层(fc),其中conv层中包含了1×1和3×3两种kernel,最后一个fc全连接层后经过reshape之后就是YOLO网络的输出,是长度为S×S×(B×5+C)=7×7×30的tensor,最后经过识别过程得到最终的检测结果。
上文说到每个bounding box要预测(x,y,w,h,confidence)五个值,一张图片共分为S×S个网格,每个网格要预测出B个bounding box和一个网格负责的object的类别信息,记为C。
则输出为 S ∗ S ∗ ( 5 ∗ B + C ) S*S*(5*B+C) S∗S∗(5∗B+C)的tensor张量,(x,y)表示bounding box相对于网格单元的边界的offset,归一化到(0,1)范围之内,而w,h表示相对于整个图片的预测宽和高,也被归一化到(0,1)范围内。c代表的是object在某个bounding box的confidence。
使用下图更形象的说明,7×7×30的Tensor中的一个1×1×30的前10维的所代表的含义。
下面解释如何将预测坐标的x,y用相对于对应网格的offset归一化到0-1和w,h是如何利用图像的宽高归一化到0-1之间。
每个单元格预测的B个(x,y,w,h,confidence)向量,假设图片为S×S个网格,S=7,图片宽为 w i w_i wi高为 h i h_i hi:
每个grid cell对应的两个bounding box的5个值在tensor中体现出来,组成前十维。每个单元格负责预测一个object,但是每个单元格预测出2个bounding box,如图。
每个grid cell有30维,其中8维是两个预测回归bboxes的坐标信息,2维是bboxes的confidences,还有20维是与类别相关的信息。
每个单元格预测一个属于类别 c l a s s i class_{i} classi的条件概率 P r ( C l a s s i ∣ O b j e c t ) Pr(Class_{i} | Object) Pr(Classi∣Object)。要注意的是,属于一个网格的2个bboxs共享一套条件概率值,因为这两个box都是为了一个grid cell服务,最终预测出一个object类别。在测试时,将条件概率和单个bbox的confidence预测相乘:
P r ( C l a s s i ∣ O b j e c t ) ∗ P r ( O b j e c t ) ∗ I o U t r u t h p r e d = P r ( C l a s s i ) ∗ I o U t r u t h p r e d Pr(Class_{i} | Object) * Pr(Object) * IoU \frac {truth} {pred} = Pr(Class_{i}) * IoU \frac {truth} {pred} Pr(Classi∣Object)∗Pr(Object)∗IoUpredtruth=Pr(Classi)∗IoUpredtruth如上式所述,每个网格预测的类别概率乘以每个bbox的预测confidence,得到每个bbox的class-specific confidence score分数。对每个格子的每一个bounding box进行此运算,最后会得到7×7×2=98个scores,设置一个阈值,滤掉得分低的bboxes,对保留的bboxes进行NMS(Non Maximum Suppression)处理,最终得到目标检测结果。
最后得到第一个为最大的score值,找出针对dog这个种类预测出的对应框,记为bbox_max
。然后将它与其他分数较低的但不是0的框作对比,这种框记为bbox_cur
。将bbox_max
和bbox_cur
分别做IoU计算,如果 IoU(bbox_max, bbox_cur) > 0.5
,那么将bbox_cur
对应的score设为0。例如:
然后接着遍历下一个score,如果它不是最大的且不为0,就和最大的score对应的框座IoU运算,若结果大于0.5则,同上。否则它的score不变,继续处理下一个bbox_cur
……直到最后一个score,如图:
计算完一轮之后,假如得到score
序列:0.5、0、0.2、0.1 … 0、0、0、0
那么进行下一轮循环,从0.2开始,将0.2对应的框作为bbox_max
,继续循环计算后面的bbox_cur
与新的bbox_max
的IoU值,大于0.5的设为0,小于0.5的score不变。再这样一直计算比较到最后一个score。
得到新的的score
序列为:0.5、0、0.2、0 … 0、0、0、0
即最后只得到两个score不为0的框,如图:
经过这些NMS算法的处理,会出现很多框针对某个class的预测的score为0的情况。
最后,针对每个bbox的20×1的张量,对20种class的预测score进行判断。例如,
1)先取出针对bbox3的所有20个scores,按照类别的默认顺序找出score最大的那个score的index索引号(根据此index可以找出所属的类别)记为class
;
2)然后找出bbox3的最大score分数,记为score
。
3)判断score
是否大于0,如果是,就在图像中画出标有class
的框。否则,丢弃此bbox。
接下来进行下一个bbox的筛选,如图,则是bbox1,流程同上。一直到最后一个bbox97,
论文中损失函数的形式,一共分为四个部分,笔者分别对各个部分作了解析说明。
在此损失函数中,只有某个网格中有object的中心落入的时候才对classification loss进行惩罚。只有当某个网格i中的bbox对某的ground-truth box负责的时候,才会对box的coordinate error进行惩罚。哪个bbox对ground-truth box负责就看ground-truth box和bbox的IoU最大。
Loss相关解释:
实验数据比较好理解,详情见论文
Fast YOLO在Pascal数据集上速度最快,达到155FPS,而UOLO的mAP是最高的。
比较了YOLO和Faster R-CNN的错误情况,结果如图所示。
预测结果包括以下几类:
正确:类别正确,IOU>0.5
定位:类别正确,0.1
其它:类别错误,IOU>0.1
背景:任何物体,IOU<0.1
YOLO v1只是最初始的版本,定然有许多不足之处,现在已经发展到了YOLO v3,针对这些不足之处都有所改进。只希望本篇文章能够对入门者有所启发,接下来可能还会写有关YOLO v2,v3的讲解博客。
编写整理本文着实费了我不少时间,网上有很多讲解YOLO的资料,但大多比较混乱,所以想自己整理一份YOLO入门资料。一方面为了巩固梳理这几天学习的知识,记录下来以便以后回顾查找;另一方面是出于知识共享的想法,希望此文也能给别人带来好的帮助。为了更容易更形象的理解YOLO的网络与原理,本博客放入了大量的图片,图片出处在参考文档第一项给了出来。我参考了很多资料,也都一一列了出来,文中有些借鉴的地方甚至还用上标标注出。
庐山烟雨浙江潮,在深度学习的路上我还有很漫长的路要走,深知此文还有许多地方需要修正,以后有时间还会慢慢补充,现在YOLO已经发展了很多版本,接下来还得继续学习,路漫漫其修远兮,fighting!
PS:如有发现错误或不当之处,敬请指正,不胜感激。
[0]. You Only Look Once: Unified, Real-Time Object Detection
[1]. Google Doc
[2]. YOLO文章详细解读
[3]. YOLO算法详解
[4]. 目标检测YOLO原理
[5]. 目标检测(九)–YOLO v1,v2,v3
[6]. yolo报告
[7]. yolov1原文地址以及论文翻译
[8]. YOLO:实时快速目标检测
yolo报告 ↩︎
基于深度学习的目标检测 ↩︎
目标检测YOLO原理 ↩︎