[损失函数]--Giou:Generalized Intersection over Union 代码实现

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文件里添加即可使用

猜你喜欢

转载自blog.csdn.net/weixin_42096202/article/details/91409046
今日推荐