Talk is cheap, show me the code. -- Lucas Jin
这篇文章讲述,如何使用框架,从0实现yolo检测算法,这对于我们掌握目标检测原理大有俾易。
yolo输出的是什么?
这是一个要思考的问题,它实现上,将图片分为7x7的grid cell,每个cell负责预测出若干个box,它的输出是这样的:
image.png这就有一个问题了,如果groud truth的中心点就在第一个cell怎么办?它的左上角坐标是0呀。
这是疑问一,再者,yolo其实最终输出的矩阵维度是 SS(B*5 + C), 这个意思是,每个cell负责预测两个框,这B个框实际上是同一个物体的两个狂 (这里就是疑问二,不同的两个物体,难道就不可能中心点刚好在一起?),5代表的是坐标点和objectness,C代表的事C个类别是哪种物体的概率,那这个设计就有问题了,你B个框一定是同一个物体?,不一定吧。
比起疑问一,疑问二更加是设计的问题了,不知道有没有人与我同一个想法,这个问题是致命且不可理解的。
关于疑问一,仔细看,有这么一个将标注转换为GT的函数:
def convert(size, box):
dw = 1./(size[0])
dh = 1./(size[1])
x = (box[0] + box[1])/2.0 - 1
y = (box[2] + box[3])/2.0 - 1
w = box[1] - box[0]
h = box[3] - box[2]
x = x*dw
w = w*dw
y = y*dh
h = h*dh
return (x,y,w,h)
仔细看,size[0] 难道不可能是0?是0你怎么处理。。
其实还没有实现就暴露除了yolo检测系统设计的两个缺陷:
1). 一个cell只能预测同一种物体的多个框,如果是中心点落在同一个cell的多个不同物体,它肯定预测不出来了;
2). 加入groudtruth就在地一个cell或者第一行cell,我估计它会直接忽略。
二画不多说,可以i先实现一下,然后我们自己来改进它,黑嘿嘿。
实现
最复杂的部分应该是实现loss函数,这个loss函数,就是 处理 网络最终输出的 7x7x(B*5 + C) 的矩阵与groudtruth 之间的关系。
image.png每一个cell中预测值与gt之间方差的总和。其中l_ij的计算方式,为:
- 如果第i个cell存在目标,则这一项为有效值,即此时值为1;
- 如果第i个cell没有目标,也就是说没有groudtruth,则此项无效,此时值为0;
这一项中,对宽高的处理也是一样的,有groudtruth,则为1,否则为0。
image.png改项理解比较麻烦,简单来说,我们需要得到每一个cell对应的B个box的confidence,当这个cell有目标的时候,此时我们希望这个confidence越大越好,(IOU越大越好),如果这个cell没有目标,我们希望这个confidence越小越好,此时,这个等试子就可以很好惩罚我们不想要得结果。
image.png第i个cell中所有的B个box所预测出来的confidence的平方差,这个平方差是用来做什么的呢?我的想法,让这B个box预测出来同一个目标。。。。。但是这就带来一个问题,更加使得同一个cell多个物体预测变得不可能实现。。。。貌似在yolov2中,这个问题通过anchor方式解决了它,其实这里的B个box其实就是anchor,差不多的意思。
理论上,这个loss函数分为4个部分。
接下来需要进行实际的实现了。实现分为两个步骤:
1)计算 objects tensor:
我们需要计算一张图上,7x7的网格,每个网格是否包含目标,比如,最终需要的矩阵形式为:
[[0. 1. 1. 1. 0.]
[0. 1. 1. 1. 0.]
[0. 1. 1. 1. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
- 计算 responsible tensor
计算图中所有gt box的中心点所落在的cell,此时这个cell负责预测目标,我们需要得到的结果是:
[[0. 0. 0. 0. 0.]
[0. 0. 1. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
先去吃个饭,未完待虚...
网友评论