Введение
В задаче обнаружения цели классификация и регрессия кадра обнаружения являются основными вопросами.Выбор функции потерь оказывает большое влияние на производительность модели.В этой статье представлены часто используемые функции потерь.IoU
,GIoU
,DIou
иCIoU
.
IoU
IoU
Это наиболее широко используемая функция обнаружения потерь в блоке обнаружения, и большинство алгоритмов обнаружения используют этот метод.IoU
То есть коэффициент пересечения (Intersection over Union
), отношение площади площади пересечения прогнозируемого кадра и реального кадра к площади объединенной области, формула расчета следующая
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