目錄
參考鏈接
前言
IOU(Intersection over Union)
?優點
缺點
代碼
存在的問題?
GIOU(Generalized Intersection over Union)
來源
GIOU公式
?實現代碼
存在的問題
DIoU(Distance-IoU)
來源
DIOU公式
?優點
實現代碼
總結
參考鏈接
IoU系列(IoU, GIoU, DIoU, CIoU)_iou giou diou_PoomHey的博客-CSDN博客
詳解IoU、GIoU、DIoU、CIoU、EIoU和DIoU-NMS_小Aer的博客-CSDN博客
【目標檢測算法】IOU、GIOU、DIOU、CIOU與YOLOv5損失函數_yolov5 iou-CSDN博客
前言
IOU損失函數目前主要應用于目標檢測的領域,其演變的過程如下:IOU --> GIOU --> DIOU -->CIOU損失函數,每一種損失函數都較上一種損失函數有所提升。下面來具體介紹這幾種損失函數。
IOU(Intersection over Union)
IoU就是我們所說的交并比,是目標檢測中最常用的指標,IOU Loss的定義是先求出預測框和真實框之間的交集和并集之比,再求負對數,但是在實際使用中我們常常將IOU Loss寫成1-IOU。如果兩個框重合則交并比等于1,Loss為0說明重合度非常高。IOU滿足非負性、同一性、對稱性、三角不等性,相比于L1/L2等損失函數還具有尺度不變性,不論box的尺度大小,輸出的iou損失總是在0-1之間。所以能夠較好的反映預測框與真實框的檢測效果。
?
?優點
- IOU具有尺度不變性,也就是對尺度不敏感(scale invariant), 在regression任務中,判斷predict box和gt的距離最直接的指標就是IoU。
- 滿足非負性;同一性;對稱性;三角不等性
缺點
- 如果兩個框沒有相交,根據定義,IoU=0,不能反映兩者的距離大小(重合度)。
?
- IoU無法精確的反映兩者的重合度大小。如下圖所示,三種情況IoU都相等,但看得出來他們的重合度是不一樣的,左邊的圖回歸的效果最好,右邊的最差。
?
代碼
import numpy as np
def Iou(box1, box2, wh=False):if wh == False:xmin1, ymin1, xmax1, ymax1 = box1xmin2, ymin2, xmax2, ymax2 = box2else:xmin1, ymin1 = int(box1[0]-box1[2]/2.0), int(box1[1]-box1[3]/2.0)xmax1, ymax1 = int(box1[0]+box1[2]/2.0), int(box1[1]+box1[3]/2.0)xmin2, ymin2 = int(box2[0]-box2[2]/2.0), int(box2[1]-box2[3]/2.0)xmax2, ymax2 = int(box2[0]+box2[2]/2.0), int(box2[1]+box2[3]/2.0)# 獲取矩形框交集對應的左上角和右下角的坐標(intersection)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) #計算交并比return iou
存在的問題?
普通IOU是對兩個框的距離不敏感的,如缺點一中的兩個圖中,左圖預測框的坐標要比右圖預測框的坐標更接近真實框。但兩者的IOU皆為0,如果直接把IOU當作loss函數進行優化,則loss=0,沒有梯度回傳,所以無法進行訓練。針對IOU的上述缺點GIOU應運而生?
GIOU(Generalized Intersection over Union)
來源
在CVPR2019中,論文?《Generalized Intersection over Union: A Metric and A Loss for Bounding Box Regression》提出了GIoU的思想。由于IoU是比值的概念,對目標物體的scale是不敏感的。然而檢測任務中的BBox的回歸損失(MSE loss, l1-smooth loss等)優化和IoU優化不是完全等價的,而且 Ln 范數對物體的scale也比較敏感,IoU無法直接優化沒有重疊的部分。
?
GIOU公式
GIOU公式如下:
?
計算過程如下:
1.假設A為預測框,B為真實框,S是所有框的集合
2.不管A與B是否相交,C是包含A與B的最小框(包含A與B的最小凸閉合框),C也屬于S集合
3.首先計算IoU,A與B的交并比
4.再計算C框中沒有A與B的面積,比上C框面積;
5.IoU減去前面算出的比;得到GIoU
過程圖示如下所示:
?
當IOU為0時,意味著A與B非常遠時,
無限接近于0,GIOU趨近于-1,同理當IOU為1時,兩框重合,
為1。所以GIOU的取值為(-1, 1]。
GIOU作為loss函數時,為L = 1 ? GIOU ?,當A、B兩框不相交時A∪B值不變,最大化GIOU 就是就小化C,這樣就會促使兩個框不斷靠近。
?實現代碼
def Giou(rec1,rec2):#分別是第一個矩形左右上下的坐標x1,x2,y1,y2 = rec1 x3,x4,y3,y4 = rec2iou = Iou(rec1,rec2)area_C = (max(x1,x2,x3,x4)-min(x1,x2,x3,x4))*(max(y1,y2,y3,y4)-min(y1,y2,y3,y4))area_1 = (x2-x1)*(y1-y2)area_2 = (x4-x3)*(y3-y4)sum_area = area_1 + area_2w1 = x2 - x1 #第一個矩形的寬w2 = x4 - x3 #第二個矩形的寬h1 = y1 - y2h2 = y3 - y4W = min(x1,x2,x3,x4)+w1+w2-max(x1,x2,x3,x4) #交叉部分的寬H = min(y1,y2,y3,y4)+h1+h2-max(y1,y2,y3,y4) #交叉部分的高Area = W*H #交叉的面積add_area = sum_area - Area #兩矩形并集的面積end_area = (area_C - add_area)/area_C #閉包區域中不屬于兩個框的區域占閉包區域的比重giou = iou - end_areareturn giou
存在的問題
盡管GIoU解決了在IoU作為損失函數時梯度無法計算的問題,且加入了最小外包框作為懲罰項。但是它任然存在一些問題。下圖第一行的三張圖片是GIoU迭代時預測框收斂情況。其中黑色框代表anchor,藍色框代表預測框,綠色框代表真實框。
?
上圖中可以看出,GIoU在開始的時候需要將檢測結果方法使其與目標框相交,之后才開始縮小檢測結果與GT重合,這就帶來了需要較多的迭代次數才能收斂問題,特別是對于水平與垂直框的情況下。此外,其在一個框包含另一個框的情況下(),GIoU降退化成IoU,無法評價好壞,見下圖所示:
?
對此,DIOU又被提出
DIoU(Distance-IoU)
來源
針對上述GIOU的兩個問題(預測框和真實框是包含關系的情況或者處于水平/垂直方向上,GIOU損失幾乎已退化為IOU損失,即 |C - A U B | --> 0 ,導致收斂較慢)。有學者將GIOU中引入最小外接框來最大化重疊面積的懲罰項修改成最小化兩個BBox中心點的標準化距離從而加速損失的收斂過程。該方法出自2020年AAAI 文章《Distance-IoU Loss: Faster and Better Learning for Bounding Box Regression》
DIoU要比GIou更加符合目標框回歸的機制,將目標與anchor之間的距離,重疊率以及尺度都考慮進去,使得目標框回歸變得更加穩定,不會像IoU和GIoU一樣出現訓練過程中發散等問題。
DIOU公式
?其中,?分別代表了預測框與真實框的中心點,
?代表的是兩個中心點之間的歐式距離,C代表的是能夠同時包含預測框和真實框的最小閉包區域(最小外接矩形)的對角線距離。 如下圖所示:
?優點
- DIoU Loss的懲罰項能夠直接最小化中心點間的距離,而且GIoU Loss旨在減少外界包圍框的面積。
- DIoU與IoU,GIoU一樣具有尺度不變性。
- DIoU與GIoU一樣在與目標框不重疊時,仍然可以為邊界框提供移動方向
- DIoU可以直接最小化兩個目標框的距離,因此比GIoU Loss 收斂快得多
- DIoU在包含兩個水平或垂直方向上的情況回歸很快,而GIoU幾乎退化為IoU。
?
實現代碼
def Diou(bboxes1, bboxes2):rows = bboxes1.shape[0]cols = bboxes2.shape[0]dious = torch.zeros((rows, cols))if rows * cols == 0:#return diousexchange = Falseif bboxes1.shape[0] > bboxes2.shape[0]:bboxes1, bboxes2 = bboxes2, bboxes1dious = 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 * h1area2 = w2 * h2center_x1 = (bboxes1[:, 2] + bboxes1[:, 0]) / 2 center_y1 = (bboxes1[:, 3] + bboxes1[:, 1]) / 2 center_x2 = (bboxes2[:, 2] + bboxes2[:, 0]) / 2center_y2 = (bboxes2[:, 3] + bboxes2[:, 1]) / 2inter_max_xy = torch.min(bboxes1[:, 2:],bboxes2[:, 2:]) inter_min_xy = torch.max(bboxes1[:, :2],bboxes2[:, :2]) out_max_xy = torch.max(bboxes1[:, 2:],bboxes2[:, 2:]) out_min_xy = torch.min(bboxes1[:, :2],bboxes2[:, :2])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)**2outer = torch.clamp((out_max_xy - out_min_xy), min=0)outer_diag = (outer[:, 0] ** 2) + (outer[:, 1] ** 2)union = area1+area2-inter_areadious = inter_area / union - (inter_diag) / outer_diagdious = torch.clamp(dious,min=-1.0,max = 1.0)if exchange:dious = dious.Treturn dious
總結
IOU、GIOU、DIOU、CIOU的對比
邊界框回歸的三大集合因素:重疊面積、中心點距離、縱橫比
IoU: 考慮了重疊面積,歸一化坐標尺度
GIoU: 考慮了重疊面積,基于IoU解決邊界框不相交時loss等于0的問題。
DIoU: 考慮了重疊面積、中心點距離,基于IoU解決GIoU收斂慢的問題
CIoU: 考慮了重疊面積、中心點距離、縱橫比,基于DIoU提升回歸精確度
?