您现在的位置是:首页 >技术交流 >使用chatGPT写的IoU及IoU变体的代码实现网站首页技术交流
使用chatGPT写的IoU及IoU变体的代码实现
简介使用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 有许多变体和扩展,常用的包括以下几种:
- Generalized IoU (GIoU):在计算 IoU 时,我们只考虑了两个边界框的重叠面积。而 GIoU 进一步考虑了两个边界框的外部区域(即不重叠的区域),并计算它们的面积,用于惩罚边界框的偏移和尺度差异。GIoU 是一种比 IoU 更准确的重叠度量。
- Distance IoU (DIoU):DIoU 在 GIoU 的基础上,又增加了对边界框中心点距离的惩罚,以进一步提高精度。DIoU 的计算公式包含了重叠区域的面积、最小闭包矩形(MBR)的面积、两个边界框中心点距离以及它们的尺度差异。
- Complete IoU (CIoU):CIoU 在 DIoU 的基础上,又增加了对边界框长宽比例的惩罚,以进一步提高精度。CIoU 的计算公式包含了 DIoU 的所有参数,并增加了一个关于长宽比例的惩罚项。
- Efficient IoU (EIoU):EIoU 与 GIoU、DIoU 和 CIoU 不同之处在于,它采用最小闭包矩形的对角线长度来代替 MBR 的面积,以降低计算成本。
这些变体都是用于计算两个边界框的重叠度量,目的是为了提高目标检测等任务的精度。在实际应用中,我们可以根据任务的需要选择适当的重叠度量。
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。