mmdetection——anchor_target解读

anchor_target函数解读
该函数输入参数:

"""Compute regression and classification targets for anchors.
Args:
    anchor_list (list[list]): Multi level anchors of each image.
    valid_flag_list (list[list]): Multi level valid flags of each image.
    gt_bboxes_list (list[Tensor]): Ground truth bboxes of each image.
    img_metas (list[dict]): Meta info of each image.
    target_means (Iterable): Mean value of regression targets.
    target_stds (Iterable): Std value of regression targets.
    cfg (dict): RPN train configs.
Returns:
    tuple
"""

核心思路:

  1. 将每张图多个尺度anchor合并起来,得出【num_imgs,num_anchors*4】的tensor
  2. 对每张图计算出target
  3. 将得出的以图片数划分的tensors重新划分为以level的主导的tensors,使得得出的tensors和模型预测结果格式对应上

1.拼接单图多尺度anchor到一个tensor

# anchor number of multi levels
num_level_anchors = [anchors.size(0) for anchors in anchor_list[0]]
# concat all level anchors and flags to a single tensor
for i in range(num_imgs):
    assert len(anchor_list[i]) == len(valid_flag_list[i])
    anchor_list[i] = torch.cat(anchor_list[i])
    valid_flag_list[i] = torch.cat(valid_flag_list[i])
  1. anchor_target_single
    针对每张图片分别用anchor_target_single得出anchor target
    这儿多图操作同样用的multi_apply完成
# assign gt and sample anchors
anchors = flat_anchors[inside_flags, :]

if sampling:
    assign_result, sampling_result = assign_and_sample(
        anchors, gt_bboxes, gt_bboxes_ignore, None, cfg)
else:
    bbox_assigner = build_assigner(cfg.assigner)
    assign_result = bbox_assigner.assign(anchors, gt_bboxes,
                                         gt_bboxes_ignore, gt_labels)
    bbox_sampler = PseudoSampler()
    sampling_result = bbox_sampler.sample(assign_result, anchors,
                                          gt_bboxes)

anchor_target_single主要涉及的就是assign gt and sample anchors

其中,只对有效anchor去计算target
faster rcnn这种就存在采样的操作,而retinanet这种就对所有负样本算损失,不采样,关于assign和sample的过程另说。

inside_flags = anchor_inside_flags(flat_anchors, valid_flags,
                                   img_meta['img_shape'][:2],
                                   cfg.allowed_border)
if not inside_flags.any():
    return (None, ) * 6
# assign gt and sample anchors
anchors = flat_anchors[inside_flags, :]

if sampling:
    assign_result, sampling_result = assign_and_sample(
        anchors, gt_bboxes, gt_bboxes_ignore, None, cfg)
else:
    bbox_assigner = build_assigner(cfg.assigner)
    assign_result = bbox_assigner.assign(anchors, gt_bboxes,
                                         gt_bboxes_ignore, gt_labels)
    bbox_sampler = PseudoSampler()
    sampling_result = bbox_sampler.sample(assign_result, anchors,
                                          gt_bboxes)

常见的assign为max_iou_assigner, 依据anchor与gt bbox的iou确定anchor target,assign返回的数据为一个数据类AssignResult,包含num_gts, assigned_gt_inds, max_overlaps, labels=assigned_labels,这几项。
num_gts: gt bbox数量
assigned_gt_inds: anchor对应的label。-1:无视,0:负样本,正数:gt bbox对应的index
max_overlaps:anchor与gt bbox的最大iou
labels:pos bbox对应的label

assign完了就是sample了,如果有sample操作,就按照指定的sample类型来,若像retinanet这种没有sample操作的,直接用的PseudoSampler这个采样类,这个类直接将所有有效anchor提取出来。
sampler返回的是SamplingResult对象,包含pos_inds, neg_inds, bboxes, gt_bboxes,assign_result, gt_flags
pos_inds:pos anchor的索引
neg_inds:neg anchor的索引
bboxes:anchors

当有了anchor的target gt之后还需要将bbox转换成delta,所下面代码做的就是计算pos neg anchor对应的delta和权重赋值。

num_valid_anchors = anchors.shape[0]
bbox_targets = torch.zeros_like(anchors)
bbox_weights = torch.zeros_like(anchors)
labels = anchors.new_zeros(num_valid_anchors, dtype=torch.long)
label_weights = anchors.new_zeros(num_valid_anchors, dtype=torch.float)


pos_inds = sampling_result.pos_inds
neg_inds = sampling_result.neg_inds
if len(pos_inds) > 0:
    pos_bbox_targets = bbox2delta(sampling_result.pos_bboxes,
                                  sampling_result.pos_gt_bboxes,
                                  target_means, target_stds)
    bbox_targets[pos_inds, :] = pos_bbox_targets
    bbox_weights[pos_inds, :] = 1.0
    if gt_labels is None:
        labels[pos_inds] = 1
    else:
        labels[pos_inds] = gt_labels[sampling_result.pos_assigned_gt_inds]
    if cfg.pos_weight <= 0:
        label_weights[pos_inds] = 1.0
    else:
        label_weights[pos_inds] = cfg.pos_weight
if len(neg_inds) > 0:
    label_weights[neg_inds] = 1.0

最后将有效anchor填充到原来所有的anchor里

# map up to original set of anchors
if unmap_outputs:
    num_total_anchors = flat_anchors.size(0)
    labels = unmap(labels, num_total_anchors, inside_flags)
    label_weights = unmap(label_weights, num_total_anchors, inside_flags)
    bbox_targets = unmap(bbox_targets, num_total_anchors, inside_flags)
    bbox_weights = unmap(bbox_weights, num_total_anchors, inside_flags)
YOLO系列是基于深度学习的端到端实时目标检测方法。 PyTorch版的YOLOv5轻量而高性能,更加灵活和易用,当前非常流行。 本课程将手把手地教大家使用labelImg标注和使用YOLOv5训练自己的数据集。课程实战分为两个项目:单目标检测(足球目标检测)和多目标检测(足球和梅西同时检测)。  本课程的YOLOv5使用ultralytics/yolov5,在Windows和Ubuntu系统上分别做项目演示。包括:安装YOLOv5、标注自己的数据集、准备自己的数据集(自动划分训练集和验证集)、修改配置文件、使用wandb训练可视化工具、训练自己的数据集、测试训练出的网络模型和性能统计。 除本课程《YOLOv5实战训练自己的数据集(Windows和Ubuntu演示)》外,本人推出了有关YOLOv5目标检测的系列课程。请持续关注该系列的其它视频课程,包括:《YOLOv5(PyTorch)目标检测:原理与源码解析》课程链接:https://edu.csdn.net/course/detail/31428《YOLOv5目标检测实战:Flask Web部署》课程链接:https://edu.csdn.net/course/detail/31087《YOLOv5(PyTorch)目标检测实战:TensorRT加速部署》课程链接:https://edu.csdn.net/course/detail/32303《YOLOv5目标检测实战:Jetson Nano部署》课程链接:https://edu.csdn.net/course/detail/32451《YOLOv5+DeepSORT多目标跟踪与计数精讲》课程链接:https://edu.csdn.net/course/detail/32669《YOLOv5实战口罩佩戴检测》课程链接:https://edu.csdn.net/course/detail/32744《YOLOv5实战国交通标志识别》课程链接:https://edu.csdn.net/course/detail/35209 《YOLOv5实战垃圾分类目标检测》课程链接:https://edu.csdn.net/course/detail/35284  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值