您现在的位置是:首页 >技术交流 >使用chatGPT写的IoU及IoU变体的代码实现网站首页技术交流

使用chatGPT写的IoU及IoU变体的代码实现

写进メ诗的结尾。 2024-06-05 12:00:02
简介使用chatGPT写的IoU及IoU变体的代码实现

IoU代码实现(Float类型)

def iou(boxA, boxB):
    # 确定交集区域的坐标
    xA = max(boxA[0], boxB[0])
    yA = max(boxA[1], boxB[1])
    xB = min(boxA[2], boxB[2])
    yB = min(boxA[3], boxB[3])
 
    # 计算交集区域面积
    interArea = max(0, xB - xA + 1) * max(0, yB - yA + 1)
 
    # 计算两个边界框面积
    boxAArea = (boxA[2] - boxA[0] + 1) * (boxA[3] - boxA[1] + 1)
    boxBArea = (boxB[2] - boxB[0] + 1) * (boxB[3] - boxB[1] + 1)
 
    # 计算并集区域面积
    unionArea = boxAArea + boxBArea - interArea
 
    # 计算交并比
    iou = interArea / float(unionArea)
 
    # 返回交并比
    return iou

'''
此代码期望输入两个包含四个元素的列表boxA和boxB,表示两个边界框的左上角和右下角坐标。代码将计算两个边界框的交集区域面积和并集区域面积,并将其用于计算交并比。该函数将返回一个0到1之间的浮点数,表示交并比的值,越接近1表示两个边界框越相似。
'''

IoU代码实现——不同维度(torch.Tensor类型)

def bbox_iou(box1, box2):
    """
    计算两个边界框的交并比

    参数:
    box1(tensor[N, 4]): 包含N个边界框的张量,每个边界框由左上角和右下角坐标表示
    box2(tensor[M, 4]): 包含M个边界框的张量,每个边界框由左上角和右下角坐标表示

    返回:
    tensor[N, M]: 包含所有边界框对的IoU值
    """
    # 计算box1和box2中所有边界框的面积
    box1_area = (box1[:, 2] - box1[:, 0]) * (box1[:, 3] - box1[:, 1])
    box2_area = (box2[:, 2] - box2[:, 0]) * (box2[:, 3] - box2[:, 1])

    # 扩展维度以便进行广播运算
    box1 = box1.unsqueeze(1)
    box2 = box2.unsqueeze(0)

    # 确定交集区域的坐标
    x1 = torch.max(box1[:, :, 0], box2[:, :, 0])
    y1 = torch.max(box1[:, :, 1], box2[:, :, 1])
    x2 = torch.min(box1[:, :, 2], box2[:, :, 2])
    y2 = torch.min(box1[:, :, 3], box2[:, :, 3])

    # 计算交集区域面积
    intersection_area = torch.clamp(x2 - x1, min=0) * torch.clamp(y2 - y1, min=0)

    # 计算并集区域面积
    union_area = box1_area.unsqueeze(1) + box2_area.unsqueeze(0) - intersection_area

    # 计算交并比
    iou = intersection_area / union_area

    return iou

'''
这个函数期望两个张量box1和box2,每个张量都包含N个或M个边界框。每个边界框由4个元素组成,表示左上角和右下角坐标。该函数计算每对边界框的IoU,并返回一个大小为[N,M]的张量,其中包含每对边界框的IoU值。使用PyTorch的张量运算可以快速有效地计算大量边界框之间的IoU。
'''

IoU代码实现——相同维度(torch.Tensor类型)

def bbox_iou(box1, box2):
    """
    计算两个边界框的交并比

    参数:
    box1(tensor[N, 4]): 包含N个边界框的张量,每个边界框由左上角和右下角坐标表示
    box2(tensor[N, 4]): 包含N个边界框的张量,每个边界框由左上角和右下角坐标表示

    返回:
    tensor[N]: 包含所有边界框对的IoU值
    """
    # 计算box1和box2中所有边界框的面积
    box1_area = (box1[:, 2] - box1[:, 0]) * (box1[:, 3] - box1[:, 1])
    box2_area = (box2[:, 2] - box2[:, 0]) * (box2[:, 3] - box2[:, 1])

    # 确定交集区域的坐标
    x1 = torch.max(box1[:, 0], box2[:, 0])
    y1 = torch.max(box1[:, 1], box2[:, 1])
    x2 = torch.min(box1[:, 2], box2[:, 2])
    y2 = torch.min(box1[:, 3], box2[:, 3])

    # 计算交集区域面积
    intersection_area = torch.clamp(x2 - x1, min=0) * torch.clamp(y2 - y1, min=0)

    # 计算并集区域面积
    union_area = box1_area + box2_area - intersection_area

    # 计算交并比
    iou = intersection_area / union_area

    return iou


def iou_loss(pred_boxes, target_boxes):
    """
    计算IoU损失

    参数:
    pred_boxes(tensor[N, 4]): 预测边界框的张量,每个边界框由左上角和右下角坐标表示
    target_boxes(tensor[N, 4]): 目标边界框的张量,每个边界框由左上角和右下角坐标表示

    返回:
    tensor: IoU损失值
    """
    iou = bbox_iou(pred_boxes, target_boxes)
    loss = 1 - iou.mean()

    return loss

'''
这个代码与上面的代码非常相似,只有一个显著的区别,即bbox_iou()函数中的维度变化。由于两个输入张量的维度相同,因此我们不需要进行扩展和广播,可以直接进行逐元素计算。此外,这个代码与上面的代码的计算方式是相同的,只是它计算的是一维张量的IoU而不是二维张量的IoU。
'''

GIoU代码实现(Float类型)

def bbox_giou(box1, box2):
    """
    计算两个边框的广义交并比(GIoU)

    参数:
    box1: 第一个边界框,由左上角和右下角坐标表示
    box2: 第二个边界框,由左上角和右下角坐标表示

    返回:
    float: GIoU值
    """
    # 计算box1和box2的面积
    box1_area = (box1[2] - box1[0]) * (box1[3] - box1[1])
    box2_area = (box2[2] - box2[0]) * (box2[3] - box2[1])

    # 确定交集区域的坐标
    x1 = max(box1[0], box2[0])
    y1 = max(box1[1], box2[1])
    x2 = min(box1[2], box2[2])
    y2 = min(box1[3], box2[3])

    # 计算交集区域面积
    intersection_area = max(0, x2 - x1) * max(0, y2 - y1)

    # 计算并集区域面积
    union_area = box1_area + box2_area - intersection_area

    # 计算box1和box2的最小外接矩形(MBR)
    MBR_x1 = min(box1[0], box2[0])
    MBR_y1 = min(box1[1], box2[1])
    MBR_x2 = max(box1[2], box2[2])
    MBR_y2 = max(box1[3], box2[3])

    # 计算最小外接矩形的面积
    MBR_area = (MBR_x2 - MBR_x1) * (MBR_y2 - MBR_y1)

    # 计算GIoU
    iou = intersection_area / union_area if union_area != 0 else 0
    c_x1 = min(box1[0], box2[0])
    c_y1 = min(box1[1], box2[1])
    c_x2 = max(box1[2], box2[2])
    c_y2 = max(box1[3], box2[3])
    c_area = (c_x2 - c_x1) * (c_y2 - c_y1)
    giou = iou - (MBR_area - union_area) / max(MBR_area, 1e-16)

    return giou

'''
这段代码的bbox_giou函数接受两个边界框box1和box2,每个边界框由左上角和右下角坐标表示。它返回这两个边框的GIoU值。GIoU值的计算基于以下公式,其中epsilon是一个极小的正数,以避免除数为零:
intersection_area / union_area - (MBR_area - union_area) / max(MBR_area, epsilon)
'''

GIoU代码实现(torch.Tensor类型)

import torch

def bbox_giou(box1, box2):
    """
    计算两个边界框的广义交并比(GIoU)

    参数:
    box1(tensor[N, 4]): 包含N个边界框的张量,每个边界框由左上角和右下角坐标表示
    box2(tensor[N, 4]): 包含N个边界框的张量,每个边界框由左上角和右下角坐标表示

    返回:
    tensor[N]: 包含所有边界框对的GIoU值
    """
    # 计算box1和box2中所有边界框的面积
    box1_area = (box1[:, 2] - box1[:, 0]) * (box1[:, 3] - box1[:, 1])
    box2_area = (box2[:, 2] - box2[:, 0]) * (box2[:, 3] - box2[:, 1])

    # 确定交集区域的坐标
    x1 = torch.max(box1[:, 0], box2[:, 0])
    y1 = torch.max(box1[:, 1], box2[:, 1])
    x2 = torch.min(box1[:, 2], box2[:, 2])
    y2 = torch.min(box1[:, 3], box2[:, 3])

    # 计算交集区域面积
    intersection_area = torch.clamp(x2 - x1, min=0) * torch.clamp(y2 - y1, min=0)

    # 计算并集区域面积
    union_area = box1_area + box2_area - intersection_area

    # 计算box1和box2的最小外接矩形(MBR)
    MBR_x1 = torch.min(box1[:, 0], box2[:, 0])
    MBR_y1 = torch.min(box1[:, 1], box2[:, 1])
    MBR_x2 = torch.max(box1[:, 2], box2[:, 2])
    MBR_y2 = torch.max(box1[:, 3], box2[:, 3])

    # 计算最小外接矩形的面积
    MBR_area = (MBR_x2 - MBR_x1) * (MBR_y2 - MBR_y1)

    # 计算GIoU
    iou = intersection_area / union_area
    c_x1 = torch.min(box1[:, 0], box2[:, 0])
    c_y1 = torch.min(box1[:, 1], box2[:, 1])
    c_x2 = torch.max(box1[:, 2], box2[:, 2])
    c_y2 = torch.max(box1[:, 3], box2[:, 3])
    c_area = (c_x2 - c_x1) * (c_y2 - c_y1)
    giou = iou - (MBR_area - union_area) / MBR_area.clamp(min=1e-16)

    return giou

DIoU代码实现(Float类型)

def bbox_diou(box1, box2):
    """
    计算两个边框的距离交并比(DIoU)

    参数:
    box1(list[float]): 第一个边界框,由左上角和右下角坐标表示
    box2(list[float]): 第二个边界框,由左上角和右下角坐标表示

    返回:
    float: DIoU值
    """
    # 计算box1和box2的中心点坐标
    x1_center, y1_center = (box1[2] + box1[0]) / 2, (box1[3] + box1[1]) / 2
    x2_center, y2_center = (box2[2] + box2[0]) / 2, (box2[3] + box2[1]) / 2

    # 计算box1和box2的面积
    box1_area = (box1[2] - box1[0]) * (box1[3] - box1[1])
    box2_area = (box2[2] - box2[0]) * (box2[3] - box2[1])

    # 确定交集区域的坐标
    x1, y1, x2, y2 = max(box1[0], box2[0]), max(box1[1], box2[1]), 
                     min(box1[2], box2[2]), min(box1[3], box2[3])

    # 计算交集区域面积和并集区域面积
    intersection_area = max(x2 - x1, 0) * max(y2 - y1, 0)
    union_area = box1_area + box2_area - intersection_area

    # 计算box1和box2的最小外接矩形(MBR)
    MBR_x1, MBR_y1 = min(box1[0], box2[0]), min(box1[1], box2[1])
    MBR_x2, MBR_y2 = max(box1[2], box2[2]), max(box1[3], box2[3])

    # 计算最小外接矩形的面积
    MBR_area = max(MBR_x2 - MBR_x1, 0) * max(MBR_y2 - MBR_y1, 0)

    # 计算距离函数的参数
    center_distance = (x1_center - x2_center) ** 2 + (y1_center - y2_center) ** 2
    diagonal_length = center_distance + max(MBR_x1 - MBR_x2, 0) ** 2 + max(MBR_y1 - MBR_y2, 0) ** 2

    # 计算DIoU
    iou = intersection_area / union_area if union_area != 0 else 0
    diou = iou - center_distance / diagonal_length

    return diou

DIoU代码实现(torch.Tensor类型)

import torch

def bbox_diou(box1, box2):
    """
    计算两个边框的距离交并比(DIoU)
    
    参数:
    box1(torch.Tensor): 第一个边界框,由左上角和右下角坐标表示,形状为[N, 4]
    box2(torch.Tensor): 第二个边界框,由左上角和右下角坐标表示,形状为[N, 4]
    
    返回:
    torch.Tensor: DIoU值,形状为[N,]
    """
    # 计算box1和box2的中心点坐标
    x1_center, y1_center = (box1[:, 2] + box1[:, 0]) / 2, (box1[:, 3] + box1[:, 1]) / 2
    x2_center, y2_center = (box2[:, 2] + box2[:, 0]) / 2, (box2[:, 3] + box2[:, 1]) / 2
    
    # 计算box1和box2的面积
    box1_area = (box1[:, 2] - box1[:, 0]) * (box1[:, 3] - box1[:, 1])
    box2_area = (box2[:, 2] - box2[:, 0]) * (box2[:, 3] - box2[:, 1])
    
    # 确定交集区域的坐标
    x1, y1 = torch.max(box1[:, 0], box2[:, 0]), torch.max(box1[:, 1], box2[:, 1])
    x2, y2 = torch.min(box1[:, 2], box2[:, 2]), torch.min(box1[:, 3], box2[:, 3])
    
    # 计算交集区域面积和并集区域面积
    intersection_area = torch.clamp(x2 - x1, min=0) * torch.clamp(y2 - y1, min=0)
    union_area = box1_area + box2_area - intersection_area
    
    # 计算box1和box2的最小外接矩形(MBR
    MBR_x1, MBR_y1 = torch.min(box1[:, 0], box2[:, 0]), torch.min(box1[:, 1], box2[:, 1])
    MBR_x2, MBR_y2 = torch.max(box1[:, 2], box2[:, 2]), torch.max(box1[:, 3], box2[:, 3])
    
    # 计算最小外接矩形的面积
    MBR_area = torch.clamp(MBR_x2 - MBR_x1, min=0) * torch.clamp(MBR_y2 - MBR_y1, min=0)
    
    # 计算距离函数的参数
    center_distance = (x1_center - x2_center) ** 2 + (y1_center - y2_center) ** 2
    diagonal_length = center_distance + torch.max(MBR_x1 - MBR_x2, torch.zeros_like(MBR_x1)) ** 2 + 
                      torch.max(MBR_y1 - MBR_y2, torch.zeros_like(MBR_y1)) ** 2
    
    return 1.0 - intersection_area / union_area + diagonal_length / MBR_area

CIoU代码实现(Float类型)

import math

def bbox_ciou(box1, box2):
    """
    计算两个边框的完备交并比(CIoU)
    参数:
    box1(tuple or list): 第一个边界框,由左上角和右下角坐标表示,形状为(4,)
    box2(tuple or list): 第二个边界框,由左上角和右下角坐标表示,形状为(4,)
    返回:
    float: CIoU值
    """
    # 将输入的边框转换为中心坐标和宽高
    x1, y1, x2, y2 = box1
    w1, h1 = x2 - x1, y2 - y1
    x1_center, y1_center = x1 + w1 / 2, y1 + h1 / 2
    x2, y2, x3, y3 = box2
    w2, h2 = x3 - x2, y3 - y2
    x2_center, y2_center = x2 + w2 / 2, y2 + h2 / 2

    # 计算两个边框的 IoU 值以及最小闭包矩形(Minimum Bounding Rectangle,MBR)的面积
    overlap_area = max(0, min(x1 + w1, x2 + w2) - max(x1, x2)) * max(0, min(y1 + h1, y2 + h2) - max(y1, y2))
    box1_area, box2_area = w1 * h1, w2 * h2
    union_area = box1_area + box2_area - overlap_area
    iou = overlap_area / union_area

    # 计算两个边框的中心距离
    center_distance = math.sqrt((x1_center - x2_center) ** 2 + (y1_center - y2_center) ** 2)

    # 计算对角线长度和宽高比惩罚系数
    w_intersect, h_intersect = max(0, min(x1 + w1, x2 + w2) - max(x1, x2)), max(0, min(y1 + h1, y2 + h2) - max(y1, y2))
    if w_intersect == 0 or h_intersect == 0:
        v = 0
    else:
        v = ((w2 - w1) ** 2 + (h2 - h1) ** 2) / (w_intersect ** 2 + h_intersect ** 2)

    # 计算 CIoU 值
    alpha = v / (1 - iou + v)
    ciou = iou - center_distance ** 2 / (union_area - overlap_area) - alpha * v
    
    return ciou

EIoU代码实现(Float类型)

import math

def bbox_eiou(box1, box2):
    """
    计算两个边框的 Efficient IoU (EIoU)
    参数:
    box1(tuple or list): 第一个边界框,由左上角和右下角坐标表示,形状为(4,)
    box2(tuple or list): 第二个边界框,由左上角和右下角坐标表示,形状为(4,)
    返回:
    float: EIoU 值
    """
    # 将输入的边框转换为中心坐标和宽高
    x1, y1, x2, y2 = box1
    w1, h1 = x2 - x1, y2 - y1
    x1_center, y1_center = x1 + w1 / 2, y1 + h1 / 2
    x2, y2, x3, y3 = box2
    w2, h2 = x3 - x2, y3 - y2
    x2_center, y2_center = x2 + w2 / 2, y2 + h2 / 2

    # 计算两个边框的 IoU 值以及最小闭包矩形(Minimum Bounding Rectangle,MBR)的面积
    overlap_area = max(0, min(x1 + w1, x2 + w2) - max(x1, x2)) * max(0, min(y1 + h1, y2 + h2) - max(y1, y2))
    box1_area, box2_area = w1 * h1, w2 * h2
    union_area = box1_area + box2_area - overlap_area
    iou = overlap_area / union_area

    # 计算两个边框的中心距离
    center_distance = math.sqrt((x1_center - x2_center) ** 2 + (y1_center - y2_center) ** 2)

    # 计算最小闭包矩形的对角线长度
    w_mbr, h_mbr = max(x1 + w1, x2 + w2) - min(x1, x2), max(y1 + h1, y2 + h2) - min(y1, y2)
    d_mbr = math.sqrt(w_mbr ** 2 + h_mbr ** 2)

    # 计算 EIoU 值
    eiou = iou - center_distance ** 2 / (d_mbr ** 2 + 1e-6)
    
    return eiou

Intersection over Union(IoU)是计算两个边界框的重叠程度的常用指标。在实际应用中,IoU 有许多变体和扩展,常用的包括以下几种:

  1. Generalized IoU (GIoU):在计算 IoU 时,我们只考虑了两个边界框的重叠面积。而 GIoU 进一步考虑了两个边界框的外部区域(即不重叠的区域),并计算它们的面积,用于惩罚边界框的偏移和尺度差异。GIoU 是一种比 IoU 更准确的重叠度量。
  2. Distance IoU (DIoU):DIoU 在 GIoU 的基础上,又增加了对边界框中心点距离的惩罚,以进一步提高精度。DIoU 的计算公式包含了重叠区域的面积、最小闭包矩形(MBR)的面积、两个边界框中心点距离以及它们的尺度差异。
  3. Complete IoU (CIoU):CIoU 在 DIoU 的基础上,又增加了对边界框长宽比例的惩罚,以进一步提高精度。CIoU 的计算公式包含了 DIoU 的所有参数,并增加了一个关于长宽比例的惩罚项。
  4. Efficient IoU (EIoU):EIoU 与 GIoU、DIoU 和 CIoU 不同之处在于,它采用最小闭包矩形的对角线长度来代替 MBR 的面积,以降低计算成本。

这些变体都是用于计算两个边界框的重叠度量,目的是为了提高目标检测等任务的精度。在实际应用中,我们可以根据任务的需要选择适当的重叠度量。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。