• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

目标检测——map概念、Miou计算、IoU汇总IoU、GIoU、DIoU、CIoU、SIoU、EIoU、Wiou、Focal、alpha

武飞扬头像
Chaoy6565
帮助1

系列文章目录

目标检测——map概念、IoU汇总IoU、GIoU、DIoU、CIoU、SIoU、EIoU、Wiou、Focal、alpha
目标检测——YOLOv3、YOLOv4、YOLOv5、YOLOv7正负样本匹配、YOLO3损失函数理解
目标检测——SE、ECA、CA、SA、CBAM、ShuffleAttention、SimAM、CrissCrossAttention、SK、NAM、GAM、SOCA注意力模块、程序



前言


一、什么是map值?

map是Mean Average Precision 的缩写(均值平均精度)
介绍map之前,先了解以下概念
TP:True Positive,分类器预测结果为正样本,实际也为正样本,即正样本被正确识别的数量。
FP:False Positive,分类器预测结果为正样本,实际为负样本,即误报的负样本数量。
TN:True Negative,分类器预测结果为负样本,实际为负样本,即负样本被正确识别的数量。
FN:False Negative,分类器预测结果为负样本,实际为正样本,即漏报的正样本数量。
TP FN:真实正样本的总和,正确分类的正样本数量 漏报的正样本数量。
FP TN:真实负样本的总和,负样本被误识别为正样本数量 正确分类的负样本数量。
TP TN:正确分类的样本总和,正确分类的正样本数量 正确分类的负样本数量。
学新通

Precision:查准率、精度

Precision表征的是预测正确的正样本的准确度,查准率等于预测正确的正样本数量/所有预测为正样本数量。Precision越大说明误检的越少,Precision越小说明误检的越多。
Precision=TP/(TP FP)

Recall:查全率、召回率

Recall表征的是预测正确的正样本的覆盖率,查全率等于预测正确的正样本数量/所有正样本的总和,TP FN实际就是Ground Truth的数量。Recall越大说明漏检的越少,Recall越小说明漏检的越多。
Recall=TP/(TP FN)

目标检测中的PR,AP,mAP

学新通
目标检测中正负样本的定义是根据预测BB(Bounding Box)与真实目标框的IoU值来判定的,IoU阈值是提前人为设定的。而且对于不同网络算法或者数据集,其正负样本的划分标准不同,表中正负样本的划分只是本人自己定义的判定标准,实际情况可能有所不同。

仿照二分类任务的PR曲线可以得出目标检测中PR曲线是怎样得到的:
1,将模型在测试集上预测的所有BB按照置信度值从大到小进行降序排列。
2,以每个置信度值作为阈值,统计当前阈值下的预测正负样本数量,得到相应的TP,TN,FP,FN,计算出相应的P和R。
3,将不同阈值下的PR值连接起来,就是PR曲线。

对于目标检测来说,每一个类都可以计算出Precision和Recall,每个类都可以得到一条P-R曲线(P-R曲线,顾名思义,就是P-R的关系曲线图,表示了召回率和准确率之间的关系),曲线下的面积就是AP(平均精确度)的值。对所有AP的值求平均就是map。

语义分割Map、Miou计算

学新通
学新通
mIOU就是每一个类的IOU的平均,所以只需要对每一个类都按照第二步的公式计算IOU,再求平均获得mIOU就行了。

二、IoU汇总Iou、Giou、Ciou、Diou

学新通

2.1 Iou

Iou通俗来说也就是交并比,计算不同图像相互重叠比例。
I o U = A ∩ B A ∪ B IoU = \frac{A\cap B}{A\cup B} IoU=ABAB

学新通
IoU Loss具有非负性、尺度不变性、同一性、对称性、三角不等性等特点,但是如果|A∩B|=0,也就是两个图像没有相交时,无法比较两个图像的距离远近,无法体现两个图像到底是如何相交的。

2.2 Giou

GIoU比IoU多了一个‘Generalized’,能在更广义的层面上计算IoU,解决了两个图像没有相交时,无法比较两个图像的距离远近的问题。
G I O U = I o U − ∣ C − A ∪ B ∣ C GIOU = IoU- \frac{\left | C-A\cup B \right | }{C} GIOU=IoUCCAB
其中C代表两个图像的最小包庇面积,也可以理解为这两个图像的最小外接矩形的面积。GIoU不仅关注重叠区域,还关注其他的非重合区域,能更好的反映两者的重合度。GIoU完善了图像重叠度的计算功能,但仍无法对图形距离以及长宽比的相似性进行很好的表示。

2.3Diou

DIoU(Distance-IoU)将两个框之间的重叠度、距离、尺度都考虑了进来。
D i o u = I o u − ρ 2 ( b , b g t ) c 2 Diou = Iou-\frac{\rho ^{2}(b,b^{gt} ) }{c^{2} } Diou=Iouc2ρ2(b,bgt)
其中b,bgt分别代表两个框的中心点,ρ代表两个中心点之间的欧氏距离,C代表最小包庇矩形的对角线。
预测框和真实框的重叠程度。并且考虑到预测框长和宽的比值问题并以此添加惩罚项,从而使预测框的效果更加稳定
DIoU在完善图像重叠度的计算功能的基础上,实现了对图形距离的考量,但仍无法对图形长宽比的相似性进行很好的表示。

2.4 Ciou

学新通
可以看出,CIoU就是在DIoU的基础上,增加了图像相似性的影响因子,因此可以更好的反映两个框之间的差异性。
我们还需要注意的一点是,在使用CIoU作为Loss的时候,v的梯度同样会参与反向传播的计算。

2.5 Iou、Giou、Diou、Ciou代码

图片以左上角为中心点

# 以左上角为中心点
# box:[上, 左, 下, 右]
import numpy as np
import math

def IoU(box1, box2):
    # 计算中间矩形的宽高
    in_h = min(box1[2], box2[2]) - max(box1[0], box2[0])
    in_w = min(box1[3], box2[3]) - max(box1[1], box2[1])
    
    # 计算交集、并集面积
    inter = 0 if in_h < 0 or in_w < 0 else in_h * in_w
    union = (box1[2] - box1[0]) * (box1[3] - box1[1])   \
            (box2[2] - box2[0]) * (box2[3] - box2[1]) - inter
    # 计算IoU
    iou = inter / union
    return iou

def GIoU(box1, box2):
    # 计算最小包庇面积
    y1,x1,y2,x2 = box1 
    y3,x3,y4,x4 = box2
    area_C = (max(x1,x2,x3,x4)-min(x1,x2,x3,x4)) * \
             (max(y1,y2,y3,y4)-min(y1,y2,y3,y4))
    
    # 计算IoU
    in_h = min(box1[2], box2[2]) - max(box1[0], box2[0])
    in_w = min(box1[3], box2[3]) - max(box1[1], box2[1])
    inter = 0 if in_h < 0 or in_w < 0 else in_h * in_w
    union = (box1[2] - box1[0]) * (box1[3] - box1[1])   \
            (box2[2] - box2[0]) * (box2[3] - box2[1]) - inter
    iou = inter / union
    
    # 计算空白部分占比
    end_area = (area_C - union)/area_C
    giou = iou - end_area
    return giou

def CIoU(box1, box2):
    y1,x1,y2,x2 = box1 
    y3,x3,y4,x4 = box2
    
    iou = IoU(box1, box2)
    diou = DIoU(box1, box2)
 
    v = 4 / math.pi**2 * (math.atan((x2-x1)/(y2-y1)) - \
                          math.atan((x4-x3)/(y4-y3)))**2   1e-5
    alpha = v / ((1-iou)   v)
    
    ciou = diou - alpha * v
    return ciou

def DIoU(box1, box2):
    # 计算对角线长度
    y1,x1,y2,x2 = box1 
    y3,x3,y4,x4 = box2
    C = np.sqrt((max(x1,x2,x3,x4)-min(x1,x2,x3,x4))**2   \
                (max(y1,y2,y3,y4)-min(y1,y2,y3,y4))**2)
    
    # 计算中心点间距
    point_1 = ((x2 x1)/2, (y2 y1)/2)
    point_2 = ((x4 x3)/2, (y4 y3)/2)
    D = np.sqrt((point_2[0]-point_1[0])**2   \
                (point_2[1]-point_1[1])**2)
 
    # 计算IoU
    iou = IoU(box1, box2)
 
    # 计算空白部分占比
    lens = D**2 / C**2
    diou = iou - lens
    return diou

输出

# box:[上, 左, 下, 右]
box1 = [0,0,8,6]
box2 = [2,3,10,9]
print('Iou',IoU(box1, box2))
print('GIou',GIoU(box1, box2))
print('DIou',DIoU(box1, box2))
print('CIou',CIoU(box1, box2))

以h,w中心为中心点

import numpy as np
import torch
import math

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)
        
    # 获取矩形框交集对应的左上角和右下角的坐标(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

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

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

def 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

box_1 = box1 = [0,0,8,6]
box_2 = box2 = [2,3,10,9]
print('Iou',Iou(box1, box2))
print('Giou',Giou(box1, box2))

box1 = torch.unsqueeze(torch.tensor(box1), dim = 0)
box2 = torch.unsqueeze(torch.tensor(box2), dim = 0)
print('Diou',Diou(box1, box2))
print('Ciou',Ciou(box1, box2))

YOLO网络代码函数

GIoU、DIoU、CIoU、SIoU、EIoU、Focal、alpha

	# alpha参数为AlphaIoU中的alpha参数,默认为1,1的意思就是跟正常的IoU一样,如果想采用AlphaIoU的话,论文alpha默认值为3
	# gamma参数是Focal_IoU中的gamma参数,一般就是为0.5。
	def bbox_iou(self,box1, box2, x1y1x2y2=True, GIoU=False, DIoU=False, CIoU=False, SIoU=False, EIoU=False, Focal=False,
                 alpha=1, gamma=0.5, eps=1e-7):
        # Returns the IoU of box1 to box2. box1 is 4, box2 is nx4
        box2 = box2.T

        # Get the coordinates of bounding boxes
        if x1y1x2y2:  # x1, y1, x2, y2 = box1
            b1_x1, b1_y1, b1_x2, b1_y2 = box1[0], box1[1], box1[2], box1[3]
            b2_x1, b2_y1, b2_x2, b2_y2 = box2[0], box2[1], box2[2], box2[3]
        else:  # transform from xywh to xyxy
            b1_x1, b1_x2 = box1[0] - box1[2] / 2, box1[0]   box1[2] / 2
            b1_y1, b1_y2 = box1[1] - box1[3] / 2, box1[1]   box1[3] / 2
            b2_x1, b2_x2 = box2[0] - box2[2] / 2, box2[0]   box2[2] / 2
            b2_y1, b2_y2 = box2[1] - box2[3] / 2, box2[1]   box2[3] / 2

        # Intersection area
        inter = (torch.min(b1_x2, b2_x2) - torch.max(b1_x1, b2_x1)).clamp(0) * \
                (torch.min(b1_y2, b2_y2) - torch.max(b1_y1, b2_y1)).clamp(0)

        # Union Area
        w1, h1 = b1_x2 - b1_x1, b1_y2 - b1_y1   eps
        w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1   eps
        union = w1 * h1   w2 * h2 - inter   eps

        # IoU
        # iou = inter / union # ori iou
        iou = torch.pow(inter / (union   eps), alpha)  # alpha iou
        if CIoU or DIoU or GIoU or EIoU or SIoU:
            cw = b1_x2.maximum(b2_x2) - b1_x1.minimum(b2_x1)  # convex (smallest enclosing box) width
            ch = b1_y2.maximum(b2_y2) - b1_y1.minimum(b2_y1)  # convex height
            if CIoU or DIoU or EIoU or SIoU:  # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1
                c2 = (cw ** 2   ch ** 2) ** alpha   eps  # convex diagonal squared
                rho2 = (((b2_x1   b2_x2 - b1_x1 - b1_x2) ** 2   (
                            b2_y1   b2_y2 - b1_y1 - b1_y2) ** 2) / 4) ** alpha  # center dist ** 2
                if CIoU:  # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47
                    v = (4 / math.pi ** 2) * (torch.atan(w2 / h2) - torch.atan(w1 / h1)).pow(2)
                    with torch.no_grad():
                        alpha_ciou = v / (v - iou   (1   eps))
                    if Focal:
                        return iou - (rho2 / c2   torch.pow(v * alpha_ciou   eps, alpha)), torch.pow(
                            inter / (union   eps), gamma)  # Focal_CIoU
                    else:
                        return iou - (rho2 / c2   torch.pow(v * alpha_ciou   eps, alpha))  # CIoU
                elif EIoU:
                    rho_w2 = ((b2_x2 - b2_x1) - (b1_x2 - b1_x1)) ** 2
                    rho_h2 = ((b2_y2 - b2_y1) - (b1_y2 - b1_y1)) ** 2
                    cw2 = torch.pow(cw ** 2   eps, alpha)
                    ch2 = torch.pow(ch ** 2   eps, alpha)
                    if Focal:
                        return iou - (rho2 / c2   rho_w2 / cw2   rho_h2 / ch2), torch.pow(inter / (union   eps),
                                                                                          gamma)  # Focal_EIou
                    else:
                        return iou - (rho2 / c2   rho_w2 / cw2   rho_h2 / ch2)  # EIou
                elif SIoU:
                    # SIoU Loss https://arxiv.org/pdf/2205.12740.pdf
                    s_cw = (b2_x1   b2_x2 - b1_x1 - b1_x2) * 0.5   eps
                    s_ch = (b2_y1   b2_y2 - b1_y1 - b1_y2) * 0.5   eps
                    sigma = torch.pow(s_cw ** 2   s_ch ** 2, 0.5)
                    sin_alpha_1 = torch.abs(s_cw) / sigma
                    sin_alpha_2 = torch.abs(s_ch) / sigma
                    threshold = pow(2, 0.5) / 2
                    sin_alpha = torch.where(sin_alpha_1 > threshold, sin_alpha_2, sin_alpha_1)
                    angle_cost = torch.cos(torch.arcsin(sin_alpha) * 2 - math.pi / 2)
                    rho_x = (s_cw / cw) ** 2
                    rho_y = (s_ch / ch) ** 2
                    gamma = angle_cost - 2
                    distance_cost = 2 - torch.exp(gamma * rho_x) - torch.exp(gamma * rho_y)
                    omiga_w = torch.abs(w1 - w2) / torch.max(w1, w2)
                    omiga_h = torch.abs(h1 - h2) / torch.max(h1, h2)
                    shape_cost = torch.pow(1 - torch.exp(-1 * omiga_w), 4)   torch.pow(1 - torch.exp(-1 * omiga_h), 4)
                    if Focal:
                        return iou - torch.pow(0.5 * (distance_cost   shape_cost)   eps, alpha), torch.pow(
                            inter / (union   eps), gamma)  # Focal_SIou
                    else:
                        return iou - torch.pow(0.5 * (distance_cost   shape_cost)   eps, alpha)  # SIou
                if Focal:
                    return iou - rho2 / c2, torch.pow(inter / (union   eps), gamma)  # Focal_DIoU
                else:
                    return iou - rho2 / c2  # DIoU
            c_area = cw * ch   eps  # convex area
            if Focal:
                return iou - torch.pow((c_area - union) / c_area   eps, alpha), torch.pow(inter / (union   eps),
                                                                                          gamma)  # Focal_GIoU https://arxiv.org/pdf/1902.09630.pdf
            else:
                return iou - torch.pow((c_area - union) / c_area   eps,
                                       alpha)  # GIoU https://arxiv.org/pdf/1902.09630.pdf
        if Focal:
            return iou, torch.pow(inter / (union   eps), gamma)  # Focal_IoU
        else:
            return iou  # IoU

调用,计算预测框和真实框的回归损失

iou = self.bbox_iou(box.T, selected_tbox, x1y1x2y2=False, CIoU=True,)

Wiou

class WIoU_Scale:
    ''' monotonous: {
            None: origin v1
            True: monotonic FM v2
            False: non-monotonic FM v3
        }
        momentum: The momentum of running mean'''

    iou_mean = 1.
    monotonous = False
    _momentum = 1 - 0.5 ** (1 / 7000)
    _is_train = True

    def __init__(self, iou):
        self.iou = iou
        self._update(self)

    @classmethod
    def _update(cls, self):
        if cls._is_train: cls.iou_mean = (1 - cls._momentum) * cls.iou_mean   \
                                         cls._momentum * self.iou.detach().mean().item()

    @classmethod
    def _scaled_loss(cls, self, gamma=1.9, delta=3):
        if isinstance(self.monotonous, bool):
            if self.monotonous:
                return (self.iou.detach() / self.iou_mean).sqrt()
            else:
                beta = self.iou.detach() / self.iou_mean
                alpha = delta * torch.pow(gamma, beta - delta)
                return beta / alpha
        return 1
        
    def bbox_iou1(self,box1, box2, x1y1x2y2=True, GIoU=False, DIoU=False, CIoU=False, SIoU=False, EIoU=False, WIoU=False,
                 Focal=False, alpha=1, gamma=0.5, scale=False, eps=1e-7):
        # Returns the IoU of box1 to box2. box1 is 4, box2 is nx4
        box2 = box2.T

        # Get the coordinates of bounding boxes
        if x1y1x2y2:  # x1, y1, x2, y2 = box1
            b1_x1, b1_y1, b1_x2, b1_y2 = box1[0], box1[1], box1[2], box1[3]
            b2_x1, b2_y1, b2_x2, b2_y2 = box2[0], box2[1], box2[2], box2[3]
        else:  # transform from xywh to xyxy
            b1_x1, b1_x2 = box1[0] - box1[2] / 2, box1[0]   box1[2] / 2
            b1_y1, b1_y2 = box1[1] - box1[3] / 2, box1[1]   box1[3] / 2
            b2_x1, b2_x2 = box2[0] - box2[2] / 2, box2[0]   box2[2] / 2
            b2_y1, b2_y2 = box2[1] - box2[3] / 2, box2[1]   box2[3] / 2

        # Intersection area
        inter = (torch.min(b1_x2, b2_x2) - torch.max(b1_x1, b2_x1)).clamp(0) * \
                (torch.min(b1_y2, b2_y2) - torch.max(b1_y1, b2_y1)).clamp(0)

        # Union Area
        w1, h1 = b1_x2 - b1_x1, b1_y2 - b1_y1   eps
        w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1   eps
        union = w1 * h1   w2 * h2 - inter   eps
        if scale:
            self = WIoU_Scale(1 - (inter / union))

        # IoU
        # iou = inter / union # ori iou
        iou = torch.pow(inter / (union   eps), alpha)  # alpha iou
        if CIoU or DIoU or GIoU or EIoU or SIoU or WIoU:
            cw = b1_x2.maximum(b2_x2) - b1_x1.minimum(b2_x1)  # convex (smallest enclosing box) width
            ch = b1_y2.maximum(b2_y2) - b1_y1.minimum(b2_y1)  # convex height
            if CIoU or DIoU or EIoU or SIoU or WIoU:  # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1
                c2 = (cw ** 2   ch ** 2) ** alpha   eps  # convex diagonal squared
                rho2 = (((b2_x1   b2_x2 - b1_x1 - b1_x2) ** 2   (
                            b2_y1   b2_y2 - b1_y1 - b1_y2) ** 2) / 4) ** alpha  # center dist ** 2
                if CIoU:  # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47
                    v = (4 / math.pi ** 2) * (torch.atan(w2 / h2) - torch.atan(w1 / h1)).pow(2)
                    with torch.no_grad():
                        alpha_ciou = v / (v - iou   (1   eps))
                    if Focal:
                        return iou - (rho2 / c2   torch.pow(v * alpha_ciou   eps, alpha)), torch.pow(
                            inter / (union   eps), gamma)  # Focal_CIoU
                    else:
                        return iou - (rho2 / c2   torch.pow(v * alpha_ciou   eps, alpha))  # CIoU
                elif EIoU:
                    rho_w2 = ((b2_x2 - b2_x1) - (b1_x2 - b1_x1)) ** 2
                    rho_h2 = ((b2_y2 - b2_y1) - (b1_y2 - b1_y1)) ** 2
                    cw2 = torch.pow(cw ** 2   eps, alpha)
                    ch2 = torch.pow(ch ** 2   eps, alpha)
                    if Focal:
                        return iou - (rho2 / c2   rho_w2 / cw2   rho_h2 / ch2), torch.pow(inter / (union   eps),
                                                                                          gamma)  # Focal_EIou
                    else:
                        return iou - (rho2 / c2   rho_w2 / cw2   rho_h2 / ch2)  # EIou
                elif SIoU:
                    # SIoU Loss https://arxiv.org/pdf/2205.12740.pdf
                    s_cw = (b2_x1   b2_x2 - b1_x1 - b1_x2) * 0.5   eps
                    s_ch = (b2_y1   b2_y2 - b1_y1 - b1_y2) * 0.5   eps
                    sigma = torch.pow(s_cw ** 2   s_ch ** 2, 0.5)
                    sin_alpha_1 = torch.abs(s_cw) / sigma
                    sin_alpha_2 = torch.abs(s_ch) / sigma
                    threshold = pow(2, 0.5) / 2
                    sin_alpha = torch.where(sin_alpha_1 > threshold, sin_alpha_2, sin_alpha_1)
                    angle_cost = torch.cos(torch.arcsin(sin_alpha) * 2 - math.pi / 2)
                    rho_x = (s_cw / cw) ** 2
                    rho_y = (s_ch / ch) ** 2
                    gamma = angle_cost - 2
                    distance_cost = 2 - torch.exp(gamma * rho_x) - torch.exp(gamma * rho_y)
                    omiga_w = torch.abs(w1 - w2) / torch.max(w1, w2)
                    omiga_h = torch.abs(h1 - h2) / torch.max(h1, h2)
                    shape_cost = torch.pow(1 - torch.exp(-1 * omiga_w), 4)   torch.pow(1 - torch.exp(-1 * omiga_h), 4)
                    if Focal:
                        return iou - torch.pow(0.5 * (distance_cost   shape_cost)   eps, alpha), torch.pow(
                            inter / (union   eps), gamma)  # Focal_SIou
                    else:
                        return iou - torch.pow(0.5 * (distance_cost   shape_cost)   eps, alpha)  # SIou
                elif WIoU:
                    if Focal:
                        raise RuntimeError("WIoU do not support Focal.")
                    elif scale:
                        return getattr(WIoU_Scale, '_scaled_loss')(self), (1 - iou) * torch.exp(
                            (rho2 / c2)), iou  # WIoU https://arxiv.org/abs/2301.10051
                    else:
                        return iou, torch.exp((rho2 / c2))  # WIoU v1
                if Focal:
                    return iou - rho2 / c2, torch.pow(inter / (union   eps), gamma)  # Focal_DIoU
                else:
                    return iou - rho2 / c2  # DIoU
            c_area = cw * ch   eps  # convex area
            if Focal:
                return iou - torch.pow((c_area - union) / c_area   eps, alpha), torch.pow(inter / (union   eps),
                                                                                          gamma)  # Focal_GIoU 
            else:
                return iou - torch.pow((c_area - union) / c_area   eps,
                                       alpha)  # GIoU https://arxiv.org/pdf/1902.09630.pdf
        if Focal:
            return iou, torch.pow(inter / (union   eps), gamma)  # Focal_IoU
        else:
            return iou  # IoU

调用

iou = self.bbox_iou(box.T, selected_tbox, x1y1x2y2=False, WIoU=True,)
if type(iou) is tuple:
	if len(iou) == 2:
		box_loss  = (iou[1].detach() * (1 - iou[0])).mean()
        iou = iou[0]
	 else:
     	box_loss  = (iou[0] * iou[1]).mean()
     	iou = iou[-1]
else:
	box_loss  = (1.0 - iou).mean()  # iou loss

总结

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhghekhc
系列文章
更多 icon
同类精品
更多 icon
继续加载