Example #1
0
    def get_anchor_labels(self, anchors, gt_boxes):
        '''
        label each anchor as fg/bg/ignore
        :param anchors: Ax4
        :param gt_boxes: Bx4
        :return:
            anchor_labels: (A,), int, each element is {-1, 0, 1}
            anchor_boxes: Ax4, the target gt_box for each anchor when the anchor is fg
        '''

        def filter_box_label(labels, value, max_num):
            curr_inds = np.where(labels == value)[0]
            if len(curr_inds) > max_num:
                disable_inds = np.random.choice(curr_inds, size=(len(curr_inds) - max_num), replace=False)
                labels[disable_inds] = -1
                curr_inds = np.where(labels == value)[0]
            return curr_inds

        NA, NB = len(anchors), len(gt_boxes)
        if NB == 0:
            anchor_labels = np.zeros((NA,), dtype=np.int32)
            filter_box_label(anchor_labels, 0, max_num=cfg.FRCNN.RPN.BATCH_PER_IM)
            return anchor_labels, np.zeros((NA, 4), dtype=np.float32)

        box_ious = np_iou(anchors, gt_boxes)  # NAxNB
        ious_argmax_per_anchor = box_ious.argmax(axis=1)  # NA
        ious_max_per_anchor = box_ious.max(axis=1)
        ious_max_per_gt = np.amax(box_ious, axis=0, keepdims=True) # 1xNB
        anchors_with_max_iou_per_gt = np.where(box_ious == ious_max_per_gt)[0]

        anchor_labels = -np.ones((NA, ), dtype=np.int32)
        anchor_labels[anchors_with_max_iou_per_gt] = 1
        anchor_labels[ious_max_per_anchor >= cfg.FRCNN.RPN.POSITIVE_ANCHOR_THRESH] = 1
        anchor_labels[ious_max_per_anchor < cfg.FRCNN.RPN.NEGATIVE_ANCHOR_THRESH] = 0

        # label all non-ignore candidate boxes which overlap crowd as ignore
        # if crowd_boxes.size > 0:
        #     cand_inds = np.where(anchor_labels >= 0)[0]
        #     cand_anchors = anchors[cand_inds]
        #     ioas = np_ioa(crowd_boxes, cand_anchors)
        #     overlap_with_crowd = cand_inds[ioas.max(axis=0) > cfg.FRCNN.RPN.CROWD_OVERLAP_THRESH]
        #     anchor_labels[overlap_with_crowd] = -1

        # subsample fg labels: ignore some fg if fg is too many
        target_sum_fg = int(cfg.FRCNN.RPN.BATCH_PER_IM * cfg.FRCNN.RPN.FG_RATIO)
        fg_inds = filter_box_label(anchor_labels, 1, target_sum_fg)

        # subsample bg labels: num_bg is not allowed to be too many
        old_num_bg = np.sum(anchor_labels == 0)
        if old_num_bg == 0:
            raise BaseException
        target_num_bg = cfg.FRCNN.RPN.BATCH_PER_IM - len(fg_inds)
        filter_box_label(anchor_labels, 0, target_num_bg)

        anchor_boxes = np.zeros((NA, 4), dtype=np.float32)
        fg_boxes = gt_boxes[ious_argmax_per_anchor[fg_inds], :]
        anchor_boxes[fg_inds, :] = fg_boxes

        return anchor_labels, anchor_boxes
Example #2
0
def draw_proposal_recall(img, proposals, proposal_scores, gt_boxes):
    """
    Draw top3 proposals for each gt.
    Args:
        proposals: NPx4
        proposal_scores: NP
        gt_boxes: NG
    """
    box_ious = np_iou(gt_boxes, proposals)    # ng x np
    box_ious_argsort = np.argsort(-box_ious, axis=1)
    good_proposals_ind = box_ious_argsort[:, :3]   # for each gt, find 3 best proposals
    good_proposals_ind = np.unique(good_proposals_ind.ravel())

    proposals = proposals[good_proposals_ind, :]
    tags = list(map(str, proposal_scores[good_proposals_ind]))
    img = viz.draw_boxes(img, proposals, tags)
    return img, good_proposals_ind
Example #3
0
def draw_proposal_recall(img, proposals, proposal_scores, gt_boxes):
    """
    Draw top3 proposals for each gt.
    Args:
        proposals: NPx4
        proposal_scores: NP
        gt_boxes: NG
    """
    box_ious = np_iou(gt_boxes, proposals)    # ng x np
    box_ious_argsort = np.argsort(-box_ious, axis=1)
    good_proposals_ind = box_ious_argsort[:, :3]   # for each gt, find 3 best proposals
    good_proposals_ind = np.unique(good_proposals_ind.ravel())

    proposals = proposals[good_proposals_ind, :]
    tags = list(map(str, proposal_scores[good_proposals_ind]))
    img = viz.draw_boxes(img, proposals, tags)
    return img, good_proposals_ind
Example #4
0
    def get_retinanet_anchor_labels(self, anchors, gt_boxes, gt_labels):
        '''
        label each anchor as fg/bg/ignore
        :param anchors: Ax4
        :param gt_boxes: Bx4
        :param gt_labels: Bx1
        :return:
            anchor_labels: (A,), int, each element is {-1, 0, C}  C is in [1, NUM_CATEGORY+1]
            anchor_boxes: Ax4, the target gt_box for each anchor when the anchor is fg
        '''

        NA, NB = len(anchors), len(gt_boxes)
        if NB == 0:
            anchor_labels = np.zeros((NA,), dtype=np.int32)
            return anchor_labels, np.zeros((NA, 4), dtype=np.float32)

        box_ious = np_iou(anchors, gt_boxes)  # NAxNB
        ious_argmax_per_anchor = box_ious.argmax(axis=1)  # NA
        ious_max_per_anchor = box_ious.max(axis=1)
        ious_max_per_gt = np.amax(box_ious, axis=0, keepdims=True) # 1xNB
        anchors_with_max_iou_per_gt = np.where(box_ious == ious_max_per_gt)[0]

        anchor_labels = -np.ones((NA, ), dtype=np.int32)
        anchor_labels[anchors_with_max_iou_per_gt] = 1
        anchor_labels[ious_max_per_anchor >= cfg.RETINANET.POSITIVE_ANCHOR_THRESH] = 1
        anchor_labels[ious_max_per_anchor < cfg.RETINANET.NEGATIVE_ANCHOR_THRESH] = 0

        # label all non-ignore candidate boxes which overlap crowd as ignore
        # if crowd_boxes.size > 0:
        #     cand_inds = np.where(anchor_labels >= 0)[0]
        #     cand_anchors = anchors[cand_inds]
        #     ioas = np_ioa(crowd_boxes, cand_anchors)
        #     overlap_with_crowd = cand_inds[ioas.max(axis=0) > cfg.FRCNN.RPN.CROWD_OVERLAP_THRESH]
        #     anchor_labels[overlap_with_crowd] = -1

        fg_inds = np.where(anchor_labels == 1)[0]
        anchor_boxes = np.zeros((NA, 4), dtype=np.float32)
        fg_boxes = gt_boxes[ious_argmax_per_anchor[fg_inds], :]
        fg_labels = gt_labels[ious_argmax_per_anchor[fg_inds]].reshape(-1)
        anchor_boxes[fg_inds, :] = fg_boxes
        anchor_labels[fg_inds] = fg_labels   # [0, 80]

        return anchor_labels, anchor_boxes
def cal_avg_iou_per_gt(gt_boxes, sizes, ratios, imageHW=768):
    def filter_box_inside(im, boxes):
        h, w = im.shape[:2]
        indices = np.where(
            (boxes[:, 0] >= 0) &
            (boxes[:, 1] >= 0) &
            (boxes[:, 2] <= w) &
            (boxes[:, 3] <= h))[0]
        return indices
    im = np.zeros((imageHW, imageHW))
    ALL_ANCHORS = get_all_anchors(sizes=sizes, ratios=ratios)
    H, W = im.shape[:2]
    featureH, featureW = H // 16, W // 16
    featuremap_anchors = ALL_ANCHORS[:featureH, :featureW, :, :]
    featuremap_anchors_flatten = featuremap_anchors.reshape((-1, 4))
    inside_ind = filter_box_inside(im, featuremap_anchors_flatten)
    inside_anchors = featuremap_anchors_flatten[inside_ind, :]

    anchors = inside_anchors
    box_ious = np_iou(anchors, gt_boxes)  # NA x NB
    ious_argmax_per_anchor = box_ious.argmax(axis=1)  # NA,
    ious_max_per_anchor = box_ious.max(axis=1)
    ious_max_per_gt = np.amax(box_ious, axis=0, keepdims=True)  # 1xNB
    return ious_max_per_gt.mean()
Example #6
0
def get_anchor_labels(anchors, gt_boxes, crowd_boxes):
    """
    Label each anchor as fg/bg/ignore.
    Args:
        anchors: Ax4 float
        gt_boxes: Bx4 float
        crowd_boxes: Cx4 float

    Returns:
        anchor_labels: (A,) int. Each element is {-1, 0, 1}
        anchor_boxes: Ax4. Contains the target gt_box for each anchor when the anchor is fg.
    """

    # This function will modify labels and return the filtered inds
    def filter_box_label(labels, value, max_num):
        curr_inds = np.where(labels == value)[0]
        if len(curr_inds) > max_num:
            disable_inds = np.random.choice(curr_inds,
                                            size=(len(curr_inds) - max_num),
                                            replace=False)
            labels[disable_inds] = -1  # ignore them
            curr_inds = np.where(labels == value)[0]
        return curr_inds

    NA, NB = len(anchors), len(gt_boxes)
    assert NB > 0  # empty images should have been filtered already
    box_ious = np_iou(anchors, gt_boxes)  # NA x NB
    ious_argmax_per_anchor = box_ious.argmax(axis=1)  # NA,
    ious_max_per_anchor = box_ious.max(axis=1)
    ious_max_per_gt = np.amax(box_ious, axis=0, keepdims=True)  # 1xNB
    # for each gt, find all those anchors (including ties) that has the max ious with it
    anchors_with_max_iou_per_gt = np.where(box_ious == ious_max_per_gt)[0]

    # Setting NA labels: 1--fg 0--bg -1--ignore
    anchor_labels = -np.ones((NA, ), dtype='int32')  # NA,

    # the order of setting neg/pos labels matter
    anchor_labels[anchors_with_max_iou_per_gt] = 1
    anchor_labels[ious_max_per_anchor >= cfg.RPN.POSITIVE_ANCHOR_THRESH] = 1
    anchor_labels[ious_max_per_anchor < cfg.RPN.NEGATIVE_ANCHOR_THRESH] = 0

    # We can label all non-ignore candidate boxes which overlap crowd as ignore
    # But detectron did not do this.
    # if crowd_boxes.size > 0:
    #     cand_inds = np.where(anchor_labels >= 0)[0]
    #     cand_anchors = anchors[cand_inds]
    #     ious = np_iou(cand_anchors, crowd_boxes)
    #     overlap_with_crowd = cand_inds[ious.max(axis=1) > cfg.RPN.CROWD_OVERLAP_THRES]
    #     anchor_labels[overlap_with_crowd] = -1

    # Subsample fg labels: ignore some fg if fg is too many
    target_num_fg = int(cfg.RPN.BATCH_PER_IM * cfg.RPN.FG_RATIO)
    fg_inds = filter_box_label(anchor_labels, 1, target_num_fg)
    # Keep an image even if there is no foreground anchors
    # if len(fg_inds) == 0:
    #     raise MalformedData("No valid foreground for RPN!")

    # Subsample bg labels. num_bg is not allowed to be too many
    old_num_bg = np.sum(anchor_labels == 0)
    if old_num_bg == 0:
        # No valid bg in this image, skip.
        raise MalformedData("No valid background for RPN!")
    target_num_bg = cfg.RPN.BATCH_PER_IM - len(fg_inds)
    filter_box_label(anchor_labels, 0, target_num_bg)  # ignore return values

    # Set anchor boxes: the best gt_box for each fg anchor
    anchor_boxes = np.zeros((NA, 4), dtype='float32')
    fg_boxes = gt_boxes[ious_argmax_per_anchor[fg_inds], :]
    anchor_boxes[fg_inds, :] = fg_boxes
    # assert len(fg_inds) + np.sum(anchor_labels == 0) == cfg.RPN.BATCH_PER_IM
    return anchor_labels, anchor_boxes
Example #7
0
def get_anchor_labels(anchors, gt_boxes, crowd_boxes):
    """
    Label each anchor as fg/bg/ignore.
    Args:
        anchors: Ax4 float
        gt_boxes: Bx4 float
        crowd_boxes: Cx4 float

    Returns:
        anchor_labels: (A,) int. Each element is {-1, 0, 1}
        anchor_boxes: Ax4. Contains the target gt_box for each anchor when the anchor is fg.
    """
    # This function will modify labels and return the filtered inds
    def filter_box_label(labels, value, max_num):
        curr_inds = np.where(labels == value)[0]
        if len(curr_inds) > max_num:
            disable_inds = np.random.choice(
                curr_inds, size=(len(curr_inds) - max_num),
                replace=False)
            labels[disable_inds] = -1    # ignore them
            curr_inds = np.where(labels == value)[0]
        return curr_inds

    NA, NB = len(anchors), len(gt_boxes)
    assert NB > 0  # empty images should have been filtered already
    box_ious = np_iou(anchors, gt_boxes)  # NA x NB
    ious_argmax_per_anchor = box_ious.argmax(axis=1)  # NA,
    ious_max_per_anchor = box_ious.max(axis=1)
    ious_max_per_gt = np.amax(box_ious, axis=0, keepdims=True)  # 1xNB
    # for each gt, find all those anchors (including ties) that has the max ious with it
    anchors_with_max_iou_per_gt = np.where(box_ious == ious_max_per_gt)[0]

    # Setting NA labels: 1--fg 0--bg -1--ignore
    anchor_labels = -np.ones((NA,), dtype='int32')   # NA,

    # the order of setting neg/pos labels matter
    anchor_labels[anchors_with_max_iou_per_gt] = 1
    anchor_labels[ious_max_per_anchor >= config.POSITIVE_ANCHOR_THRES] = 1
    anchor_labels[ious_max_per_anchor < config.NEGATIVE_ANCHOR_THRES] = 0

    # First label all non-ignore candidate boxes which overlap crowd as ignore
    if crowd_boxes.size > 0:
        cand_inds = np.where(anchor_labels >= 0)[0]
        cand_anchors = anchors[cand_inds]
        ious = np_iou(cand_anchors, crowd_boxes)
        overlap_with_crowd = cand_inds[ious.max(axis=1) > config.CROWD_OVERLAP_THRES]
        anchor_labels[overlap_with_crowd] = -1

    # Filter fg labels: ignore some fg if fg is too many
    target_num_fg = int(config.RPN_BATCH_PER_IM * config.RPN_FG_RATIO)
    fg_inds = filter_box_label(anchor_labels, 1, target_num_fg)
    # Note that fg could be fewer than the target ratio

    # filter bg labels. num_bg is not allowed to be too many
    old_num_bg = np.sum(anchor_labels == 0)
    if old_num_bg == 0 or len(fg_inds) == 0:
        # No valid bg/fg in this image, skip.
        # This can happen if, e.g. the image has large crowd.
        raise MalformedData("No valid foreground/background for RPN!")
    target_num_bg = config.RPN_BATCH_PER_IM - len(fg_inds)
    filter_box_label(anchor_labels, 0, target_num_bg)   # ignore return values

    # Set anchor boxes: the best gt_box for each fg anchor
    anchor_boxes = np.zeros((NA, 4), dtype='float32')
    fg_boxes = gt_boxes[ious_argmax_per_anchor[fg_inds], :]
    anchor_boxes[fg_inds, :] = fg_boxes
    return anchor_labels, anchor_boxes
Example #8
0
def get_anchor_labels_ignore(anchors, gt_boxes, crowd_boxes, ignore_boxes):
    """
    Label each anchor as fg/bg/ignore.
    Args:
        anchors: Ax4 float
        gt_boxes: Bx4 float
        crowd_boxes: Cx4 float
        ignore_boxes: Dx4 int

    Returns:
        anchor_labels: (A,) int. Each element is {-1, 0, 1}
        anchor_boxes: Ax4. Contains the target gt_box for each anchor when the anchor is fg.
    """

    # This function will modify labels and return the filtered inds
    def filter_box_label(labels, value, max_num):
        curr_inds = np.where(labels == value)[0]
        if len(curr_inds) > max_num:
            disable_inds = np.random.choice(curr_inds,
                                            size=(len(curr_inds) - max_num),
                                            replace=False)
            labels[disable_inds] = -1  # ignore them
            curr_inds = np.where(labels == value)[0]
        return curr_inds

    NA, NB = len(anchors), len(gt_boxes)
    assert NB > 0  # empty images should have been filtered already
    box_ious = np_iou(anchors, gt_boxes)  # NA x NB
    ious_argmax_per_anchor = box_ious.argmax(axis=1)  # NA,
    ious_max_per_anchor = box_ious.max(axis=1)
    ious_max_per_gt = np.amax(box_ious, axis=0, keepdims=True)  # 1xNB
    # for each gt, find all those anchors (including ties) that has the max ious with it
    anchors_with_max_iou_per_gt = np.where(box_ious == ious_max_per_gt)[0]

    # Setting NA labels: 1--fg 0--bg -1--ignore
    anchor_labels = -np.ones((NA, ), dtype='int32')  # NA,

    # the order of setting neg/pos labels matter
    anchor_labels[anchors_with_max_iou_per_gt] = 1
    anchor_labels[ious_max_per_anchor >= cfg.RPN.POSITIVE_ANCHOR_THRESH] = 1
    anchor_labels[ious_max_per_anchor < cfg.RPN.NEGATIVE_ANCHOR_THRESH] = 0

    # We can label all non-ignore candidate boxes which overlap crowd as ignore
    # But detectron did not do this.
    # if crowd_boxes.size > 0:
    #     cand_inds = np.where(anchor_labels >= 0)[0]
    #     cand_anchors = anchors[cand_inds]
    #     ious = np_iou(cand_anchors, crowd_boxes)
    #     overlap_with_crowd = cand_inds[ious.max(axis=1) > cfg.RPN.CROWD_OVERLAP_THRES]
    #     anchor_labels[overlap_with_crowd] = -1

    def to_xyxy(box):
        box = np.array(box)
        box[:, 2] += box[:, 0]
        box[:, 3] += box[:, 1]
        return box

    if len(ignore_boxes) > 0:
        ignores_xyxy = to_xyxy(ignore_boxes)
        box_left = anchors[:, 0].reshape(1, len(anchors))
        box_top = anchors[:, 1].reshape(1, len(anchors))
        box_right = anchors[:, 2].reshape(1, len(anchors))
        box_bottom = anchors[:, 3].reshape(1, len(anchors))
        box_area = (box_right - box_left) * (box_bottom - box_top)

        ignore_left = ignores_xyxy[:, 0].reshape(len(ignores_xyxy), 1)
        ignore_top = ignores_xyxy[:, 1].reshape(len(ignores_xyxy), 1)
        ignore_right = ignores_xyxy[:, 2].reshape(len(ignores_xyxy), 1)
        ignore_bottom = ignores_xyxy[:, 3].reshape(len(ignores_xyxy), 1)

        left = np.maximum(box_left, ignore_left)
        top = np.maximum(box_top, ignore_top)
        right = np.minimum(box_right, ignore_right)
        bottom = np.minimum(box_bottom, ignore_bottom)
        overlap = np.logical_and(left < right, top < bottom)
        overlap_area = (right - left) * (bottom - top)
        overlap_ratio = overlap_area / box_area
        overlap_pos = np.logical_and(overlap_ratio > 0.5, overlap)
        ignored = np.any(overlap_pos, axis=0)

        anchor_labels[ignored == True] = -1

    # def area(box):
    #     xmin, ymin, xmax, ymax = box
    #     return (xmax - xmin) * (yma
    #     xmin, ymin, xmax, ymax = box
    #     return (xmax - xmin) * (ymax - ymin)

    # for i in range(len(anchors)):
    #     for ignore in ignores_xyxy:
    #         top_left = [
    #             max(anchors[i][0], ignore[0]),
    #             max(anchors[i][1], ignore[1])
    #         ]
    #         bottom_right = [
    #             min(anchors[i][2], ignore[2]),
    #             min(anchors[i][3], ignore[3])
    #         ]
    #         if np.all(top_left<bottom_right):
    #             inter_area = area([*top_left, *bottom_right])
    #             anchor_area = area(anchors[i])
    #             if inter_area/anchor_area > 0.5:
    #                 anchor_labels[i] = -1

    # Subsample fg labels: ignore some fg if fg is too many
    target_num_fg = int(cfg.RPN.BATCH_PER_IM * cfg.RPN.FG_RATIO)
    fg_inds = filter_box_label(anchor_labels, 1, target_num_fg)
    # Keep an image even if there is no foreground anchors
    # if len(fg_inds) == 0:
    #     raise MalformedData("No valid foreground for RPN!")

    # Subsample bg labels. num_bg is not allowed to be too many
    old_num_bg = np.sum(anchor_labels == 0)
    if old_num_bg == 0:
        # No valid bg in this image, skip.
        raise MalformedData("No valid background for RPN!")
    target_num_bg = cfg.RPN.BATCH_PER_IM - len(fg_inds)
    filter_box_label(anchor_labels, 0, target_num_bg)  # ignore return values

    # Set anchor boxes: the best gt_box for each fg anchor
    anchor_boxes = np.zeros((NA, 4), dtype='float32')
    fg_boxes = gt_boxes[ious_argmax_per_anchor[fg_inds], :]
    anchor_boxes[fg_inds, :] = fg_boxes
    # assert len(fg_inds) + np.sum(anchor_labels == 0) == cfg.RPN.BATCH_PER_IM
    return anchor_labels, anchor_boxes