mmdetection 代码库中的 anchor 设置原则

本文主要介绍 CUHK 的 mmdetection 代码库 (https://github.com/open-mmlab/mmdetection)中关于 anchor 的设置的一些 tips。以下提到的所有 anchor 尺寸均为对应到输入图像上的bounding box 尺寸。 

mmdetection 代码库总体框架还比较清晰,对于大部分经典的检测算法都有实现。大部分的接口参数都可以通过修改配置接口文件实现,配置文件在 ~/mmdetection/tree/master/configs/ 文件夹中。

一般来说,利用开源的检测代码库做自己的任务,一个肯定要考虑修改的地方便是 anchor 机制。因为自己检测任务中的目标的尺寸和高宽比和开源模型中的目标可能会不一致。

已 mmdetection 的 faster_rcnn_r50_fpn_1x.py 文件为例。本配置主要是算法是 Faster-RCNN + RPN,目标任务是 COCO 物体检测。输入尺寸为 800 * 1333 左右,利用 FPN 在 5 个尺寸的 featuremap 上进行 anchor 设置。最小的 anchor 基准面积为 32 * 32,最大的基准面积为 512 * 512 (高宽比不同,面积相同)。

而如果自己准备输入的图像尺寸为 512 * 512,而且目标相对较小,比如面积在 16*16~32*32之间,那么anchor 设置就不能用默认的了。那么怎么在 mmdetection 代码库中根据自己的任务来设置 anchor 参数呢?

首先关注以下几个参数:

配置文件中的关键字段
配置文件中的关键字段

其实,这里面有一个隐含参数没有显示出来就是:

anchor_base_sizes : 见~/mmdet/models/anchor_heads/anchor_head.py ;这个参数物理含义是base anchor 的高和宽。与 anchor_scales 共同决定了基准 anchor 的尺寸。为什么在这里没有显示呢?因为在代码中,anchor_base_sizes 被设置为与 anchor_strides 相同。

anchor_strides  -- 与 RPN 中选取的 feature map 尺寸有联动关系,这里 len(anchor_strides)==5,说明在 5 个feature map 上进行anchor 设置。一般原图到目标 feature map 缩小了多少倍,就设置为多少。anchor_strides 为 base anchor 族(一个基准  base size 的基准 anchor + 不同的高宽比的模版形成一个anchor 族)设置完成后平移的 stride,以保证设置的anchors 能覆盖原图所有区域。这里将 anchor_strides 设置为与 anchor_base_size 相同,目的是对于 FPN 的每一个 feature map 中anchor 生成的区域能刚好覆盖所有的原图区域。如果anchor_base_size 大于 anchor_stride 则会照成一些冗余,反之则会有一些区域覆盖不了(有兴趣自己可以画一下)。

anchor_scales -- 默认为 [8, 16, 32], 物理含义是base anchor 的倍数,与 anchor_base_sizes 共同决定anchor 的面积。比如在上图例子中,anchor_base_sizes == anchor_strides == [4, 8, 16, 32, 64],anchor_scales == [8] 因此 anchor 最小面积为 (4*8)*(4*8) = 32 * 32, 最大面积为 (64*8)*(64*8) = 512 * 512。

anchor_ratio: 这个参数比较好理解,就是面积固定后,anchor 的高宽比。

综上,如果我的任务中,目标面积为 16*16~32*32。那么我应该做如下参数设置:

anchor_scales = [4]

anchor_base_size = anchor_stride = [4, 8, 0, 0, 0]

anchor_ratio 根据目标可能的高宽比来设置 (可以先做个统计,同样目标尺寸也可以先看以下统计分布)

 

这样,其实anchor 就在浅层的 feature map 中获取,在深层不取anchor。(fpn中,浅层获取小目标anchor,深层获取大目标anchor)

总结起来,如果要用 mmdetection 中的检测器适配自己的任务,那么在anchor 设置中,首先统计自己目标的尺寸和高宽比,然后按照上面的基本原理调整以上三个参数的配比即可。

有问题,欢迎留言讨论。

参考资料:

1. Faster-RCNN 中的 anchor 与原图中 boundingbox 的对应关系 https://blog.csdn.net/yangyehuisw/article/details/105033932

  • 13
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
MMDetection是一个基于PyTorch框架开发的目标检测工具箱,其中的参数设置通常在配置文件(config file)中进行。配置文件中包含了许多不同的参数,例如模型结构、数据集路径、优化器、训练参数等等。 在MMDetection中,通常会有一个主配置文件config.py,其中包含了许多默认的配置参数。这些参数可以通过命令行参数(args)进行覆盖或修改。例如,以下代码是在COCO数据集上训练Faster R-CNN模型的例子,其中的config文件是faster_rcnn_r50_fpn_1x_coco.py: ```python python tools/train.py configs/faster_rcnn_r50_fpn_1x_coco.py ``` 在faster_rcnn_r50_fpn_1x_coco.py中,可以设置许多不同的参数,例如学习率、batch_size、数据集路径、模型结构等等。例如,以下代码是faster_rcnn_r50_fpn_1x_coco.py中的一部分: ```python model = dict( type='FasterRCNN', pretrained='torchvision://resnet50', backbone=dict( type='ResNet', depth=50, num_stages=4, out_indices=(0, 1, 2, 3), frozen_stages=1, norm_cfg=dict(type='BN', requires_grad=True), norm_eval=True, style='pytorch'), neck=dict( type='FPN', in_channels=[256, 512, 1024, 2048], out_channels=256, num_outs=5), rpn_head=dict( type='RPNHead', in_channels=256, feat_channels=256, anchor_generator=dict( type='AnchorGenerator', scales=[8], ratios=[0.5, 1.0, 2.0], strides=[4, 8, 16, 32, 64]), bbox_coder=dict( type='DeltaXYWHBBoxCoder', target_means=[0.0, 0.0, 0.0, 0.0], target_stds=[1.0, 1.0, 1.0, 1.0]), loss_cls=dict( type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0), loss_bbox=dict(type='SmoothL1Loss', beta=1.0 / 9.0, loss_weight=1.0)), roi_head=dict( type='StandardRoIHead', bbox_roi_extractor=dict( type='SingleRoIExtractor', roi_layer=dict(type='RoIAlign', out_size=7, sample_num=2), out_channels=256, featmap_strides=[4, 8, 16, 32]), bbox_head=dict( type='Shared2FCBBoxHead', in_channels=256, fc_out_channels=1024, roi_feat_size=7, num_classes=80, bbox_coder=dict( type='DeltaXYWHBBoxCoder', target_means=[0.0, 0.0, 0.0, 0.0], target_stds=[0.1, 0.1, 0.2, 0.2]), reg_class_agnostic=False, loss_cls=dict( type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0), loss_bbox=dict(type='SmoothL1Loss', beta=1.0, loss_weight=1.0))), # model training and testing settings train_cfg=dict( rpn=dict( assigner=dict( type='MaxIoUAssigner', pos_iou_thr=0.7, neg_iou_thr=0.3, min_pos_iou=0.3, match_low_quality=True, ignore_iof_thr=-1), sampler=dict( type='RandomSampler', num=256, pos_fraction=0.5, neg_pos_ub=-1, add_gt_as_proposals=False), allowed_border=0, pos_weight=-1, debug=False), rcnn=dict( assigner=dict( type='MaxIoUAssigner', pos_iou_thr=0.5, neg_iou_thr=0.5, min_pos_iou=0.5, match_low_quality=True, ignore_iof_thr=-1), sampler=dict( type='RandomSampler', num=512, pos_fraction=0.25, neg_pos_ub=-1, add_gt_as_proposals=True), pos_weight=-1, debug=False)), test_cfg=dict( rpn=dict( nms_across_levels=False, nms_pre=1000, nms_post=1000, max_num=1000, nms_thr=0.7, min_bbox_size=0), rcnn=dict( score_thr=0.05, nms=dict(type='nms', iou_thr=0.5), max_per_img=100))) # dataset settings dataset_type = 'CocoDataset' data_root = 'data/coco/' img_norm_cfg = dict( mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True) train_pipeline = [ dict(type='LoadImageFromFile'), dict(type='LoadAnnotations', with_bbox=True), dict(type='Resize', img_scale=(1333, 800), keep_ratio=True), dict(type='RandomFlip', flip_ratio=0.5), dict(type='Normalize', **img_norm_cfg), dict(type='Pad', size_divisor=32), dict(type='DefaultFormatBundle'), dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']), ] test_pipeline = [ dict(type='LoadImageFromFile'), dict( type='MultiScaleFlipAug', img_scale=(1333, 800), flip=False, transforms=[ dict(type='Resize', keep_ratio=True), dict(type='RandomFlip'), dict(type='Normalize', **img_norm_cfg), dict(type='Pad', size_divisor=32), dict(type='ImageToTensor', keys=['img']), dict(type='Collect', keys=['img']), ]) ] data = dict( samples_per_gpu=2, workers_per_gpu=2, train=dict( type=dataset_type, ann_file=data_root + 'annotations/instances_train2017.json', img_prefix=data_root + 'train2017/', pipeline=train_pipeline), val=dict( type=dataset_type, ann_file=data_root + 'annotations/instances_val2017.json', img_prefix=data_root + 'val2017/', pipeline=test_pipeline), test=dict( type=dataset_type, ann_file=data_root + 'annotations/instances_val2017.json', img_prefix=data_root + 'val2017/', pipeline=test_pipeline)) ``` 在这个配置文件中,model定义了模型结构,train_cfg定义了训练参数,test_cfg定义了测试参数,dataset_type定义了数据集类型,data定义了数据路径和预处理方式。这些参数的设置可以根据具体的需求进行修改。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值