前言
anchor-based目标检测,如何生成anchor?
这可能是一个很弱的问题,可是呢,网上也没找到涉及源码实现层面的好点的资料。
所以,还是记录下我自己的看法。
anchor是如何起作用的
anchor也就是锚框,它的作用就是划定一块区域,让网络去探寻这块区域里是否有物体。
常人此时的思维,既然探寻这块区域,那是不是要把这块区域的图像抠出来扔进网络计算呢?进而,会引出问题。抠出来的图不可能正好是完整的,那对不完整的图如何做目标预测呢?起初这点老是困扰我,也看了一些资料,发现:即便是点赞很高的教程视频,也不会涉及这些细节。那些资料好像默认你本该懂这些东西似的。后来,就如Linus说的“show me the code”,看了源码就了解了。
原来,yolo这种one-stage是将整张图片甩进网络,然后输出针对每个anchor的预测结果。那么问题又来了,既然整张图片都甩进去了,anchor的意义体现在何处?这个问题,网上没人解答,好像就是只要画了anchor,那网络自然就会去关注anchor区域。anchor既然可以让网络关注自身区域内的内容,那这点是如何体现?none
有时候就是这样,他们讲了一堆,核心的东西却没有解释。我的理解是:anchor是通过损失函数来体现的。损失函数会引导网络去关注anchor区域。
anchor的生成
anchor的生成就是两个问题组成:anchor的中心位置、anchor的size(包括大小和比例)。
先说,anchor的中心位置确定。
假设计算资源无限,那干脆每个像素作为中心点来画N个anchor得了。可是,很不幸这样会有一堆anchor。比如:1000X1000像素的图片,每个点3个size的anchor,那就得三百万个anchor,简直爆炸。那就得减少anchor,所以有了对特征去画anchor,也就是以每个特征点为中心。比如:1000X1000的图片,提取特征后是100X100,还是每个点3个size,那就只有3万个anchor了,这样我们的小显卡就跑得动了。
那对特征画anchor的本质是啥的?不就是从原来每个像素为中心点,改成了选取间隔一定数量的像素作为中心点。也就是:一个anchor紧挨着一个anchor改成了,anchor之间隔开一定数量像素。理解卷积过程,就能理解此点。
那anchor的size呢?因为目标有大小,所以不同的size就适合与之大小对应的目标的检测。由于目标还存在不同形状,因此就有anchor的比例。其实一般也就3种比例:1:2、1:1、2:1。此处注意:anchor大小指的是anchor的面积、比例指的是长宽比。
anchor的大小和比例有时候能玩点花活,比如:根据训练数据的GT,采用聚类去确定,而不是固定anchor size。再比如:根据所检测目标的密度去确定anchor的密度。
另外,不同size的anchor都使用同一套中心点的话,其实是不合理的。因为,size越大的anchor预测的目标就越大,而目标越大那往往anchor之间的间隔就该越大。anchor之间的间隔与anchor的大小的比值,应该在一个合理的范围。如果,anchor间隔太近,就会出现大量重复anchor。这是毫无必要的,徒增计算压力。所以,anchor size越大其数量就越少。
所以,detectron2在实现maskrcnn的anchor生成时,不同size的anchor其中心点是不同的,进而间隔不同,进而anchor数量不同。
anchor生成细节
以detectron2在实现maskrcnn的anchor生成为例。anchor是落在图像坐标系的,肯定不是原始图像坐标系,而是经过统一处理后的图像的坐标系。
1,先将图像坐标系的anchor中心点提取出来。这个过程是根据上层传过来的特征size乘以步长来确定的。上层传过来的是经过fpn处理后输出的不同size的特征,正好拿来乘以不同步长,得到了anchor中心点。
2,再计算anchor的相对坐标。就是anchor的四个点相对自身中心的坐标。
3,anchor四个点的坐标加上图像坐标系中anchor中心点坐标即可。这个就类似坐标偏移,为什么加上即可呢?因为,anchor自身中心点坐标为零点。
伪代码
1,假设原始图像经过处理后是20x20像素,则先构建两个anchor中心点坐标系;
2,假设两个anchor中心点坐标系为:1,3,5。。。19和1,5,9。。。17,其实就是一个步长是2,一个是4;
3,假设两个坐标系对应的anchor size为:2x2,4x4,处于简单考虑,只采用一个size,也就是1:1,则两个anchor的相对自身坐标,以x1y1,x2y2,x3y3,x4y4格式,为:(-1,1)、(1,1)、(1,-1)、(-1,-1)。另一个anchor的坐标乘以2即可,因为比例关系为2。这个坐标是相对anchor自身中心原点(0,0)的坐标;
4,将anchor坐标嵌到每一个anchor中心点坐标即可;
最终,anchor size越小,则anchor越密集,数量越多。