目标检测之ATSS介绍

目标检测之ATSS介绍:

论文:https://arxiv.org/pdf/1912.02424.pdf
代码:https://github.com/sfzhang15/ATSS
不过作者这个代码我没看错的话是基于facebook的maskrcnn-benchmark做的,写的挺好的,不过因为我最近mmdection用的多一点(主要是加组件好加),所以底下代码介绍我还是用mmdection的代码介绍。

这篇论文可以说是2020上半年目标检测最具有价值的文章之一了。直接揭露除了anchor 和anchor free类算法本质的区别,同时提出了一种筛选正负样本的方法,基于ATSS加成的RetinaNet直接吊打众多twostage网络。下面就是一些ATSS的介绍和分享(个人知识有限,说的不一定都对,如果有不对的地方请多指出我一定修改):

先简单介绍一下ATSS提出的背景,在目标检测的开始是RCNN这一条线,包括著名的Faster-Rcnn,Faster-Rcnn做目标检测本质其实就是图片过backbone提出特征图,然后过RPN得到初步候选框,再通过特征图和候选框得到候选框对应的特征向量进行分类和回归。由于中间需要RPN初步得到候选框然后再过ROI,有两步,所以这块也就是所谓的twostage结构,twostage结构的Faster-Rcnn以及Cascade-Rcnn+bigbackbone+FPN+DCN的结构在各大目标检测比赛和项目频繁出现。可以说只要数据合理,算力够,这一套就不会让人失望。

然后由于这套太耗时,RetinaNet就想直接一步把框的生成分类回归全干了,由于生成框会有大量的框没有前景,就导致了所谓的正负样本不均衡,RetinaNet通过著名的focalloss缓解了这一个缺点。再然后在18到19 20出现了大量的onestage结构,基于anchor的yolov3 v4,还有类似基于FCOS,CornerNet和CenterNet这样的anchor free网络结构。

这篇博文的主角ATSS就揭露了anchor free和base anchor的本质区别,即正负样本的选择。并给出了一种更为合理的样本选择策略。

这里简单说一下,这篇文章宝贵之处就是作者各项消融试验做的很好,很值得我们学习。

首先就是分析RetinaNet和FCOS区别:
这里参考了知乎https://zhuanlan.zhihu.com/p/115407465
作者通过分析主要给出了三个区别:

  1. RetinaNet在特征图上每个点铺设多个anchor,而FCOS在特征图上每个点只铺设一个中心点,这是数量上的差异。

  2. RetinaNet基于anchor和GT之间的IoU和设定的阈值来确定正负样本,而FCOS通过GT中心点和铺设点之间的距离和尺寸来确定正负样本。这1点可以从下图的对比中看到,这张图像中蓝色框和点表示GT,红色框表示RetinaNet铺设的anchor,红色点表示FCOS铺设的点,左右两边类似表格上的数值表示最终确定的正负样本,0表示负样本,1表示正样本。

在这里插入图片描述

  1. RetinaNet通过回归矩形框的2个角点偏置进行预测框位置和大小的预测,而FCOS是基于中心点预测四条边和中心点的距离进行预测框位置和大小的预测。这1点可以从下图的对比中看到,蓝色框和点表示GT,红色框表示RetinaNet的正样本,红色点表示FCOS的正样本。
    在这里插入图片描述
    接下来就可以设计对比实验了。因为主要关注第2、3点的影响,所以首先将RetinaNet在每个点铺设的anchor数量减少到1,也就是和FCOS保持一致,这样第1点差异就不存在了。另外,由于FCOS论文中用了一些训练的技巧,如Table所示,比如Group Normalization、GIoU Loss等,所以为了公平对比2个算法,作者在RetinaNet上也加上了这些技巧,最后mAP达到37.0,基本上和FCOS的37.8很接近了。
    在这里插入图片描述

所以接下来作者对剩余的0.8mAP差异进行了分析,做了下面这个实验。这个表格可以这样看:
按行看,Intersection over Union这一行的两个数值表示RetinaNet和FCOS都采用基于IoU方式确定正负样本,二者的mAP基本没有差别;同样Spatial and Scale Constraint这一行的两个数值表示RetinaNet和FCOS都采用基于距离和尺寸方式确定正负样本,二者的mAP也是一样。所以结论就是:回归方式的不同并不是造成FCOS和RetinaNet效果差异的原因,也就是前面说的第3点差异是不影响的。
按列看,Box这一列的两个数值表示将RetinaNet的正负样本确定方式从IoU换成和FCOS一样的基于距离和尺寸,那么mAP就从37.0上升到37.8;同样Point这一列的两个数值表示将FCOS的正负样本确定方式从基于距离和尺寸换成和RetinaNet一样的基于IoU,那么mAP就从37.8降为36.9。所以结论就是:如何确定正负样本才是造成FCOS和RetinaNet效果差异的原因,也就是前面说的第2点差异才是根源。
从论文开始到目前为止的实验对比和分析都是步步紧扣,答案也随之浮出水面,接下来就是论文的第2大部分内容,也就是提出ATSS来确定正负样本,
在这里插入图片描述

在这项工作中,作者指出:
一级段基于锚点和基于中心的无锚点探测器之间的本质区别实际上是正训练样本和负训练样本的定义。 这表明在训练对象检测器的过程中如何选择正样本和负样本至关重要。
受此启发,作者深入研究了这一基本问题,并提出了自适应训练样本选择方法,该方法根据目标的统计特征(方差和均值)自动划分正训练样本和负训练样本,弥合了基于锚的探测器与无锚探测器之间的差距。 此外,作者讨论了在每个位置平铺多个锚点的必要性,并证明了在当前情况下这是不费吹灰之力的操作。 在具有挑战性的基准MS COCO上进行的大量实验表明,所提出的方法可以实现最新性能,而不会引入任何额外的开销。

基于以上:
作者提出了一种自适应的选取正样本的方法,具体方法如下:

1.对于每个输出的检测层,选计算每个anchor的中心点和目标的中心点的L2距离,选取K(mmdetection的topK是9)个anchor中心点离目标中心点最近的anchor为候选正样本(candidate positive samples)

2.计算每个候选正样本和groundtruth之间的IOU,计算这组IOU的均值和方差
根据方差和均值,设置选取正样本的阈值:t=m+g ;m为均值,g为方差

3.根据每一层的t从其候选正样本中选出真正需要加入训练的正样本
然后进行训练

这里我借用mmdetection的代码简单介绍一下:
在atss_head中,首先生成anchor_all(就是先在featuremap上左上角(0,0)位置生成base_anchor,我没记错的话是三个,然后依次shift类似滑窗生成anchor_all,有了anchor之后就进入atss阶段)

assign_result = self.assigner.assign(anchors, num_level_anchors_inside,
                                             gt_bboxes, gt_bboxes_ignore,
                                             gt_labels)

        sampling_result = self.sampler.sample(assign_result, anchors,
                                              gt_bboxes)

Atss步骤在ATSSAssigner中:

我们一个个来说:

1.首先计算每个anchor的中心点和目标的中心点的L2距离(compute center distance between all bbox and gt)

 # compute center distance between all bbox and gt
        gt_cx = (gt_bboxes[:, 0] + gt_bboxes[:, 2]) / 2.0
        gt_cy = (gt_bboxes[:, 1] + gt_bboxes[:, 3]) / 2.0
        gt_points = torch.stack((gt_cx, gt_cy), dim=1)

        bboxes_cx = (bboxes[:, 0] + bboxes[:, 2]) / 2.0
        bboxes_cy = (bboxes[:, 1] + bboxes[:, 3]) / 2.0
        bboxes_points = torch.stack((bboxes_cx, bboxes_cy), dim=1)

        distances = (bboxes_points[:, None, :] -
                     gt_points[None, :, :]).pow(2).sum(-1).sqrt()

2.计算每个候选正样本和groundtruth之间的IOU:注意这里直接调的IOU计算函数self.iou_calculator

# compute iou between all bbox and gt
        overlaps = self.iou_calculator(bboxes, gt_bboxes)

3.计算每个候选正样本和groundtruth之间的IOU,计算这组IOU的均值和方差
根据方差和均值,设置选取正样本的阈值:t=m+g ;m为均值,g为方差

# get corresponding iou for the these candidates, and compute the
        # mean and std, set mean + std as the iou threshold
        candidate_overlaps = overlaps[candidate_idxs, torch.arange(num_gt)]
        overlaps_mean_per_gt = candidate_overlaps.mean(0)
        overlaps_std_per_gt = candidate_overlaps.std(0)
        overlaps_thr_per_gt = overlaps_mean_per_gt + overlaps_std_per_gt

        is_pos = candidate_overlaps >= overlaps_thr_per_gt[None, :]

通过计算候选框与gt的左,右,上,下,距离,继续找出合适的框

# calculate the left, top, right, bottom distance between positive
        # bbox center and gt side
        l_ = ep_bboxes_cx[candidate_idxs].view(-1, num_gt) - gt_bboxes[:, 0]
        t_ = ep_bboxes_cy[candidate_idxs].view(-1, num_gt) - gt_bboxes[:, 1]
        r_ = gt_bboxes[:, 2] - ep_bboxes_cx[candidate_idxs].view(-1, num_gt)
        b_ = gt_bboxes[:, 3] - ep_bboxes_cy[candidate_idxs].view(-1, num_gt)
        is_in_gts = torch.stack([l_, t_, r_, b_], dim=1).min(dim=1)[0] > 0.01
        is_pos = is_pos & is_in_gts

由于atss已经找出足够优秀的框了,不需要再sample,所以sample函数用的PseudoSampler。直接将所有pos 和neg 样本提取出来。至此ATSS步骤完成。

直接贴结果:
在这里插入图片描述
可以看出ATSS取得了极为优秀的结果,这点在我们实际使用中也得到了证明,表现已经超过了twostage这一套。

下面是我自己的一点思考(不一定对啊。只是把自己的想法说出来),那就是ATSS在onestage上这么优秀,能不能应用于twostage上,我自己翻了一遍mmdection的实现,将ATSS应用在Faster-Rcnn上,感觉是不合理的,twostage,或者说Faster-Rcnn这一套和RetinaNet这类onestage本质区别其实就是那个RPN,RPN给出一堆的候选框,配合featuremap进入roi进行分类和回归,为什么twostage比onestage效果好,就是因为RPN找出了一堆的高质量anchor,atss找出高质量anchor之后直接进行分类回归,就已经干了这个事情,那么Faster-Rcnn上atss,我认为不是很合理的。

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值