定位:pcdet/models/dense_heads/target_assigner/axis_aligned_target_assigner.py
# IOU 计算
if len(gt_boxes) > 0 and anchors.shape[0] > 0:
anchor_by_gt_overlap = iou3d_nms_utils.boxes_iou3d_gpu(anchors[:, 0:7], gt_boxes[:, 0:7]) \
if self.match_height else box_utils.boxes3d_nearest_bev_iou(anchors[:, 0:7], gt_boxes[:, 0:7])
# (cx, cy, cz) 为物体3D框的几何中心位置,(dx, dy, dz)分别为物体3D框在heading角度为0时沿着x-y-z三个方向的长度,heading为物体在俯视图下的朝向角
anchors[:, 0:7] #(cx, cy, cz, dx, dy, dz, heading)
gt_boxes[:, 0:7]
tensor([[ 0.0000, -39.6800, 0.2650, ..., 0.6000, 1.7300, 0.0000],
[ 0.0000, -39.6800, 0.2650, ..., 0.6000, 1.7300, 1.5700],
[ 0.3215, -39.6800, 0.2650, ..., 0.6000, 1.7300, 0.0000],
...,
[ 68.7985, 39.6800, 0.2650, ..., 0.6000, 1.7300, 1.5700],
[ 69.1200, 39.6800, 0.2650, ..., 0.6000, 1.7300, 0.0000],
[ 69.1200, 39.6800, 0.2650, ..., 0.6000, 1.7300, 1.5700]],
device='cuda:0')
tensor([[ 5.7474, -2.8168, -0.7688, 0.7971, 0.4994, 1.6710, 1.7641],
[ 7.4414, -1.6039, -0.6621, 0.9123, 0.6050, 1.8727, 2.8541],
[ 10.8724, 0.4536, -0.6721, 0.9988, 0.4033, 1.8247, 1.5041],
[ 10.9733, -8.8892, -0.6260, 1.0852, 0.8451, 1.8151, 1.9441],
[ 4.6155, -5.4593, -0.7389, 0.7299, 0.6242, 1.7190, 1.6041],
[ 16.6888, -11.4180, -0.7195, 0.8355, 0.6434, 1.5173, -0.6459],
[ 7.5312, -4.4219, -0.7520, 1.0756, 0.4802, 1.6614, -2.0691],
[ 9.3284, -12.7250, -0.6318, 1.1140, 0.5282, 1.7862, -1.9059],
[ 24.1482, -16.5193, -0.5080, 0.9411, 0.6530, 1.7766, -1.6359],
[ 10.7779, -14.6549, -0.6205, 1.0756, 0.7491, 1.7670, 2.0641],
[ 10.7733, -2.6072, -0.8293, 0.4898, 0.7011, 1.4789, 2.9741],
[ 37.1105, 1.8952, -0.5361, 0.1921, 0.4129, 1.7286, -2.4791]],
device='cuda:0')
torch.Size([107136, 7]) # 固定107136个anchor,2种角度:0°、90°
torch.Size([12, 7]) # 这个batch=3有12个anchor,不是固定的
产生的anchor,解释107136,backbone之后的feature map是[batch_size,6C, H/2=248, W/2=216]
,每个位置产生2种角度(0°、90°)的anchor,248 x 216 x 2 = 107136
。
产生的anchor分析(预测3类)
仅仅看90°的anchor
print(anchors[1, 0:7])
print(anchors[3, 0:7])
print(anchors[5, 0:7])
print(anchors[431, 0:7])
print(anchors[433, 0:7])
print(anchors[435, 0:7])
print(anchors[437, 0:7])
print(anchors[863, 0:7])
tensor([ 0.0000, -39.6800, -1.0000, 3.9000, 1.6000, 1.5600, 1.5700], device='cuda:0')
tensor([ 0.3215, -39.6800, -1.0000, 3.9000, 1.6000, 1.5600, 1.5700], device='cuda:0')
tensor([ 0.6430, -39.6800, -1.0000, 3.9000, 1.6000, 1.5600, 1.5700], device='cuda:0')
tensor([ 69.1200, -39.6800, -1.0000, 3.9000, 1.6000, 1.5600, 1.5700], device='cuda:0')
tensor([ 0.0000, -39.3587, -1.0000, 3.9000, 1.6000, 1.5600, 1.5700], device='cuda:0')
tensor([ 0.3215, -39.3587, -1.0000, 3.9000, 1.6000, 1.5600, 1.5700], device='cuda:0')
tensor([ 0.6430, -39.3587, -1.0000, 3.9000, 1.6000, 1.5600, 1.5700], device='cuda:0')
tensor([ 69.1200, -39.3587, -1.0000, 3.9000, 1.6000, 1.5600, 1.5700], device='cuda:0')
1、3、5、431行只有x移动,每次移动0.3215
,怎么来的呢,69.12/216=0.32
。(3.9, 1.6, 1.56)
是Car
的尺寸。
433、435、437行和上面x移动一样距离,同时y也移动了0.3213,这又是怎么来的呢,(39.68x2)/248=0.32
。
来看看Pedestrian
的尺寸,和上面非常类似,仅仅尺寸改变。
tensor([ 0.0000, -39.6800, 0.2650, 0.8000, 0.6000, 1.7300, 1.5700], device='cuda:0')
tensor([ 0.3215, -39.6800, 0.2650, 0.8000, 0.6000, 1.7300, 1.5700], device='cuda:0')
tensor([ 0.6430, -39.6800, 0.2650, 0.8000, 0.6000, 1.7300, 1.5700], device='cuda:0')
tensor([ 69.1200, -39.6800, 0.2650, 0.8000, 0.6000, 1.7300, 1.5700], device='cuda:0')
tensor([ 0.0000, -39.3587, 0.2650, 0.8000, 0.6000, 1.7300, 1.5700], device='cuda:0')
tensor([ 0.3215, -39.3587, 0.2650, 0.8000, 0.6000, 1.7300, 1.5700], device='cuda:0')
tensor([ 0.6430, -39.3587, 0.2650, 0.8000, 0.6000, 1.7300, 1.5700], device='cuda:0')
tensor([ 69.1200, -39.3587, 0.2650, 0.8000, 0.6000, 1.7300, 1.5700], device='cuda:0')
同理,Cyclist
tensor([ 0.0000, -39.6800, 0.2650, 1.7600, 0.6000, 1.7300, 1.5700], device='cuda:0')
tensor([ 0.3215, -39.6800, 0.2650, 1.7600, 0.6000, 1.7300, 1.5700], device='cuda:0')
tensor([ 0.6430, -39.6800, 0.2650, 1.7600, 0.6000, 1.7300, 1.5700], device='cuda:0')
tensor([ 69.1200, -39.6800, 0.2650, 1.7600, 0.6000, 1.7300, 1.5700], device='cuda:0')
tensor([ 0.0000, -39.3587, 0.2650, 1.7600, 0.6000, 1.7300, 1.5700], device='cuda:0')
tensor([ 0.3215, -39.3587, 0.2650, 1.7600, 0.6000, 1.7300, 1.5700], device='cuda:0')
tensor([ 0.6430, -39.3587, 0.2650, 1.7600, 0.6000, 1.7300, 1.5700], device='cuda:0')
tensor([ 69.1200, -39.3587, 0.2650, 1.7600, 0.6000, 1.7300, 1.5700], device='cuda:0')
然后就是计算IOU了,用的是标准2D IOU计算方法。返回[107136, num_gt_box]
# 标准/普通 2D IOU 计算
def boxes_iou_normal(boxes_a, boxes_b):
"""
Args:
boxes_a: (N, 4) [x1, y1, x2, y2] [x_min, y_min, x_max, y_max]
boxes_b: (M, 4) [x1, y1, x2, y2]
Returns:
"""
assert boxes_a.shape[1] == boxes_b.shape[1] == 4
x_min = torch.max(boxes_a[:, 0, None], boxes_b[None, :, 0])
x_max = torch.min(boxes_a[:, 2, None], boxes_b[None, :, 2])
y_min = torch.max(boxes_a[:, 1, None], boxes_b[None, :, 1])
y_max = torch.min(boxes_a[:, 3, None], boxes_b[None, :, 3])
x_len = torch.clamp_min(x_max - x_min, min=0)
y_len = torch.clamp_min(y_max - y_min, min=0)
area_a = (boxes_a[:, 2] - boxes_a[:, 0]) * (boxes_a[:, 3] - boxes_a[:, 1])
area_b = (boxes_b[:, 2] - boxes_b[:, 0]) * (boxes_b[:, 3] - boxes_b[:, 1])
a_intersect_b = x_len * y_len # 交
iou = a_intersect_b / torch.clamp_min(area_a[:, None] + area_b[None, :] - a_intersect_b, min=1e-6)
return iou