123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- # Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- import paddle
- import paddle.nn as nn
- import paddle.nn.functional as F
- from ppdet.core.workspace import register
- from ppdet.modeling.bbox_utils import batch_bbox_overlaps
- from ppdet.modeling.transformers import bbox_xyxy_to_cxcywh
- __all__ = ['UniformAssigner']
- def batch_p_dist(x, y, p=2):
- """
- calculate pairwise p_dist, the first index of x and y are batch
- return [x.shape[0], y.shape[0]]
- """
- x = x.unsqueeze(1)
- diff = x - y
- return paddle.norm(diff, p=p, axis=list(range(2, diff.dim())))
- @register
- class UniformAssigner(nn.Layer):
- def __init__(self, pos_ignore_thr, neg_ignore_thr, match_times=4):
- super(UniformAssigner, self).__init__()
- self.pos_ignore_thr = pos_ignore_thr
- self.neg_ignore_thr = neg_ignore_thr
- self.match_times = match_times
- def forward(self, bbox_pred, anchor, gt_bboxes, gt_labels=None):
- num_bboxes = bbox_pred.shape[0]
- num_gts = gt_bboxes.shape[0]
- match_labels = paddle.full([num_bboxes], -1, dtype=paddle.int32)
- pred_ious = batch_bbox_overlaps(bbox_pred, gt_bboxes)
- pred_max_iou = pred_ious.max(axis=1)
- neg_ignore = pred_max_iou > self.neg_ignore_thr
- # exclude potential ignored neg samples first, deal with pos samples later
- #match_labels: -2(ignore), -1(neg) or >=0(pos_inds)
- match_labels = paddle.where(neg_ignore,
- paddle.full_like(match_labels, -2),
- match_labels)
- bbox_pred_c = bbox_xyxy_to_cxcywh(bbox_pred)
- anchor_c = bbox_xyxy_to_cxcywh(anchor)
- gt_bboxes_c = bbox_xyxy_to_cxcywh(gt_bboxes)
- bbox_pred_dist = batch_p_dist(bbox_pred_c, gt_bboxes_c, p=1)
- anchor_dist = batch_p_dist(anchor_c, gt_bboxes_c, p=1)
- top_pred = bbox_pred_dist.topk(
- k=self.match_times, axis=0, largest=False)[1]
- top_anchor = anchor_dist.topk(
- k=self.match_times, axis=0, largest=False)[1]
- tar_pred = paddle.arange(num_gts).expand([self.match_times, num_gts])
- tar_anchor = paddle.arange(num_gts).expand([self.match_times, num_gts])
- pos_places = paddle.concat([top_pred, top_anchor]).reshape([-1])
- pos_inds = paddle.concat([tar_pred, tar_anchor]).reshape([-1])
- pos_anchor = anchor[pos_places]
- pos_tar_bbox = gt_bboxes[pos_inds]
- pos_ious = batch_bbox_overlaps(
- pos_anchor, pos_tar_bbox, is_aligned=True)
- pos_ignore = pos_ious < self.pos_ignore_thr
- pos_inds = paddle.where(pos_ignore,
- paddle.full_like(pos_inds, -2), pos_inds)
- match_labels[pos_places] = pos_inds
- match_labels.stop_gradient = True
- pos_keep = ~pos_ignore
- if pos_keep.sum() > 0:
- pos_places_keep = pos_places[pos_keep]
- pos_bbox_pred = bbox_pred[pos_places_keep].reshape([-1, 4])
- pos_bbox_tar = pos_tar_bbox[pos_keep].reshape([-1, 4]).detach()
- else:
- pos_bbox_pred = None
- pos_bbox_tar = None
- return match_labels, pos_bbox_pred, pos_bbox_tar
|