IOU、GIOU、DIOU、CIOU剖析及代码实现

 一、IOU

def iou(box, boxes):
    # box:[x1, y1, x2, y2] 左上角和右下角坐标
    # boxes: [[x1, y1, x2, y2], [x1, y1, x2, y2], [x1, y1, x2, y2]....] 包含很多个框
    box_area = (box[2]-box[0])*(box[3]-box[1])
    boxes_area = (boxes[:, 2]-boxes[:, 0])*(boxes[:, 3]-boxes[:, 1]) #第一个维度全取,第二个维度...

    # 求交集
    xx1 = torch.maximum(box[0], boxes[:, 0])
    yy1 = torch.maximum(box[1], boxes[:, 1])
    xx2 = torch.minimum(box[2], boxes[:, 2])
    yy2 = torch.minimum(box[3], boxes[:, 3])

    # 判断两个框有没有交集,如果xx2-xx1<0,w*h=0
    w,h = torch.maximum(torch.Tensor([0]), xx2-xx1), torch.maximum(torch.Tensor([0]), yy2-yy1)
    #交集的面积
    over_area = w*h

    # iou = 交集/并集
    return over_area/(box_area+boxes_area-over_area)

if __name__ == '__main__':
    box = torch.tensor([1, 1, 7, 7])
    boxes = torch.tensor([[1, 1, 10, 10], [4, 4, 7, 7], [3, 3, 6, 6], [2, 2, 7, 7]])
    print(iou(box,boxes))

二、GIOU

def Giou(box, boxes):
    # box:[x1, y1, x2, y2] 左上角和右下角坐标
    # boxes: [[x1, y1, x2, y2], [x1, y1, x2, y2], [x1, y1, x2, y2]....] 包含很多个框
    box_area = (box[2] - box[0]) * (box[3] - box[1])
    boxes_area = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1])  # 第一个维度全取,第二个维度...

    # 求交集
    xx1 = torch.maximum(box[0], boxes[:, 0])
    yy1 = torch.maximum(box[1], boxes[:, 1])
    xx2 = torch.minimum(box[2], boxes[:, 2])
    yy2 = torch.minimum(box[3], boxes[:, 3])

    # 判断两个框有没有交集,如果xx2-xx1<0,w*h=0
    w, h = torch.maximum(torch.Tensor([0]), xx2 - xx1), torch.maximum(torch.Tensor([0]), yy2 - yy1)
    # 交集的面积
    over_area = w * h

    # 求最小外接矩形
    xx11 = torch.minimum(box[0], boxes[:, 0])
    yy11 = torch.minimum(box[1], boxes[:, 1])
    xx22 = torch.maximum(box[2], boxes[:, 2])
    yy22 = torch.maximum(box[3], boxes[:, 3])
    w, h = xx22-xx11, yy22-yy11
    # 最小外接矩形面积
    max_area = w * h

    return over_area/(box_area + boxes_area - over_area)-((max_area)-(box_area + boxes_area - over_area))/max_area

if __name__ == '__main__':
    box = torch.tensor([1,1,7,7])
    boxes = torch.tensor([[1,1,10,10], [4,4,7,7], [3,3,6,6], [2,2,7,7]])
    print(Giou(box,boxes))

三、DIOU

def Diou(box, boxes):
    # box:[x1, y1, x2, y2] 左上角和右下角坐标
    # boxes: [[x1, y1, x2, y2], [x1, y1, x2, y2], [x1, y1, x2, y2]....] 包含很多个框
    box_area = (box[2] - box[0]) * (box[3] - box[1])
    boxes_area = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1])  # 第一个维度全取,第二个维度...

    # 真实框中心点x坐标
    x1_center = (box[2] - box[0]) / 2 + box[0]
    # 真实框中心点y坐标
    y1_center = (box[3] - box[1]) / 2 + box[1]
    # 预测框中心点x坐标
    x2_center = (boxes[:, 2] - boxes[:, 0]) / 2 + boxes[:, 0]
    # 预测框中心点y坐标
    y2_center = (boxes[:, 3] - boxes[:, 1]) / 2 + boxes[:, 1]

    # print(x1_center, y1_center)
    # print(x2_center, y2_center)

    # 求交集
    xx1 = torch.maximum(box[0], boxes[:, 0])
    yy1 = torch.maximum(box[1], boxes[:, 1])
    xx2 = torch.minimum(box[2], boxes[:, 2])
    yy2 = torch.minimum(box[3], boxes[:, 3])
    # 判断两个框有没有交集,如果xx2-xx1<0,w*h=0
    w, h = torch.maximum(torch.Tensor([0]), xx2 - xx1), torch.maximum(torch.Tensor([0]), yy2 - yy1)
    # 交集的面积
    over_area = w * h

    # 求最小外接矩形
    xx11 = torch.minimum(box[0], boxes[:, 0])
    yy11 = torch.minimum(box[1], boxes[:, 1])
    xx22 = torch.maximum(box[2], boxes[:, 2])
    yy22 = torch.maximum(box[3], boxes[:, 3])

    P_sqrt = (x2_center-x1_center)**2 + (y2_center-y1_center)**2
    C_sqrt = (xx22-xx11)**2 + (yy22-yy11)**2

    return over_area/(box_area + boxes_area - over_area) - P_sqrt/C_sqrt


if __name__ == '__main__':
    box = torch.tensor([1,1,7,7])
    boxes = torch.tensor([[1,1,10,10], [4,4,7,7], [3,3,6,6], [2,2,7,7]])
    print(Diou(box,boxes))

四、CIOU

def Ciou(box, boxes):
    # box:[x1, y1, x2, y2] 左上角和右下角坐标
    # boxes: [[x1, y1, x2, y2], [x1, y1, x2, y2], [x1, y1, x2, y2]....] 包含很多个框
    box_area = (box[2] - box[0]) * (box[3] - box[1])
    boxes_area = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1])  # 第一个维度全取,第二个维度...

    # 真实框宽、高
    w_gt = box[2] - box[0]
    h_gt = box[3] - box[1]
    # 预测框宽、高
    w_pr = boxes[:, 2] - boxes[:, 0]
    h_pr = boxes[:, 3] - boxes[:, 1]

    # 真实框中心点x坐标
    x1_center = (box[2] - box[0]) / 2 + box[0]
    # 真实框中心点y坐标
    y1_center = (box[3] - box[1]) / 2 + box[1]
    # 预测框中心点x坐标
    x2_center = (boxes[:, 2] - boxes[:, 0]) / 2 + boxes[:, 0]
    # 预测框中心点y坐标
    y2_center = (boxes[:, 3] - boxes[:, 1]) / 2 + boxes[:, 1]

    # print(x1_center, y1_center)
    # print(x2_center, y2_center)

    # 求交集
    xx1 = torch.maximum(box[0], boxes[:, 0])
    yy1 = torch.maximum(box[1], boxes[:, 1])
    xx2 = torch.minimum(box[2], boxes[:, 2])
    yy2 = torch.minimum(box[3], boxes[:, 3])
    # 判断两个框有没有交集,如果xx2-xx1<0,w*h=0
    w, h = torch.maximum(torch.Tensor([0]), xx2 - xx1), torch.maximum(torch.Tensor([0]), yy2 - yy1)
    # 交集的面积
    over_area = w * h

    # 求最小外接矩形
    xx11 = torch.minimum(box[0], boxes[:, 0])
    yy11 = torch.minimum(box[1], boxes[:, 1])
    xx22 = torch.maximum(box[2], boxes[:, 2])
    yy22 = torch.maximum(box[3], boxes[:, 3])

    P_sqrt = (x2_center-x1_center)**2 + (y2_center-y1_center)**2
    C_sqrt = (xx22-xx11)**2 + (yy22-yy11)**2


    # v = (4 / (math.pi ** 2)) * torch.pow((torch.atan(w2 / h2) - torch.atan(w1 / h1)), 2)
    n = 4 / (math.pi ** 2)
    t = (np.arctan(w_gt / h_gt)-np.arctan(w_pr / h_pr))**2
    v = n * t
    S = 1 - over_area/(box_area + boxes_area - over_area) # 1-iou
    alpha = v / (S + v)

    return over_area/(box_area + boxes_area - over_area) - P_sqrt/C_sqrt - alpha*v


if __name__ == '__main__':
    box = torch.tensor([1,2,4,10])
    boxes = torch.tensor([[1,1,10,10], [4,4,7,7], [3,3,6,6], [2,2,7,7]])
    print(Ciou(box,boxes))

猜你喜欢

转载自blog.csdn.net/m0_56247038/article/details/127590989