GBB (Gaussian Bounding Box)
GBB,全称高斯边界框 (Gaussian Bounding Box),是一种用二维高斯分布来表示边界框的方法。传统的边界框(无论是水平的 HBB 还是旋转的 OBB)通常用几个离散的参数来定义(例如中心点、宽高、角度)。而 GBB 则将边界框看作是一个概率分布,具体来说,是一个二维高斯(正态)分布。
二维高斯分布参数定义
均值向量 (Mean Vector)
一个二维向量 ,表示高斯分布的中心,通常对应于目标对象的中心点
。数学形式为:
协方差矩阵 (Covariance Matrix)
一个 的对称半正定矩阵,描述数据点围绕均值的分布形状和方向。其形式为:
其中:
-
对角线元素
:分别表示
和
方向上的方差。
-
非对角线元素
(等于
):表示
和
之间的协方差,反映分布的倾斜程度或方向。
公式说明
均值向量:
协方差矩阵:
OBB转换为GBB
OBB 到 GBB 的转换过程
OBB 参数定义
有向包围盒(Oriented Bounding Box, OBB)由以下参数描述:
-
中心点:
-
半长轴长度:
(沿主方向)
-
半宽轴长度:
(沿次方向)
-
旋转角度:
(主方向相对于
轴的逆时针角度)
GBB 参数定义
目标高斯分布参数(Gaussian Bounding Box, GBB)包括:
-
均值向量
-
协方差矩阵
(需从 OBB 推导)
转换步骤
均值向量确定
直接继承 OBB 的中心点:
-
协方差矩阵推导
协方差矩阵的几何意义与椭圆分布的主轴方向一致,推导步骤如下:
-
步骤 1:构造缩放矩阵
将 OBB 的半长轴和半宽轴
转换为椭圆的轴长标准差
:
(注:假设 OBB 覆盖 12σ 范围)缩放矩阵为:
步骤 2:构造旋转矩阵
根据 OBB 的旋转角度,定义旋转矩阵
:
-
步骤 3:计算协方差矩阵
协方差矩阵是旋转和缩放的组合:
展开计算:
步骤 4:简化结果
最终协方差矩阵的显式形式为:
-
公式总结
均值向量:
协方差矩阵:
注意事项
-
方向定义:旋转角度
是 OBB 主轴相对于
轴的逆时针角度。
- 3σ 假设:假设 OBB 的边长远大于高斯分布的 3σ 范围,实际应用中可根据需求调整系数。
-
对称性验证:最终协方差矩阵
必须是对称且半正定的。
ProbIoU
ProbIoU 是一种用于衡量两个概率性边界框(通常是高斯边界框 GBB)之间相似度或重叠程度的指标或损失函数。它与传统的 IoU (Intersection over Union) / GIoU / DIoU / CIoU 以及旋转框的 RIoU (Rotated IoU) 不同,因为它不是直接计算几何形状的交集和并集面积比,而是基于概率分布的度量。
为计算不同 GBB 间的相似度,本文首先采用了 Bhattacharyya Coefficient( )。两个概率密度函数
和
间的
按下列公式进行计算:
其中 ,当且仅当两个分布相同时,
。
基于上述 ,可以得到不同分布间的巴氏距离 (Bhattacharyya Distance,
)。两个概率密度函数
和
间的
按下列公式进行计算:
当 ,
且目标检测中实际问题为 2 维向量及矩阵时,巴氏距离
可通过如下公式进行计算:
参数定义:
由于 Bhattacharyya Distance 不满足三角不等式,因此它并不是严格定义的距离度量。为表示真实距离,本文采用 Hellinger Distance (HD),其公式如下:
其中 ,当且仅当两个分布相同时,
。
Probabilistic IoU (ProbIoU)
基于上述 Hellinger Distance,本文提出高斯分布相似性计算方法 ProbIoU,其具体计算公式如下:
特性说明:
-
,值越大表示分布相似性越高
- 当两分布完全相同时,
- 公式通过非线性映射将巴氏系数转换为更直观的相似性度量
计算OBB的ProbIoU
- python计算OBB的ProbIoU
def probiou(obb1, obb2, eps=1e-7):
# Calculate the prob iou between oriented bounding boxes, https://arxiv.org/pdf/2106.06072v1.pdf.
def covariance_matrix(obb):
# Extract elements
w, h, r = obb[2:5]
a = (w ** 2) / 12
b = (h ** 2) / 12
cos_r = torch.cos(torch.tensor(r))
sin_r = torch.sin(torch.tensor(r))
# Calculate covariance matrix elements
a_val = a * cos_r ** 2 + b * sin_r ** 2
b_val = a * sin_r ** 2 + b * cos_r ** 2
c_val = (a - b) * sin_r * cos_r
return a_val, b_val, c_val
a1, b1, c1 = covariance_matrix(obb1)
a2, b2, c2 = covariance_matrix(obb2)
x1, y1 = obb1[:2]
x2, y2 = obb2[:2]
t1 = ((a1 + a2) * ((y1 - y2) ** 2) + (b1 + b2) * ((x1 - x2) ** 2)) / ((a1 + a2) * (b1 + b2) - (c1 + c2) ** 2 + eps)
t2 = ((c1 + c2) * (x2 - x1) * (y1 - y2)) / ((a1 + a2) * (b1 + b2) - (c1 + c2) ** 2 + eps)
t3 = torch.log(((a1 + a2) * (b1 + b2) - (c1 + c2) ** 2) / (4 * torch.sqrt(a1 * b1 - c1 ** 2) * torch.sqrt(a2 * b2 - c2 ** 2) + eps) + eps)
bd = 0.25 * t1 + 0.5 * t2 + 0.5 * t3
hd = torch.sqrt(1.0 - torch.exp(-torch.clamp(bd, eps, 100.0)) + eps)
return 1 - hd
- cuda计算OBB的ProbIoU
static __device__ void convariance_matrix(float w, float h, float r, float& a, float& b, float& c){
float a_val = w * w / 12.0f;
float b_val = h * h / 12.0f;
float cos_r = cosf(r);
float sin_r = sinf(r);
a = a_val * cos_r * cos_r + b_val * sin_r * sin_r;
b = a_val * sin_r * sin_r + b_val * cos_r * cos_r;
c = (a_val - b_val) * sin_r * cos_r;
}
static __device__ float box_probiou(
float cx1, float cy1, float w1, float h1, float r1,
float cx2, float cy2, float w2, float h2, float r2,
float eps = 1e-7
){
// Calculate the prob iou between oriented bounding boxes, https://arxiv.org/pdf/2106.06072v1.pdf.
float a1, b1, c1, a2, b2, c2;
convariance_matrix(w1, h1, r1, a1, b1, c1);
convariance_matrix(w2, h2, r2, a2, b2, c2);
float t1 = ((a1 + a2) * powf(cy1 - cy2, 2) + (b1 + b2) * powf(cx1 - cx2, 2)) / ((a1 + a2) * (b1 + b2) - powf(c1 + c2, 2) + eps);
float t2 = ((c1 + c2) * (cx2 - cx1) * (cy1 - cy2)) / ((a1 + a2) * (b1 + b2) - powf(c1 + c2, 2) + eps);
float t3 = logf(((a1 + a2) * (b1 + b2) - powf(c1 + c2, 2)) / (4 * sqrtf(fmaxf(a1 * b1 - c1 * c1, 0.0f)) * sqrtf(fmaxf(a2 * b2 - c2 * c2, 0.0f)) + eps) + eps);
float bc = 0.25f * t1 + 0.5f * t2 + 0.5f * t3;
bc = fmaxf(fminf(bd, 100.0f), eps);
float hd = sqrtf(1.0f - expf(-bc) + eps);
return 1 - hd;
}