刚开始yolo系列的目标检测算法,在一个网格中只能检测一个对象,但是我们在实验中发现,一个网格中很多时候存在不仅一个目标,可能存在多个目标,类似如下图所示,下面中间的网格中就存在人和车辆两个目标的中心点,因此如何检测出一个网格中存在的多个目标就成了我们需要研究的问题。Anchor Boxes的出现帮我们解决了这个问题。
对于如上图的情况我们输出向量的时候C1 C2 C3种类这块没法输出,因为里面有两个,人和车。
因此 Anchor Boxes的做法是我们建立两个Anchor Box,如下图所示:
当然目标更多的时候,你也可以建立更多,我们这里为了方便讲解,只构建两个,同时因为左边的那个更适合我们图片上的人的形状,因此左边的anchor box用来检测人,右边更适合汽车的形状,因此右边的anchor box用来检测汽车。(具体这个anchor box跟目标的适配过程是根据交并比的计算决定的,那个对象跟相应的anchor box的交并比更高就使用那个)。然后针对我们之前的输出向量只能表示一个目标,而导致检测不准确的情况,我们可以将两个向量堆叠到一起。如下图所示:
完成的Anchor Box输出过程:
在使用anchor box之前,3*3的网格,每个网格输出一个向量(即检测一个目标),每个向量有8个参数(这是因为我们设置的有3个对象,所以每个向量都是8维),即使一共要输出3*3*8个参数。
上述向量参数分别为 Pc:网格里是否存在目标对象,存在为1,不存在为0
bx为目标中心点的横坐标,by为目标中心点的纵坐标,bh为相对网格的纵向偏移程度,bw为横向偏移程度。
C1为行人 、C2为车辆、C3为摩托。
y = (Pc、bx、by、bw、bh、C1、C2、C3)
两个目标的y = (Pc、bx、by、bw、bh、C1、C2、C3,Pc、bx、by、bw、bh、C1、C2、C3)
如上所讲的那样,如果一个网格里有两个目标了,那输出即为3*3*16,或者也为3*3*2*8。
当然这个2就是代表目标的个数,这说明如果一个网格里存在的目标更多,那你输出向量的维度则会更大。
向量的上半部分是行人,下半部分是汽车。只有汽车没有行人的向量如下所示:
总结:
有的同学可能想问,那如果一个网格中存在的的目标数量大于两个呢,甚至更多呢,那我们要预设更多的anchor box吗?答案是否定的。事实上当我们按照19*19,或者30*30或者更大更密集划分网格的时候,一个网格中存在多个目标的可能性已经变得非常小,因此这种情况出现的概率非常低,因此这个问题并不会过于影响我们算法的性能。
一般来说需要人工根据自己目标的形状特性,手动设置5个左右的anchor box,比如说,我知道我要检测的目标里面存在瘦高的目标我就设置瘦高的长方形的anchor box,我要检测目标里面有胖的目标,我就设置矮宽的正方形等等。但是人工设置总归不是最好的办法,在后面的yolo算法中我们将会学习到,K-means方法,使用K聚类的方法,我们可以自适应的选择最合适的anchor box,这才是更智能更好的方法。