1.之前参加DF交通标志识别比赛,自己手写了个GIOU的损失函数,原理比较简单,可以自己去看一下相关论文,最后虽然由于时间不够没有用上,但是也许别人可以参考一下:
# coding = utf-8
import torch
def Giou_loss(box_pre, box_gt, method='mean'):
" " "
input:
box_pre : shape(N, 4) predicted x1, y1, x2, y2
box_gt : shape(N, 4) groundtruth x1, y1, x2, y2
return :
Giou loss
" " "
assert box_pre.shape == box_gt.shape
# 并集区域坐标
xx1 = torch.max(box_pre[:, 0], box_gt[:, 0])
yy1 = torch.max(box_pre[:, 1], box_gt[:, 1])
xx2 = torch.min(box_pre[:, 2], box_gt[:, 2])
yy2 = torch.min(box_pre[:, 3], box_gt[:, 3])
# 预测坐标面积
box_pre_area = (box_pre[:, 2] - box_pre[:, 0] + 1) * (box_pre[:, 3] - box_pre[:, 1] + 1)
# 标签坐标面积
box_gt_area = (box_gt[:, 2] - box_gt[:, 0] + 1) * (box_gt[:, 3] - box_gt[:, 1] + 1)
# inter 面积
inter = (xx2 - xx1 + 1) * (yy2 - yy1 + 1)
union = box_pre_area + box_gt_area - inter
iou = inter / union
# 最小封闭形状坐标
xx1_c = torch.min(box_pre[:, 0], box_gt[:, 0])
yy1_c = torch.min(box_pre[:, 1], box_gt[:, 1])
xx2_c = torch.max(box_pre[:, 2], box_gt[:, 2])
yy2_c = torch.max(box_pre[:, 3], box_gt[:, 3])
# C面积
area_c = (xx2_c - xx1_c) * (yy2_c - yy1_c)
# Giou
giou = iou - (area_c - union) / area_c
giou_loss = 1 - giou
if(method=='mean'):
return giou_loss.mean()
else:
return giou_loss.sum()
2.mmdetection上giou loss的实现
def generalized_iou_loss(pred, target, anchors, means, stds, reduction='mean'):
assert pred.size() == target.size() and target.numel() > 0
# dx, dy, dw, dh ---->px, py, pw, ph
bboxes_pred = delta2bbox(anchors, pred, means, stds).float()
bboxes_target = delta2bbox(anchors, target, means, stds) .float()
# 并集区域坐标
xx1 = torch.max(bboxes_pred[:, 0], bboxes_target[:, 0])
yy1 = torch.max(bboxes_pred[:, 1], bboxes_target[:, 1])
xx2 = torch.min(bboxes_pred[:, 2], bboxes_target[:, 2])
yy2 = torch.min(bboxes_pred[:, 3], bboxes_target[:, 3])
w = (xx2 - xx1 + 1).clamp(min=0)
h = (yy2 - yy1 + 1).clamp(min=0)
# pred, gt boxes面积
bboxes_pre_area = (bboxes_pred[:, 2] - bboxes_pred[:, 0] + 1) * (bboxes_pred[:, 3] - bboxes_pred[:, 1] + 1)
bboxes_tar_area = (bboxes_target[:, 2] - bboxes_target[:, 0] + 1) * (bboxes_target[:, 3] - bboxes_target[:, 1] + 1)
# 并集区域面积
inter = w*h
union = bboxes_pre_area + bboxes_tar_area - inter
iou = inter / (union + 1e-7)
# 最小封闭区域C
xx1_c = torch.min(bboxes_pred[:, 0], bboxes_target[:, 0])
yy1_c = torch.min(bboxes_pred[:, 1], bboxes_target[:, 1])
xx2_c = torch.max(bboxes_pred[:, 2], bboxes_target[:, 2])
yy2_c = torch.max(bboxes_pred[:, 3], bboxes_target[:, 3])
w_c = (xx2_c - xx1_c + 1).clamp(min=0)
h_c = (yy2_c - yy1_c + 1).clamp(min=0)
# C面积
area_c = w_c * h_c
giou = iou - (area_c - union) / area_c
giou_loss = 1 - giou
# none: 0, mean:1, sum: 2
reduction_enum = F._Reduction.get_enum(reduction)
if reduction_enum == 0:
return giou_oss
elif reduction_enum == 1:
return giou_loss.mean()
elif reduction_enum == 2:
return giou_loss.sum()
def weighted_generalized_iou(pred, target, anchors, means, stds, weight, avg_factor=None):
if avg_factor is None:
avg_factor = torch.sum(weight > 0).float().item() / 4 + 1e-6
giou_loss = generalized_iou_loss(pred, target, anchors, means, stds, reduction='none')
return torch.sum(loss * weight)[None] / avg_factor
然后在init文件里添加即可使用