Example #1
0
    def bbox_ciou(self, boxes1_x0y0x1y1, boxes2_x0y0x1y1):
        '''
        计算ciou = iou - p2/c2 - av
        :param boxes1: (batch_size, num_priors, 4)   pred_x0y0x1y1
        :param boxes2: (batch_size, num_priors, 4)   label_x0y0x1y1
        :return:
        '''

        # 得到中心点坐标、宽高
        boxes1 = P.concat(
            [(boxes1_x0y0x1y1[:, :, :2] + boxes1_x0y0x1y1[:, :, 2:]) * 0.5,
             boxes1_x0y0x1y1[:, :, 2:] - boxes1_x0y0x1y1[:, :, :2]],
            axis=-1)
        boxes2 = P.concat(
            [(boxes2_x0y0x1y1[:, :, :2] + boxes2_x0y0x1y1[:, :, 2:]) * 0.5,
             boxes2_x0y0x1y1[:, :, 2:] - boxes2_x0y0x1y1[:, :, :2]],
            axis=-1)

        # 两个矩形的面积
        boxes1_area = (boxes1_x0y0x1y1[:, :, 2] - boxes1_x0y0x1y1[:, :, 0]) * (
            boxes1_x0y0x1y1[:, :, 3] - boxes1_x0y0x1y1[:, :, 1])
        boxes2_area = (boxes2_x0y0x1y1[:, :, 2] - boxes2_x0y0x1y1[:, :, 0]) * (
            boxes2_x0y0x1y1[:, :, 3] - boxes2_x0y0x1y1[:, :, 1])

        # 相交矩形的左上角坐标、右下角坐标
        left_up = P.elementwise_max(boxes1_x0y0x1y1[:, :, :2],
                                    boxes2_x0y0x1y1[:, :, :2])
        right_down = P.elementwise_min(boxes1_x0y0x1y1[:, :, 2:],
                                       boxes2_x0y0x1y1[:, :, 2:])

        # 相交矩形的面积inter_area。iou
        inter_section = P.relu(right_down - left_up)
        inter_area = inter_section[:, :, 0] * inter_section[:, :, 1]
        union_area = boxes1_area + boxes2_area - inter_area
        iou = inter_area / union_area

        # 包围矩形的左上角坐标、右下角坐标
        enclose_left_up = P.elementwise_min(boxes1_x0y0x1y1[:, :, :2],
                                            boxes2_x0y0x1y1[:, :, :2])
        enclose_right_down = P.elementwise_max(boxes1_x0y0x1y1[:, :, 2:],
                                               boxes2_x0y0x1y1[:, :, 2:])

        # 包围矩形的对角线的平方
        enclose_wh = enclose_right_down - enclose_left_up
        enclose_c2 = P.pow(enclose_wh[:, :, 0], 2) + P.pow(
            enclose_wh[:, :, 1], 2)

        # 两矩形中心点距离的平方
        p2 = P.pow(boxes1[:, :, 0] - boxes2[:, :, 0], 2) + P.pow(
            boxes1[:, :, 1] - boxes2[:, :, 1], 2)

        # 增加av。分母boxes2[:, :, 3]可能为0,所以加了极小的常数防止nan
        atan1 = P.atan(boxes1[:, :, 2] / (boxes1[:, :, 3] + 1e-9))
        atan2 = P.atan(boxes2[:, :, 2] / (boxes2[:, :, 3] + 1e-9))
        v = 4.0 * P.pow(atan1 - atan2, 2) / (math.pi**2)
        a = v / (1 - iou + v)

        ciou = iou - 1.0 * p2 / enclose_c2 - 1.0 * a * v
        return ciou
Example #2
0
def _iou_hw(box_a, box_b, eps=1e-9):
    """计算两组矩形两两之间的iou以及长宽比信息
    Args:
        box_a: (tensor) bounding boxes, Shape: [A, 4].
        box_b: (tensor) bounding boxes, Shape: [B, 4].
    Return:
      (tensor) iou, Shape: [A, B].
    """
    A = box_a.shape[0]
    B = box_b.shape[0]

    box_a_rb = L.reshape(box_a[:, 2:], (A, 1, 2))
    box_a_rb = L.expand(box_a_rb, [1, B, 1])
    box_b_rb = L.reshape(box_b[:, 2:], (1, B, 2))
    box_b_rb = L.expand(box_b_rb, [A, 1, 1])
    max_xy = L.elementwise_min(box_a_rb, box_b_rb)

    box_a_lu = L.reshape(box_a[:, :2], (A, 1, 2))
    box_a_lu = L.expand(box_a_lu, [1, B, 1])
    box_b_lu = L.reshape(box_b[:, :2], (1, B, 2))
    box_b_lu = L.expand(box_b_lu, [A, 1, 1])
    min_xy = L.elementwise_max(box_a_lu, box_b_lu)

    inter = L.relu(max_xy - min_xy)
    inter = inter[:, :, 0] * inter[:, :, 1]

    box_a_w = box_a[:, 2]-box_a[:, 0]
    box_a_h = box_a[:, 3]-box_a[:, 1]
    area_a = box_a_h * box_a_w
    area_a = L.reshape(area_a, (A, 1))
    area_a = L.expand(area_a, [1, B])  # [A, B]

    box_b_w = box_b[:, 2]-box_b[:, 0]
    box_b_h = box_b[:, 3]-box_b[:, 1]
    area_b = box_b_h * box_b_w
    area_b = L.reshape(area_b, (1, B))
    area_b = L.expand(area_b, [A, 1])  # [A, B]

    union = area_a + area_b - inter
    iou = inter / union  # [A, B]  iou取值0~1之间,iou越大越应该抑制

    # 长宽比信息
    atan1 = L.atan(box_a_h / (box_a_w + eps))
    atan2 = L.atan(box_b_h / (box_b_w + eps))
    atan1 = L.reshape(atan1, (A, 1))
    atan1 = L.expand(atan1, [1, B])  # [A, B]
    atan2 = L.reshape(atan2, (1, B))
    atan2 = L.expand(atan2, [A, 1])  # [A, B]
    v = 4.0 * L.pow(atan1 - atan2, 2) / (math.pi ** 2)  # [A, B]  v取值0~1之间,v越小越应该抑制

    factor = 0.4
    overlap = L.pow(iou, (1 - factor)) * L.pow(1.0 - v, factor)

    return overlap
Example #3
0
def bbox_ciou(boxes1, boxes2):
    '''
    计算ciou = iou - p2/c2 - av
    :param boxes1: (8, 13, 13, 3, 4)   pred_xywh
    :param boxes2: (8, 13, 13, 3, 4)   label_xywh
    :return:
    '''

    # 变成左上角坐标、右下角坐标
    boxes1_x0y0x1y1 = P.concat([
        boxes1[:, :, :, :, :2] - boxes1[:, :, :, :, 2:] * 0.5,
        boxes1[:, :, :, :, :2] + boxes1[:, :, :, :, 2:] * 0.5
    ],
                               axis=-1)
    boxes2_x0y0x1y1 = P.concat([
        boxes2[:, :, :, :, :2] - boxes2[:, :, :, :, 2:] * 0.5,
        boxes2[:, :, :, :, :2] + boxes2[:, :, :, :, 2:] * 0.5
    ],
                               axis=-1)
    '''
    逐个位置比较boxes1_x0y0x1y1[..., :2]和boxes1_x0y0x1y1[..., 2:],即逐个位置比较[x0, y0]和[x1, y1],小的留下。
    比如留下了[x0, y0]
    这一步是为了避免一开始w h 是负数,导致x0y0成了右下角坐标,x1y1成了左上角坐标。
    '''
    boxes1_x0y0x1y1 = P.concat([
        P.elementwise_min(boxes1_x0y0x1y1[:, :, :, :, :2],
                          boxes1_x0y0x1y1[:, :, :, :, 2:]),
        P.elementwise_max(boxes1_x0y0x1y1[:, :, :, :, :2],
                          boxes1_x0y0x1y1[:, :, :, :, 2:])
    ],
                               axis=-1)
    boxes2_x0y0x1y1 = P.concat([
        P.elementwise_min(boxes2_x0y0x1y1[:, :, :, :, :2],
                          boxes2_x0y0x1y1[:, :, :, :, 2:]),
        P.elementwise_max(boxes2_x0y0x1y1[:, :, :, :, :2],
                          boxes2_x0y0x1y1[:, :, :, :, 2:])
    ],
                               axis=-1)

    # 两个矩形的面积
    boxes1_area = (
        boxes1_x0y0x1y1[:, :, :, :, 2] - boxes1_x0y0x1y1[:, :, :, :, 0]) * (
            boxes1_x0y0x1y1[:, :, :, :, 3] - boxes1_x0y0x1y1[:, :, :, :, 1])
    boxes2_area = (
        boxes2_x0y0x1y1[:, :, :, :, 2] - boxes2_x0y0x1y1[:, :, :, :, 0]) * (
            boxes2_x0y0x1y1[:, :, :, :, 3] - boxes2_x0y0x1y1[:, :, :, :, 1])

    # 相交矩形的左上角坐标、右下角坐标,shape 都是 (8, 13, 13, 3, 2)
    left_up = P.elementwise_max(boxes1_x0y0x1y1[:, :, :, :, :2],
                                boxes2_x0y0x1y1[:, :, :, :, :2])
    right_down = P.elementwise_min(boxes1_x0y0x1y1[:, :, :, :, 2:],
                                   boxes2_x0y0x1y1[:, :, :, :, 2:])

    # 相交矩形的面积inter_area。iou
    inter_section = P.relu(right_down - left_up)
    inter_area = inter_section[:, :, :, :, 0] * inter_section[:, :, :, :, 1]
    union_area = boxes1_area + boxes2_area - inter_area
    iou = inter_area / (union_area + 1e-9)

    # 包围矩形的左上角坐标、右下角坐标,shape 都是 (8, 13, 13, 3, 2)
    enclose_left_up = P.elementwise_min(boxes1_x0y0x1y1[:, :, :, :, :2],
                                        boxes2_x0y0x1y1[:, :, :, :, :2])
    enclose_right_down = P.elementwise_max(boxes1_x0y0x1y1[:, :, :, :, 2:],
                                           boxes2_x0y0x1y1[:, :, :, :, 2:])

    # 包围矩形的对角线的平方
    enclose_wh = enclose_right_down - enclose_left_up
    enclose_c2 = P.pow(enclose_wh[:, :, :, :, 0], 2) + P.pow(
        enclose_wh[:, :, :, :, 1], 2)

    # 两矩形中心点距离的平方
    p2 = P.pow(boxes1[:, :, :, :, 0] - boxes2[:, :, :, :, 0], 2) + P.pow(
        boxes1[:, :, :, :, 1] - boxes2[:, :, :, :, 1], 2)

    # 增加av。
    atan1 = P.atan(boxes1[:, :, :, :, 2] / (boxes1[:, :, :, :, 3] + 1e-9))
    atan2 = P.atan(boxes2[:, :, :, :, 2] / (boxes2[:, :, :, :, 3] + 1e-9))
    v = 4.0 * P.pow(atan1 - atan2, 2) / (math.pi**2)
    a = v / (1 - iou + v)

    ciou = iou - 1.0 * p2 / enclose_c2 - 1.0 * a * v
    return ciou
Example #4
0
    def __iou_loss(self, pred, targets, positive_mask, weights=None):
        """
        Calculate the loss for location prediction
        Args:
            pred          (Variables): bounding boxes prediction
            targets       (Variables): targets for positive samples
            positive_mask (Variables): mask of positive samples
            weights       (Variables): weights for each positive samples
        Return:
            loss (Varialbes): location loss
        """
        positive_mask = fluid.layers.reshape(positive_mask,
                                             (-1, ))  # [批大小*所有格子数, ]
        plw = pred[:, 0] * positive_mask  # [批大小*所有格子数, ], 预测的l
        pth = pred[:, 1] * positive_mask  # [批大小*所有格子数, ], 预测的t
        prw = pred[:, 2] * positive_mask  # [批大小*所有格子数, ], 预测的r
        pbh = pred[:, 3] * positive_mask  # [批大小*所有格子数, ], 预测的b
        tlw = targets[:, 0] * positive_mask  # [批大小*所有格子数, ], 真实的l
        tth = targets[:, 1] * positive_mask  # [批大小*所有格子数, ], 真实的t
        trw = targets[:, 2] * positive_mask  # [批大小*所有格子数, ], 真实的r
        tbh = targets[:, 3] * positive_mask  # [批大小*所有格子数, ], 真实的b
        tlw.stop_gradient = True
        trw.stop_gradient = True
        tth.stop_gradient = True
        tbh.stop_gradient = True
        area_target = (tlw + trw) * (tth + tbh)  # [批大小*所有格子数, ], 真实的面积
        area_predict = (plw + prw) * (pth + pbh)  # [批大小*所有格子数, ], 预测的面积
        ilw = fluid.layers.elementwise_min(plw, tlw)  # [批大小*所有格子数, ], 相交矩形的l
        irw = fluid.layers.elementwise_min(prw, trw)  # [批大小*所有格子数, ], 相交矩形的r
        ith = fluid.layers.elementwise_min(pth, tth)  # [批大小*所有格子数, ], 相交矩形的t
        ibh = fluid.layers.elementwise_min(pbh, tbh)  # [批大小*所有格子数, ], 相交矩形的b
        clw = fluid.layers.elementwise_max(plw, tlw)  # [批大小*所有格子数, ], 包围矩形的l
        crw = fluid.layers.elementwise_max(prw, trw)  # [批大小*所有格子数, ], 包围矩形的r
        cth = fluid.layers.elementwise_max(pth, tth)  # [批大小*所有格子数, ], 包围矩形的t
        cbh = fluid.layers.elementwise_max(pbh, tbh)  # [批大小*所有格子数, ], 包围矩形的b
        area_inter = (ilw + irw) * (ith + ibh)  # [批大小*所有格子数, ], 相交矩形的面积
        ious = (area_inter + 1.0) / (area_predict + area_target - area_inter +
                                     1.0)
        ious = ious * positive_mask
        if self.iou_loss_type.lower() == "linear_iou":
            loss = 1.0 - ious
        elif self.iou_loss_type.lower() == "giou":
            area_uniou = area_predict + area_target - area_inter
            area_circum = (clw + crw) * (cth + cbh) + 1e-7
            giou = ious - (area_circum - area_uniou) / area_circum
            loss = 1.0 - giou
        elif self.iou_loss_type.lower() == "iou":
            loss = 0.0 - fluid.layers.log(ious)
        elif self.iou_loss_type.lower() == "ciou":
            # 预测的矩形。cx_cy_w_h格式,以格子中心点为坐标原点。
            pred_cx = (prw - plw) * 0.5
            pred_cy = (pbh - pth) * 0.5
            pred_w = (plw + prw)
            pred_h = (pth + pbh)
            pred_cx = L.reshape(pred_cx, (-1, 1))
            pred_cy = L.reshape(pred_cy, (-1, 1))
            pred_w = L.reshape(pred_w, (-1, 1))
            pred_h = L.reshape(pred_h, (-1, 1))
            pred_cx_cy_w_h = L.concat([pred_cx, pred_cy, pred_w, pred_h],
                                      -1)  # [批大小*所有格子数, 4]

            # 真实的矩形。cx_cy_w_h格式,以格子中心点为坐标原点。
            true_cx = (trw - tlw) * 0.5
            true_cy = (tbh - tth) * 0.5
            true_w = (tlw + trw)
            true_h = (tth + tbh)
            true_cx = L.reshape(true_cx, (-1, 1))
            true_cy = L.reshape(true_cy, (-1, 1))
            true_w = L.reshape(true_w, (-1, 1))
            true_h = L.reshape(true_h, (-1, 1))
            true_cx_cy_w_h = L.concat([true_cx, true_cy, true_w, true_h],
                                      -1)  # [批大小*所有格子数, 4]

            # 预测的矩形。x0y0x1y1格式,以格子中心点为坐标原点。
            boxes1_x0y0x1y1 = L.concat([
                pred_cx_cy_w_h[:, :2] - pred_cx_cy_w_h[:, 2:] * 0.5,
                pred_cx_cy_w_h[:, :2] + pred_cx_cy_w_h[:, 2:] * 0.5
            ],
                                       axis=-1)

            # 真实的矩形。x0y0x1y1格式,以格子中心点为坐标原点。
            boxes2_x0y0x1y1 = L.concat([
                true_cx_cy_w_h[:, :2] - true_cx_cy_w_h[:, 2:] * 0.5,
                true_cx_cy_w_h[:, :2] + true_cx_cy_w_h[:, 2:] * 0.5
            ],
                                       axis=-1)

            # 包围矩形的左上角坐标、右下角坐标,shape 都是 (批大小*所有格子数, 2)
            enclose_left_up = L.elementwise_min(boxes1_x0y0x1y1[:, :2],
                                                boxes2_x0y0x1y1[:, :2])
            enclose_right_down = L.elementwise_max(boxes1_x0y0x1y1[:, 2:],
                                                   boxes2_x0y0x1y1[:, 2:])

            # 包围矩形的对角线的平方
            enclose_wh = enclose_right_down - enclose_left_up
            enclose_c2 = L.pow(enclose_wh[:, 0], 2) + L.pow(
                enclose_wh[:, 1], 2)

            # 两矩形中心点距离的平方
            p2 = L.pow(pred_cx_cy_w_h[:, 0] - true_cx_cy_w_h[:, 0], 2) \
                 + L.pow(pred_cx_cy_w_h[:, 1] - true_cx_cy_w_h[:, 1], 2)

            # 增加av。加上除0保护防止nan。
            atan1 = L.atan(pred_cx_cy_w_h[:, 2] /
                           (pred_cx_cy_w_h[:, 3] + 1e-9))
            atan2 = L.atan(true_cx_cy_w_h[:, 2] /
                           (true_cx_cy_w_h[:, 3] + 1e-9))
            v = 4.0 * L.pow(atan1 - atan2, 2) / (math.pi**2)
            a = v / (1 - ious + v)
            ciou = ious - 1.0 * p2 / (enclose_c2 + 1e-9) - 1.0 * a * v
            loss = 1.0 - ciou
        else:
            raise KeyError
        loss = fluid.layers.reshape(loss, (-1, 1))  # [批大小*所有格子数, 1]
        if weights is not None:
            loss = loss * weights
        return loss