PASCAL VOC 数据集:https://blog.csdn.net/baidu_27643275/article/details/82754902
yolov1阅读笔记:https://blog.csdn.net/baidu_27643275/article/details/82789212
yolov1源码解析:https://blog.csdn.net/baidu_27643275/article/details/82794559
yolov2阅读笔记:https://blog.csdn.net/baidu_27643275/article/details/82859273
YOLOv2–k_means方法:
https://blog.csdn.net/baidu_27643275/article/details/88673185
yolo_weights_convert:https://blog.csdn.net/baidu_27643275/article/details/83189124
yolov3阅读笔记:https://blog.csdn.net/baidu_27643275/article/details/82964784
yolov3源码:https://github.com/1273545169/object-detection/tree/master/yolo_v3
本文先简单
再从yolo v1基本思路、网络结构、网络训练、网络预测、总结 几个方面对yolo进行讲解。
yolo之前的检测系统,比较有代表性的是DPM和R-CNN系列。
DPM使用滑动窗口的方法(在整张图片的均匀间隔区域内使用分类器)
R-CNN先选取候选区域,然后在ROI进行分类和回归。
yolo把目标检测当做回归问题来处理,直接从图像中得到bounding box和类别概率。
yolo v1 将一张图片分为 S × S S×S S×S个网格,每个网格负责预测中心点落在此网格内的目标。
每个网格会预测 B B B个bounding box, C C C个类别概率值。
每个bounding box预测5个值 ( x , y , w , h ) (x,y,w,h) (x,y,w,h)以及 o b j e c t c o n f i d e n c e object confidence objectconfidence
一张图片的预测结果有 [ S × S × ( 5 ∗ B + C ) ] [S×S×(5*B+C)] [S×S×(5∗B+C)]个值。
在PASCAL VOC 数据集上评估模型, S = 7 , B = 2 , C = 20 S=7,B=2,C=20 S=7,B=2,C=20,最终得到7×7×30的tensor。
如下图所示:狗的中心在红色网格内,由该网格来负责预测这只狗。
每个 b o u n d i n g b o x bounding box boundingbox的大小和位置可以通过 ( x , y , w , h ) (x,y,w,h) (x,y,w,h)四个值来表示,其中 ( x , y ) (x,y) (x,y)的值是相对于每个网格的, ( w , h ) (w,h) (w,h)的值是想对于整张图片的。
c o n f i d e n c e confidence confidence 中 P r ( O b j e c t ) Pr(Object) Pr(Object) 的取值为0或者1.
若目标的中心在网格内,则 P r ( O b j e c t ) Pr(Object) Pr(Object) 的取值为1;
若目标的中心不在网格内,则 P r ( O b j e c t ) Pr(Object) Pr(Object) 的取值为0;
注意: 必须是目标的中心在网格内,若仅仅只是目标的一部分在网格内, P r ( O b j e c t ) Pr(Object) Pr(Object) 的取值仍然为0。
如果网格中存在目标,则 c o n f i d e n c e confidence confidence = I O U IOU IOU,否则 c o n f i d e n c e confidence confidence值为0
整个网络先使用卷积层进行特征提取,再通过全连接层进行分类和回归。
网络的构思来自GoogleNet,网络由24层卷积+2层全连接层组成。在3×3的卷积后面加上1×1卷积来降低feature map的空间大小,从而较少网络的参数和计算量。
使用PASCAL VOC 数据集来评估模型,所以网络的最后输出为7×7×30=1470。
网络的训练分为2部分:
(1)预训练一个分类网络:使用上述网络的前20个卷积层+average-pool+全连接层在ImageNet进行训练,网络输入为(224×224×3)。
(2)训练检测网络:移除预训练网络中的后两层,再在预训练网络的基础上+4层卷积层+2层全连接层,将网络的输入变为(448×448×3)。
提高分辨率从而获得细粒度的特征。
增加4层卷积层是为了提取到的特征更好,提高网络的性能。
网络的最后一层全连接层使用线性激活函数,其它层均使用leaky Relu激活函数。
最后一层的输出:
bbox中的值为 ( x , y , w , h ) (x,y,\sqrt{w},\sqrt{h}) (x,y,w,h),这四个值均被归一化到0~1, ( x , y ) (x,y) (x,y)相对于网格, ( w , h ) (\sqrt{w},\sqrt{h}) (w,h)相对于整张图。
为什么将 ( w , h ) − > ( w , h ) (w,h) -> (\sqrt{w},\sqrt{h}) (w,h)−>(w,h) ?
实际上较小的边界框的坐标误差应该要比较大的边界框要更重要、更敏感。为了保证这一点,将网络的边界框的宽与高预测改为对其平方根的预测
loss函数
我们使用SSE来优化模型
一个网格中会预测多个bbox,在训练时,只选择IOU最大的那个bbox来负责预测目标,其他bbox的 P r ( O b j e c t ) Pr(Object) Pr(Object)值被设为0。这个操作使得bbox的预测更加专业,提高整体的recall。
1 i j o b j 1_{ij}^{obj} 1ijobj: 如果网格 ( i ) (i) (i)个内存在目标, 1 i j o b j 1_{ij}^{obj} 1ijobj则表示网格 ( i ) (i) (i)内的第 ( j ) (j) (j)个bbox负责预测目标。
不同的部分采取不同的权重,其中, λ c o r d = 5 \lambda_{cord}=5 λcord=5 ; 因为大部分网格中没有目标,所以 λ n o o b j \lambda_{noobj} λnoobj的值设置的小一些, λ n o o b j = 0.5 \lambda_{noobj}=0.5 λnoobj=0.5
第三步详细过程如下:
对于98个boxes,首先将小于置信度阈值的值归0,然后分类别地对类别置信度值采用NMS。
non_max_suppression
一个目标可能有多个预测框,通过NMS可以去除多余的预测框,确保一个目标只有一个预测框。NMS是通过类别置信度来筛选的。
c l a s s class class c o n f i d e n c e confidence confidence 计算公式如下:
其中, P r ( O b j e c t ) ∗ I O U p r e s d t r u t h Pr(Object)*IOU_{presd}^{truth} Pr(Object)∗IOUpresdtruth 为bbox置信度 ; P r ( C l a s s ∣ O b j e c t ) Pr(Class|Object) Pr(Class∣Object)为类别概率。
原理: 首先从所有的预测框中找到置信度最大的那个bbox,然后挨个计算其与剩余bbox的IOU,如果其值大于一定阈值(重合度过高),那么就将该剩余bbox剔除;然后对剩余的预测框重复上述过程,直到处理完所有的检测框。
def _non_max_suppression(scores, boxes):
"""Non max suppression"""
# https://github.com/xiaohu2015/DeepLearning_tutorials/blob/master/ObjectDetections/yolo/yolo.py
# scores :[S*S*B, C] ; boxes:[S*S*B, 4]
# for each class
for c in range(self.C):
sorted_idxs = np.argsort(scores[:, c])
last = len(sorted_idxs) - 1
while last > 0:
# scores[sorted_idxs[last], c]为一个类中scores最大的值
if scores[sorted_idxs[last], c] < 1e-6:
break
for i in range(last):
if scores[sorted_idxs[i], c] < 1e-6:
continue
# 将两个bbox的IOU值 与 iou_threshold 进行比较
if cal_iou(boxes[sorted_idxs[i]], boxes[sorted_idxs[last]]) > self.iou_threshold:
scores[sorted_idxs[i], c] = 0.0
last -= 1
def cal_iou(box1, box2):
box1_ = [box1[0] - 0.5 * box1[2], box1[1] - 0.5 * box1[3],
box1[0] + 0.5 * box1[2], box1[1] + 0.5 * box1[3]]
box2_ = [box2[0] - 0.5 * box2[2], box2[1] - 0.5 * box2[3],
box2[0] + 0.5 * box2[2], box2[1] + 0.5 * box2[3]]
lu = tf.maximum(box1_[:2], box2_[:2])
rd = tf.maximum(box1_[2:], box2_[2:])
intersection = tf.maximum(rd - lu, 0)
inter_square = intersection[0] * intersection[1]
union_square = box1[2] * box1[3] + box1[2] * box1[3] - inter_square
return inter_square / union_square
yolo误差主要来自定位不准确
1、the entire model is trained jointly,训练简单;速度快、实时检测
2、泛化性能好,可以推广到新的领域
3、YOLO先对整张图片做卷积再同时预测bbox和类别概率,看到的视野更大,能够减少将背景错认为目标的概率,即reduce the errors from background false positives
1、每个网格只能预测一个目标,所以对于相邻目标的预测效果不好
2、小目标预测效果不好
3、在新的或者不常见的方向比和配置 中泛化性能不好。
输入图片被划分为7x7个网格。网格只是物体中心点位置的划分之用,并不是对图片进行切片,不会让网格脱离整体的关系
下一篇将通过解析yolo源码加深对yolo算法的理解。
参考资料:
1、paper
2、论文翻译
3、yolo详解
4、ppt