示例#1
0
def get_windows(img_W, img_H, sizes, steps, in_rate_thr=0.6):
    assert 1 >= in_rate_thr >= 0, 'The `in_rate_thr` should lie in 0~1'
    windows = []
    for size, step in zip(sizes, steps):
        assert size > step, 'Size should large than step'

        x_num = 1 if img_W <= size else ceil((img_W - size) / step + 1)
        x_start = [step * i for i in range(x_num)]
        if len(x_start) > 1 and x_start[-1] + size > img_W:
            x_start[-1] = img_W - size

        y_num = 1 if img_H <= size else ceil((img_H - size) / step + 1)
        y_start = [step * i for i in range(y_num)]
        if len(y_start) > 1 and y_start[-1] + size > img_H:
            y_start[-1] = img_H - size

        start = np.array(list(product(x_start, y_start)), dtype=np.int64)
        windows.append(np.concatenate([start, start + size], axis=1))
    windows = np.concatenate(windows, axis=0)

    img_contour = np.array([[0, 0, img_W, img_H]])
    win_iofs = bt.bbox_overlaps(windows, img_contour, mode='iof').reshape(-1)
    if not np.any(win_iofs >= in_rate_thr):
        win_iofs[abs(win_iofs - win_iofs.max()) < 0.01] = 1

    return windows[win_iofs >= in_rate_thr]
示例#2
0
    def __call__(self, results):
        results['rotate_after_flip'] = self.rotate_after_flip
        if 'angle' not in results:
            results['angle'] = self.get_random_angle(results)
        if results['angle'] == 0:
            results['matrix'] = np.eye(3)
            return results
        matrix, w, h = self.get_matrix_and_size(results)
        results['matrix'] = matrix
        img_bound = np.array([[0, 0, w, 0, w, h, 0, h]])
        self.base_rotate(results, matrix, w, h, img_bound)

        for k in results.get('img_fields', []):
            if k != 'img':
                results[k] = cv2.warpAffine(results[k], matrix, (w, h))

        for k in results.get('bbox_fields', []):
            if k == 'gt_bboxes':
                continue
            warped_bboxes = bt.warp(results[k], matrix, keep_type=True)
            if self.keep_shape:
                iofs = bt.bbox_overlaps(warped_bboxes, img_bound, mode='iof')
                warped_bboxes = warped_bboxes[iofs[:, 0] > self.keep_iof_thr]
            results[k] = warped_bboxes

        for k in results.get('mask_fields', []):
            if k == 'gt_masks':
                continue
            polys = switch_mask_type(results[k], 'polygon')
            warped_polys = rotate_polygonmask(polys, matrix, w, h)
            if self.keep_shape:
                obbs = mask2bbox(warped_polys, 'obb')
                iofs = bt.bbox_overlaps(obbs, img_bound, mode='iof')
                index = np.nonzero(iofs[:, 0] > self.keep_iof_thr)[0]
                warped_polys = warped_polys[index]

            if isinstance(results[k], BitmapMasks):
                results[k] = switch_mask_type(warped_polys, 'bitmap')
            elif isinstance(results[k], PolygonMasks):
                results[k] = switch_mask_type(warped_polys, 'polygon')
            else:
                raise NotImplementedError

        for k in results.get('seg_fields', []):
            results[k] = cv2.warpAffine(results[k], matrix, (w, h))

        return results
示例#3
0
    def base_rotate(self, results, matrix, w, h, img_bound):
        if 'img' in results:
            img = cv2.warpAffine(results['img'], matrix, (w, h))
            results['img'] = img
            results['img_shape'] = img.shape

        if 'gt_masks' in results:
            polygons = switch_mask_type(results['gt_masks'], 'polygon')
            warped_polygons = rotate_polygonmask(polygons, matrix, w, h)

            if self.keep_shape:
                obbs = mask2bbox(warped_polygons, 'obb')
                iofs = bt.bbox_overlaps(obbs, img_bound, mode='iof')
                if_inwindow = iofs[:, 0] > self.keep_iof_thr
                index = np.nonzero(if_inwindow)[0]
                warped_polygons = warped_polygons[index]

            if isinstance(results['gt_masks'], BitmapMasks):
                results['gt_masks'] = switch_mask_type(warped_polygons,
                                                       'bitmap')
            elif isinstance(results['gt_masks'], PolygonMasks):
                results['gt_masks'] = switch_mask_type(warped_polygons,
                                                       'polygon')
            else:
                raise NotImplementedError

            if 'gt_bboxes' in results:
                results['gt_bboxes'] = mask2bbox(warped_polygons, 'hbb')

        elif 'gt_bboxes' in results:
            warped_bboxes = bt.warp(results['gt_bboxes'],
                                    matrix,
                                    keep_type=True)
            if self.keep_shape:
                iofs = bt.bbox_overlaps(warped_bboxes, img_bound, mode='iof')
                if_inwindow = iofs[:, 0] > self.keep_iof_thr
                # if ~if_inwindow.any():
                # return True
                warped_bboxes = warped_bboxes[if_inwindow]
            results['gt_bboxes'] = warped_bboxes

        if 'gt_labels' in results and self.keep_shape:
            results['gt_labels'] = results['gt_labels'][if_inwindow]

        for k in results.get('aligned_fields', []):
            if self.keep_shape:
                results[k] = results[k][if_inwindow]
示例#4
0
def eval_arb_recalls(gts,
                     proposals,
                     with_scores=True,
                     proposal_nums=None,
                     iou_thrs=0.5,
                     logger=None):
    """Calculate recalls.

    Args:
        gts (list[ndarray]): a list of arrays of shape (n, 4)
        proposals (list[ndarray]): a list of arrays of shape (k, 4) or (k, 5)
        proposal_nums (int | Sequence[int]): Top N proposals to be evaluated.
        iou_thrs (float | Sequence[float]): IoU thresholds. Default: 0.5.
        logger (logging.Logger | str | None): The way to print the recall
            summary. See `mmdet.utils.print_log()` for details. Default: None.

    Returns:
        ndarray: recalls of different ious and proposal nums
    """

    img_num = len(gts)
    assert img_num == len(proposals)

    proposal_nums, iou_thrs = set_recall_param(proposal_nums, iou_thrs)

    all_ious = []
    for i in range(img_num):
        if proposals[i].ndim == 2 and with_scores:
            scores = proposals[i][:, -1]
            sort_idx = np.argsort(scores)[::-1]
            img_proposal = proposals[i][sort_idx, :]
        else:
            img_proposal = proposals[i]
        if with_scores:
            img_proposal = img_proposal[:, :-1]
        prop_num = min(img_proposal.shape[0], proposal_nums[-1])
        if gts[i] is None or gts[i].shape[0] == 0:
            ious = np.zeros((0, img_proposal.shape[0]), dtype=np.float32)
        else:
            ious = bt.bbox_overlaps(gts[i], img_proposal[:prop_num])
        all_ious.append(ious)
    all_ious = np.array(all_ious)
    recalls = _recalls(all_ious, proposal_nums, iou_thrs)

    print_recall_summary(recalls, proposal_nums, iou_thrs, logger=logger)
    return recalls
示例#5
0
def get_window_obj(info, windows, iof_thr):
    bboxes = info['ann']['bboxes']
    iofs = bt.bbox_overlaps(bboxes, windows, mode='iof')

    window_anns = []
    for i in range(windows.shape[0]):
        win_iofs = iofs[:, i]
        pos_inds = np.nonzero(win_iofs >= iof_thr)[0].tolist()

        win_ann = dict()
        for k, v in info['ann'].items():
            try:
                win_ann[k] = v[pos_inds]
            except TypeError:
                win_ann[k] = [v[i] for i in pos_inds]
        win_ann['trunc'] = win_iofs[pos_inds] < 1
        window_anns.append(win_ann)
    return window_anns
    def __call__(self, bboxes1, bboxes2, mode='iou', is_aligned=False):
        """Calculate IoU between 2D bboxes

        Args:
            bboxes1 (Tensor): bboxes have shape (m, 4) in <x1, y1, x2, y2>
                format, or shape (m, 5) in <x1, y1, x2, y2, score> format.
            bboxes2 (Tensor): bboxes have shape (m, 4) in <x1, y1, x2, y2>
                format, shape (m, 5) in <x1, y1, x2, y2, score> format, or be
                empty. If is_aligned is ``True``, then m and n must be equal.
            mode (str): "iou" (intersection over union) or iof (intersection
                over foreground).

        Returns:
            ious(Tensor): shape (m, n) if is_aligned == False else shape (m, 1)
        """
        assert bboxes1.size(-1) in [0, 8, 9]
        assert bboxes2.size(-1) in [0, 8, 9]
        if bboxes2.size(-1) == 9:
            bboxes2 = bboxes2[..., :8]
        if bboxes1.size(-1) == 9:
            bboxes1 = bboxes1[..., :8]
        return bt.bbox_overlaps(bboxes1, bboxes2, mode, is_aligned)
示例#7
0
def tpfp_default(det_bboxes,
                 gt_bboxes,
                 gt_bboxes_ignore=None,
                 iou_thr=0.5,
                 area_ranges=None):
    """Check if detected bboxes are true positive or false positive.

    Args:
        det_bbox (ndarray): Detected bboxes of this image, of shape (m, 5).
        gt_bboxes (ndarray): GT bboxes of this image, of shape (n, 4).
        gt_bboxes_ignore (ndarray): Ignored gt bboxes of this image,
            of shape (k, 4). Default: None
        iou_thr (float): IoU threshold to be considered as matched.
            Default: 0.5.
        area_ranges (list[tuple] | None): Range of bbox areas to be evaluated,
            in the format [(min1, max1), (min2, max2), ...]. Default: None.

    Returns:
        tuple[np.ndarray]: (tp, fp) whose elements are 0 and 1. The shape of
            each array is (num_scales, m).
    """
    # an indicator of ignored gts
    gt_ignore_inds = np.concatenate((np.zeros(gt_bboxes.shape[0],
                                              dtype=np.bool),
                                     np.ones(gt_bboxes_ignore.shape[0],
                                             dtype=np.bool)))
    # stack gt_bboxes and gt_bboxes_ignore for convenience
    gt_bboxes = np.vstack((gt_bboxes, gt_bboxes_ignore))

    num_dets = det_bboxes.shape[0]
    num_gts = gt_bboxes.shape[0]
    if area_ranges is None:
        area_ranges = [(None, None)]
    num_scales = len(area_ranges)
    # tp and fp are of shape (num_scales, num_gts), each row is tp or fp of
    # a certain scale
    tp = np.zeros((num_scales, num_dets), dtype=np.float32)
    fp = np.zeros((num_scales, num_dets), dtype=np.float32)

    # if there is no gt bboxes in this image, then all det bboxes
    # within area range are false positives
    if gt_bboxes.shape[0] == 0:
        if area_ranges == [(None, None)]:
            fp[...] = 1
        else:
            det_areas = bt.bbox_areas(
                det_bboxes[:, :-1]
            )  #-------------------------------------------------
            for i, (min_area, max_area) in enumerate(area_ranges):
                fp[i, (det_areas >= min_area) & (det_areas < max_area)] = 1
        return tp, fp

    ious = bt.bbox_overlaps(det_bboxes[:, :-1],
                            gt_bboxes)  #------------------------------
    # for each det, the max iou with all gts
    ious_max = ious.max(axis=1)
    # for each det, which gt overlaps most with it
    ious_argmax = ious.argmax(axis=1)
    # sort all dets in descending order by scores
    sort_inds = np.argsort(-det_bboxes[:, -1])
    for k, (min_area, max_area) in enumerate(area_ranges):
        gt_covered = np.zeros(num_gts, dtype=bool)
        # if no area range is specified, gt_area_ignore is all False
        if min_area is None:
            gt_area_ignore = np.zeros_like(gt_ignore_inds, dtype=bool)
        else:
            gt_areas = bt.bbox_areas(
                gt_bboxes)  #------------------------------------
            gt_area_ignore = (gt_areas < min_area) | (gt_areas >= max_area)
        for i in sort_inds:
            if ious_max[i] >= iou_thr:
                matched_gt = ious_argmax[i]
                if not (gt_ignore_inds[matched_gt]
                        or gt_area_ignore[matched_gt]):
                    if not gt_covered[matched_gt]:
                        gt_covered[matched_gt] = True
                        tp[k, i] = 1
                    else:
                        fp[k, i] = 1
                # otherwise ignore this detected bbox, tp = 0, fp = 0
            elif min_area is None:
                fp[k, i] = 1
            else:
                bbox = det_bboxes[i:i + 1, :-1]
                area = bt.bbox_areas(
                    bbox)  #--------------------------------------------
                if area >= min_area and area < max_area:
                    fp[k, i] = 1
    return tp, fp