GIOU,DIOU

一.IOU 

1.GIOU解決沒有交集的框,IOU爲0,其損失函數導數爲0,無法優化的問題。

圖1 GIOU,IOU,l2範數差異

a)可看出 l2值一樣,IOU值是不一樣的,也就是l2對於尺度不具有不變性

b)可看出當框有包含關係,GIOU就退化爲IOU

其是找到一個最小的封閉形狀C,讓C可以將A和B包圍在裏面,然後我們計算C中沒有覆蓋A和B的面積佔C總面積的比例S.

GIOU = IOU - S

可看出,GIOU<=IOU

圖2 GIOU 計算公式

 

GIOU的損失函數算法:

1.代碼 

import numpy as np
def Giou(box1, box2):
    xmin1, ymin1, xmax1, ymax1 = box1
    xmin2, ymin2, xmax2, ymax2 = box2
    xx1 = np.max([xmin1, xmin2])
    yy1 = np.max([ymin1, ymin2])
    xx2 = np.min([xmax1, xmax2])
    yy2 = np.min([ymax1, ymax2])
    # 計算兩個矩形框面積
    area1 = (xmax1-xmin1) * (ymax1-ymin1)
    area2 = (xmax2-xmin2) * (ymax2-ymin2)
    inter_area = (np.max([0, xx2-xx1])) * (np.max([0, yy2-yy1]))#計算交集面積
    iou = inter_area / (area1+area2-inter_area+1e-6)#計算交併比
    print('===inter_area:', inter_area)
    print('===iou:', iou)
    #兩個框的包圍面積
    area_C = (max(xmin1, xmax1, xmin2, xmax2) - min(xmin1, xmax1, xmin2, xmax2)) *\
             (max(ymin1, ymax1, ymin2, ymax2) - min(ymin1, ymax1, ymin2, ymax2))
    print('==area_C:', area_C)
    end_area = (area_C - inter_area) / area_C  #閉包區域中不屬於兩個框的區域佔閉包區域的比重
    giou = iou - end_area
    print('===giou:', giou)
    return giou

box1 = [0, 0, 2, 2]
box2 = [1, 1, 3, 3]
# box2 = [5, 5, 7, 7]
Giou(box1, box2)

二.DIOU

基於IoU和GIoU存在的問題:
1. 直接最小化anchor框與目標框之間的歸一化距離是否可行,以達到更快的收斂速度?
2. 如何使迴歸在與目標框有重疊甚至包含時更準確、更快?

其中,b,bgt分別代表了預測框和真實框的中心點,p2代表計算兩個中心點間的歐式距離。 c2代表的是能夠同時包含預測框和真實框的最小閉包區域的對角線距離。

DIoU loss可以直接最小化兩個目標框的距離,因此比GIoU loss收斂快得多。

1.DIOU代碼

import torch
def Diou(bboxes1, bboxes2):
    rows = bboxes1.shape[0]
    cols = bboxes2.shape[0]
    dious = torch.zeros((rows, cols))
    if rows * cols == 0:#
        return dious
    exchange = False
    if bboxes1.shape[0] > bboxes2.shape[0]:
        bboxes1, bboxes2 = bboxes2, bboxes1
        dious = torch.zeros((cols, rows))
        exchange = True
    # #xmin,ymin,xmax,ymax->[:,0],[:,1],[:,2],[:,3]
    w1 = bboxes1[:, 2] - bboxes1[:, 0]
    h1 = bboxes1[:, 3] - bboxes1[:, 1]
    w2 = bboxes2[:, 2] - bboxes2[:, 0]
    h2 = bboxes2[:, 3] - bboxes2[:, 1]

    area1 = w1 * h1
    area2 = w2 * h2

    center_x1 = (bboxes1[:, 2] + bboxes1[:, 0]) / 2
    center_y1 = (bboxes1[:, 3] + bboxes1[:, 1]) / 2
    center_x2 = (bboxes2[:, 2] + bboxes2[:, 0]) / 2
    center_y2 = (bboxes2[:, 3] + bboxes2[:, 1]) / 2

    inter_max_xy = torch.min(bboxes1[:, 2:], bboxes2[:, 2:])
    inter_min_xy = torch.max(bboxes1[:, :2], bboxes2[:, :2])
    print('==inter_min_xy:', inter_min_xy)
    print('==inter_max_xy:', inter_max_xy)

    out_max_xy = torch.max(bboxes1[:, 2:], bboxes2[:, 2:])
    out_min_xy = torch.min(bboxes1[:, :2], bboxes2[:, :2])

    print('==out_min_xy:', out_min_xy)
    print('==out_max_xy:', out_max_xy)

    inter = torch.clamp((inter_max_xy - inter_min_xy), min=0)
    inter_area = inter[:, 0] * inter[:, 1]
    inter_diag = (center_x2 - center_x1)**2 + (center_y2 - center_y1)**2
    
    outer = torch.clamp((out_max_xy - out_min_xy), min=0)
    outer_diag = (outer[:, 0] ** 2) + (outer[:, 1] ** 2)
    union = area1+area2-inter_area
    dious = inter_area / union - (inter_diag) / outer_diag
    dious = torch.clamp(dious,min=-1.0, max = 1.0)
    if exchange:
        dious = dious.T
    return dious


box1 = torch.from_numpy(np.array([[0, 0, 2, 2]]))
box2 = torch.from_numpy(np.array([[1, 1, 3, 3]]))
Diou(box1, box2)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章