Функции обнаружения потери объекта IoU, GIou, DIoU и CIou

глубокое обучение

Введение

В задаче обнаружения цели классификация и регрессия кадра обнаружения являются основными вопросами.Выбор функции потерь оказывает большое влияние на производительность модели.В этой статье представлены часто используемые функции потерь.IoU,GIoU,DIouиCIoU.

IoU

IoUЭто наиболее широко используемая функция обнаружения потерь в блоке обнаружения, и большинство алгоритмов обнаружения используют этот метод.IoUТо есть коэффициент пересечения (Intersection over Union), отношение площади площади пересечения прогнозируемого кадра и реального кадра к площади объединенной области, формула расчета следующая

IoU

IoUреализация кода

import numpy as np

def Iou(box1, box2, wh=False):
    if wh == False:
        xmin1, ymin1, xmax1, ymax1 = box1
        xmin2, ymin2, xmax2, ymax2 = box2
    else:
        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)

    # 获取矩形框交集对应的左上角和右下角的坐标
    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, в это время возврат градиента отсутствует, и обучение и обучение не могут быть выполнены.

GIoU

2019CVPR,GIoUв диссертацииGeneralized Intersection over Union: A Metric and A Loss for Bounding Box Regressionпредложено в

Смысл приведенной выше формулы: сначала рассчитайте минимальную площадь замыкания двух ящиков(Он также включает площадь наименьшего ящика предсказанного ящика и реального ящика), затем вычислите долю площади, которая не принадлежит двум ящикам в закрытой области, к закрытой области, и, наконец, используйтеIoUВычтите этот вес, чтобы получитьGIoU.

GIoUреализация кода

def Giou(rec1,rec2):
    # 分别是第一个矩形左右上下的坐标
    x1,x2,y1,y2 = rec1 
    x3,x4,y3,y4 = rec2
    iou = 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_2

    # 第一个矩形的宽
    w1 = x2 - x1
    
    # 第二个矩形的宽
    w2 = x4 - x3   
    h1 = y1 - y2
    h2 = y3 - y4
    # 交叉部分的宽
    W = 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_area
    return giou

GIoUРассмотрение ситуации, когда кадр обнаружения и реальный кадр не перекрываются, но когда имеет место явление включения между кадром обнаружения и реальным кадромGIoUкакIoUЭто тот же эффект.

DIoU

DIoUкоторыйDistance-IoU, Рассчитывается следующим образом

в,b,представляют собой центральные точки предсказанного поля и поля истинности соответственно, иПредставляет вычисление евклидова расстояния между двумя центральными точками.cПредставляет диагональное расстояние наименьшей области замыкания, которая может содержать как предсказанный блок, так и блок истинности.

DIoUучитываяGIoUНедостатком также является увеличение минимального закрытия двух ящиков, включая реальный ящик и предсказанный ящик, ноDIoUВычисление - это не пересечение между прямоугольниками, а евклидово расстояние между каждым полем обнаружения, которое можно решитьGIoUПроблема возникает при одновременном включенииDIoUМинимизируйте расстояние между центральными точками между блоками прогнозирования, чтобы можно было достичь быстрой сходимости.

DIoUКод

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]) 
    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)**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

CIoU

CIoUкоторыйComplete-IoU, то есть вDIoUНа основе добавляется потеря длины и ширины, что позволяет еще быстрее сходиться и повышать производительность.

в,- весовая функция, аИспользуется для измерения сходства в соотношении сторон

и завершитьCIoUФункция потерь позиционируется как

CIoUГрадиент похож наDIoU, но и учитыватьГрадиент , когда длина и ширина находятся в [0, 1], вызовет взрыв градиента.

CIoUКод

def bbox_overlaps_ciou(bboxes1, bboxes2):
    rows = bboxes1.shape[0]
    cols = bboxes2.shape[0]
    cious = torch.zeros((rows, cols))
    if rows * cols == 0:
        return cious
    exchange = False
    if bboxes1.shape[0] > bboxes2.shape[0]:
        bboxes1, bboxes2 = bboxes2, bboxes1
        cious = torch.zeros((cols, rows))
        exchange = True

    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])
    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)**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
    u = (inter_diag) / outer_diag
    iou = inter_area / union
    with torch.no_grad():
        arctan = torch.atan(w2 / h2) - torch.atan(w1 / h1)
        v = (4 / (math.pi ** 2)) * torch.pow((torch.atan(w2 / h2) - torch.atan(w1 / h1)), 2)
        S = 1 - iou
        alpha = v / (S + v)
        w_temp = 2 * w1
    ar = (8 / (math.pi ** 2)) * arctan * ((w1 - w_temp) * h1)
    cious = iou - (u + alpha * ar)
    cious = torch.clamp(cious,min=-1.0,max = 1.0)
    if exchange:
        cious = cious.T
    return cious

использованная литература