什么是Anchor?

anchor机制是广泛应用于目标检测任务中的一种方法,anchor box指的是是一组预先定义好的不同长宽比的边界框,通过对这些不同长宽比的anchor进行微调,我们能够检测到对应不同尺寸的真实物体。

目标检测中的anchor 目标检测中的anchor

Anchor的作用是什么?

考虑到图像中会出现不同尺寸(scale),不同长宽比(aspect ratio)的物体,而我们神经网络的输出是一组同样scale的feature map和一组同样的weights,这样的情况下让其预测不同scale和aspect ratio的物体就相对来说比较困难。如图所示:

图像中的多尺度物体

Faster-RCNN中首先引入anchor的概念,论文中有这样一段话:

In contrast to prevalent methods [8], [9], [1], [2] that use pyramids of images (Figure 1, a) or pyramids of filters (Figure 1, b), we introduce novel “anchor” boxes that serve as references at multiple scales and aspect ratios. Our scheme can be thought of as a pyramid of regression references (Figure 1, c), which avoids enumerating images or filters of multiple scales or aspect ratios. This model performs well when trained and tested using single-scale images and thus benefits running speed.

也就是说,anchor的作用在于解决图像中物体scale和aspect ratio变化范围大的问题,之前的解决方法是pyramids of images 或者 pyramids of filters,但是前者耗费的时间太多,而后者是传统的CV的方法,当时对于CNN还没有一种一种对应的pyramids of filters的方案(真正得到CNN的方法是2016年提出的FPN,pyramids of features)

anchor的方法同时还解决了另外一个问题。我们在做检测的时候,如果两个ground truth预测框之间的overlap过大,它们会落到同一个cell中,这样就会导致ground truth被过滤掉。如下图所示:

同一个cell中gt box出现overlap的情况

而如果采用的anchor方法,一个cell中不同的anchor负责去预测不同scale和aspect ratio的物体,即便是有多个框会预测到同一个cell,也不会导致ground truth丢失的情况出现。

总结来说,anchor机制解决了两个问题:(1) 不同scale和aspect ratio物体预测难度大,利用anchor将scale和aspect ratio空间划分为几个子空间,降低了问题难度 (2) 解决了gt box与gt box之间overlap过大导致gt box丢失的问题。

Anchor的选取

anchor的大小是在我们进行模型训练之前就已经确定的了,那么是如何确定的呢?

我们以Pascal VOC 2007数据集为例,采用的方法是k-means聚类,根据VOC 2007数据集中图片的长度和宽度进行聚类,这里需要注意的问题是,我们采用的是Yolov3模型,Yolov3模型采用的输入图像的size 是416*416的,因此在做聚类之前就需要将图片和对应的label做等比例的resize,然后再进行聚类,获取anchor。

聚类代码:

class kMean_parse:
    def __init__(self,path_txt):
        self.path = path_txt
        self.km = KMeans(n_clusters=9,init="k-means++",n_init=10,max_iter=3000000,tol=1e-3,random_state=0)
        self._load_data()

    def _load_data (self):
        self.data = np.loadtxt(self.path)

    def parse_data (self):
        self.y_k = self.km.fit_predict(self.data)
        print(self.km.cluster_centers_)

    def plot_data (self):
        plt.scatter(self.data[self.y_k == 0, 0], self.data[self.y_k == 0, 1], s=50, c="orange", marker="o", label="cluster 1")
        plt.scatter(self.data[self.y_k == 1, 0], self.data[self.y_k == 1, 1], s=50, c="green", marker="s", label="cluster 2")
        plt.scatter(self.data[self.y_k == 2, 0], self.data[self.y_k == 2, 1], s=50, c="blue", marker="^", label="cluster 3")
        plt.scatter(self.data[self.y_k == 3, 0], self.data[self.y_k == 3, 1], s=50, c="gray", marker="*",label="cluster 4")
        plt.scatter(self.data[self.y_k == 4, 0], self.data[self.y_k == 4, 1], s=50, c="yellow", marker="d",label="cluster 5")
       # draw the centers
        plt.scatter(self.km.cluster_centers_[:, 0], self.km.cluster_centers_[:, 1], s=250, marker="*", c="red", label="cluster center")
        plt.legend()
        plt.grid()
        plt.show()

完整的代码可以参考这里

参考资料

1.Anchor Boxes for Object Detection
2.Neural Networks Intuitions: 5. Anchors and Object Detection
3.史上最详细的Yolov3边框预测分析
4.Why anchor?



object detection

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!