这个函数 probiou 是用于计算定向边界框之间的概率交并比是yolov8-obb计算损失时的核心代码,其可以缓解边界不连续的问题
原论文 “https://arxiv.org/pdf/2106.06072v1.pdf”。
该函数接受两个定向边界框作为输入,分别为真实的边界框和预测的边界框,然后计算它们之间的相似度。
def probiou(obb1, obb2, CIoU=False, eps=1e-7):
# 定义函数probiou,计算两个OBB之间的ProbIoU。
#obb1和obb2是输入的OBBs
x1, y1 = obb1[..., :2].split(1, dim=-1)
x2, y2 = obb2[..., :2].split(1, dim=-1)
# 分割输入的OBBs,提取中心坐标x,y。
#obb1和obb2的形状应为(N, 5),其中包含中心坐标、宽高和旋转角度。
a1, b1, c1 = _get_covariance_matrix(obb1)
a2, b2, c2 = _get_covariance_matrix(obb2)
# 调用_get_covariance_matrix函数计算每个OBB的协方差矩阵元素(a, b, c)。
t1 = (
((a1 + a2) * (torch.pow(y1 - y2, 2)) + (b1 + b2) * (torch.pow(x1 - x2, 2)))
/ ((a1 + a2) * (b1 + b2) - (torch.pow(c1 + c2, 2)) + eps)
) * 0.25
# 计算Bhattacharyya距离的第一部分t1,这部分涉及到OBBs中心点的差异。
t2 = (((c1 + c2) * (x2 - x1) * (y1 - y2)) / ((a1 + a2) * (b1 + b2) - (torch.pow(c1 + c2, 2)) + eps)) * 0.5
# 计算Bhattacharyya距离的第二部分t2,这部分考虑了OBBs的协方差。
t3 = (
torch.log(
((a1 + a2) * (b1 + b2) - (torch.pow(c1 + c2, 2)))
/ (4 * torch.sqrt((a1 * b1 - torch.pow(c1, 2)).clamp_(0) * (a2 * b2 - torch.pow(c2, 2)).clamp_(0)) + eps)
+ eps
)
* 0.5
)
# 计算Bhattacharyya距离的第三部分t3,涉及到协方差矩阵的行列式和它们的对数。
bd = t1 + t2 + t3
bd = torch.clamp(bd, eps, 100.0)
# 计算最终的Bhattacharyya距离bd,通过clamp函数限制bd的范围以避免潜在的数值问题。
hd = torch.sqrt(1.0 - torch.exp(-bd) + eps)
# 根据Bhattacharyya距离计算Hellinger距离hd。
iou = 1 - hd
# 通过1减去Hellinger距离计算概率IoU。
if CIoU: # only include the wh aspect ratio part
w1, h1 = obb1[..., 2:4].split(1, dim=-1)
w2, h2 = obb2[..., 2:4].split(1, dim=-1)
# 如果计算CIoU,额外提取宽和高用于计算长宽比的影响。
v = (4 / math.pi**2) * (torch.atan(w2 / h2) - torch.atan(w1 / h1)).pow(2)
# 计算长宽比的一致性项v。
with torch.no_grad():
alpha = v / (v - iou + (1 + eps))
# 计算长宽比一致性项的权重alpha。
return iou - v * alpha # CIoU
# 返回考虑长宽比影响的完整IoU(CIoU)。
return iou
# 如果不计算CIoU,直接返回概率IoU。