"vscode:/vscode.git/clone" did not exist on "6086874863402d2cbe2e2d2c1b4caec831007b98"
Commit 2eebdc2d authored by Yezhen Cong's avatar Yezhen Cong Committed by Tai-Wang
Browse files

[Refactor] Main code modification for coordinate system refactor (#677)

parent 26ab7ff2
......@@ -293,6 +293,7 @@ class AnchorTrainMixin(object):
sampling_result.pos_bboxes,
pos_bbox_targets,
self.dir_offset,
self.dir_limit_offset,
one_hot=False)
bbox_targets[pos_inds, :] = pos_bbox_targets
bbox_weights[pos_inds, :] = 1.0
......@@ -318,6 +319,7 @@ class AnchorTrainMixin(object):
def get_direction_target(anchors,
reg_targets,
dir_offset=0,
dir_limit_offset=0,
num_bins=2,
one_hot=True):
"""Encode direction to 0 ~ num_bins-1.
......@@ -333,7 +335,7 @@ def get_direction_target(anchors,
torch.Tensor: Encoded direction targets.
"""
rot_gt = reg_targets[..., 6] + anchors[..., 6]
offset_rot = limit_period(rot_gt - dir_offset, 0, 2 * np.pi)
offset_rot = limit_period(rot_gt - dir_offset, dir_limit_offset, 2 * np.pi)
dir_cls_targets = torch.floor(offset_rot / (2 * np.pi / num_bins)).long()
dir_cls_targets = torch.clamp(dir_cls_targets, min=0, max=num_bins - 1)
if one_hot:
......
......@@ -471,7 +471,7 @@ class VoteHead(BaseModule):
vote_target_masks = points.new_zeros([num_points],
dtype=torch.long)
vote_target_idx = points.new_zeros([num_points], dtype=torch.long)
box_indices_all = gt_bboxes_3d.points_in_boxes(points)
box_indices_all = gt_bboxes_3d.points_in_boxes_batch(points)
for i in range(gt_labels_3d.shape[0]):
box_indices = box_indices_all[:, i]
indices = torch.nonzero(
......@@ -621,7 +621,7 @@ class VoteHead(BaseModule):
box_dim=bbox.shape[-1],
with_yaw=self.bbox_coder.with_rot,
origin=(0.5, 0.5, 0.5))
box_indices = bbox.points_in_boxes(points)
box_indices = bbox.points_in_boxes_batch(points)
corner3d = bbox.corners
minmax_box3d = corner3d.new(torch.Size((corner3d.shape[0], 6)))
......
......@@ -502,7 +502,7 @@ class H3DBboxHead(BaseModule):
box_dim=bbox.shape[-1],
with_yaw=self.bbox_coder.with_rot,
origin=(0.5, 0.5, 0.5))
box_indices = bbox.points_in_boxes(points)
box_indices = bbox.points_in_boxes_batch(points)
corner3d = bbox.corners
minmax_box3d = corner3d.new(torch.Size((corner3d.shape[0], 6)))
......
......@@ -344,7 +344,7 @@ class PartA2BboxHead(BaseModule):
pred_boxes3d[..., 0:3] = rotation_3d_in_axis(
pred_boxes3d[..., 0:3].unsqueeze(1),
(pos_rois_rotation + np.pi / 2),
pos_rois_rotation,
axis=2).squeeze(1)
pred_boxes3d[:, 0:3] += roi_xyz
......@@ -436,8 +436,7 @@ class PartA2BboxHead(BaseModule):
pos_gt_bboxes_ct[..., 0:3] -= roi_center
pos_gt_bboxes_ct[..., 6] -= roi_ry
pos_gt_bboxes_ct[..., 0:3] = rotation_3d_in_axis(
pos_gt_bboxes_ct[..., 0:3].unsqueeze(1),
-(roi_ry + np.pi / 2),
pos_gt_bboxes_ct[..., 0:3].unsqueeze(1), -roi_ry,
axis=2).squeeze(1)
# flip orientation if rois have opposite orientation
......@@ -530,8 +529,7 @@ class PartA2BboxHead(BaseModule):
local_roi_boxes[..., 0:3] = 0
rcnn_boxes3d = self.bbox_coder.decode(local_roi_boxes, bbox_pred)
rcnn_boxes3d[..., 0:3] = rotation_3d_in_axis(
rcnn_boxes3d[..., 0:3].unsqueeze(1), (roi_ry + np.pi / 2),
axis=2).squeeze(1)
rcnn_boxes3d[..., 0:3].unsqueeze(1), roi_ry, axis=2).squeeze(1)
rcnn_boxes3d[:, 0:3] += roi_xyz
# post processing
......
......@@ -355,7 +355,7 @@ class PrimitiveHead(BaseModule):
# Generate pts_semantic_mask and pts_instance_mask when they are None
if pts_semantic_mask is None or pts_instance_mask is None:
points2box_mask = gt_bboxes_3d.points_in_boxes(points)
points2box_mask = gt_bboxes_3d.points_in_boxes_batch(points)
assignment = points2box_mask.argmax(1)
background_mask = points2box_mask.max(1)[0] == 0
......
......@@ -61,9 +61,9 @@ __device__ inline int check_in_box2d(const float *box, const Point &p) {
angle_sin =
sin(-box[4]); // rotate the point in the opposite direction of box
float rot_x =
(p.x - center_x) * angle_cos + (p.y - center_y) * angle_sin + center_x;
(p.x - center_x) * angle_cos - (p.y - center_y) * angle_sin + center_x;
float rot_y =
-(p.x - center_x) * angle_sin + (p.y - center_y) * angle_cos + center_y;
(p.x - center_x) * angle_sin + (p.y - center_y) * angle_cos + center_y;
#ifdef DEBUG
printf("box: (%.3f, %.3f, %.3f, %.3f, %.3f)\n", box[0], box[1], box[2],
box[3], box[4]);
......@@ -112,9 +112,9 @@ __device__ inline void rotate_around_center(const Point &center,
const float angle_cos,
const float angle_sin, Point &p) {
float new_x =
(p.x - center.x) * angle_cos + (p.y - center.y) * angle_sin + center.x;
(p.x - center.x) * angle_cos - (p.y - center.y) * angle_sin + center.x;
float new_y =
-(p.x - center.x) * angle_sin + (p.y - center.y) * angle_cos + center.y;
(p.x - center.x) * angle_sin + (p.y - center.y) * angle_cos + center.y;
p.set(new_x, new_y);
}
......
......@@ -7,17 +7,17 @@ def points_in_boxes_gpu(points, boxes):
"""Find points that are in boxes (CUDA)
Args:
points (torch.Tensor): [B, M, 3], [x, y, z] in LiDAR coordinate
points (torch.Tensor): [B, M, 3], [x, y, z] in LiDAR/DEPTH coordinate
boxes (torch.Tensor): [B, T, 7],
num_valid_boxes <= T, [x, y, z, w, l, h, ry] in LiDAR coordinate,
(x, y, z) is the bottom center
num_valid_boxes <= T, [x, y, z, dx, dy, dz, rz] in
LiDAR/DEPTH coordinate, (x, y, z) is the bottom center
Returns:
box_idxs_of_pts (torch.Tensor): (B, M), default background = -1
"""
assert boxes.shape[0] == points.shape[0], \
assert points.shape[0] == boxes.shape[0], \
f'Points and boxes should have the same batch size, ' \
f'got {boxes.shape[0]} and {boxes.shape[0]}'
f'got {points.shape[0]} and {boxes.shape[0]}'
assert boxes.shape[2] == 7, \
f'boxes dimension should be 7, ' \
f'got unexpected shape {boxes.shape[2]}'
......@@ -53,31 +53,35 @@ def points_in_boxes_gpu(points, boxes):
def points_in_boxes_cpu(points, boxes):
"""Find points that are in boxes (CPU)
Note:
Currently, the output of this function is different from that of
points_in_boxes_gpu.
Args:
points (torch.Tensor): [npoints, 3]
boxes (torch.Tensor): [N, 7], in LiDAR coordinate,
(x, y, z) is the bottom center
points (torch.Tensor): [B, M, 3], [x, y, z] in
LiDAR/DEPTH coordinate
boxes (torch.Tensor): [B, T, 7],
num_valid_boxes <= T, [x, y, z, dx, dy, dz, rz],
(x, y, z) is the bottom center.
Returns:
point_indices (torch.Tensor): (N, npoints)
box_idxs_of_pts (torch.Tensor): (B, M, T), default background = 0
"""
# TODO: Refactor this function as a CPU version of points_in_boxes_gpu
assert boxes.shape[1] == 7, \
assert points.shape[0] == boxes.shape[0], \
f'Points and boxes should have the same batch size, ' \
f'got {points.shape[0]} and {boxes.shape[0]}'
assert boxes.shape[2] == 7, \
f'boxes dimension should be 7, ' \
f'got unexpected shape {boxes.shape[2]}'
assert points.shape[1] == 3, \
assert points.shape[2] == 3, \
f'points dimension should be 3, ' \
f'got unexpected shape {points.shape[2]}'
batch_size, num_points, _ = points.shape
num_boxes = boxes.shape[1]
point_indices = points.new_zeros((boxes.shape[0], points.shape[0]),
point_indices = points.new_zeros((batch_size, num_boxes, num_points),
dtype=torch.int)
roiaware_pool3d_ext.points_in_boxes_cpu(boxes.float().contiguous(),
points.float().contiguous(),
point_indices)
for b in range(batch_size):
roiaware_pool3d_ext.points_in_boxes_cpu(boxes[b].float().contiguous(),
points[b].float().contiguous(),
point_indices[b])
point_indices = point_indices.transpose(1, 2)
return point_indices
......@@ -86,9 +90,9 @@ def points_in_boxes_batch(points, boxes):
"""Find points that are in boxes (CUDA)
Args:
points (torch.Tensor): [B, M, 3], [x, y, z] in LiDAR coordinate
points (torch.Tensor): [B, M, 3], [x, y, z] in LiDAR/DEPTH coordinate
boxes (torch.Tensor): [B, T, 7],
num_valid_boxes <= T, [x, y, z, w, l, h, ry] in LiDAR coordinate,
num_valid_boxes <= T, [x, y, z, dx, dy, dz, rz],
(x, y, z) is the bottom center.
Returns:
......
......@@ -15,9 +15,7 @@
inline void lidar_to_local_coords_cpu(float shift_x, float shift_y, float rz,
float &local_x, float &local_y) {
// should rotate pi/2 + alpha to translate LiDAR to local
float rot_angle = rz + M_PI / 2;
float cosa = cos(rot_angle), sina = sin(rot_angle);
float cosa = cos(-rz), sina = sin(-rz);
local_x = shift_x * cosa + shift_y * (-sina);
local_y = shift_x * sina + shift_y * cosa;
}
......@@ -29,13 +27,13 @@ inline int check_pt_in_box3d_cpu(const float *pt, const float *box3d,
// bottom center
float x = pt[0], y = pt[1], z = pt[2];
float cx = box3d[0], cy = box3d[1], cz = box3d[2];
float w = box3d[3], l = box3d[4], h = box3d[5], rz = box3d[6];
cz += h / 2.0; // shift to the center since cz in box3d is the bottom center
float dx = box3d[3], dy = box3d[4], dz = box3d[5], rz = box3d[6];
cz += dz / 2.0; // shift to the center since cz in box3d is the bottom center
if (fabsf(z - cz) > h / 2.0) return 0;
if (fabsf(z - cz) > dz / 2.0) return 0;
lidar_to_local_coords_cpu(x - cx, y - cy, rz, local_x, local_y);
float in_flag = (local_x > -l / 2.0) & (local_x < l / 2.0) &
(local_y > -w / 2.0) & (local_y < w / 2.0);
float in_flag = (local_x > -dx / 2.0) & (local_x < dx / 2.0) &
(local_y > -dy / 2.0) & (local_y < dy / 2.0);
return in_flag;
}
......
......@@ -24,9 +24,7 @@
__device__ inline void lidar_to_local_coords(float shift_x, float shift_y,
float rz, float &local_x,
float &local_y) {
// should rotate pi/2 + alpha to translate LiDAR to local
float rot_angle = rz + M_PI / 2;
float cosa = cos(rot_angle), sina = sin(rot_angle);
float cosa = cos(-rz), sina = sin(-rz);
local_x = shift_x * cosa + shift_y * (-sina);
local_y = shift_x * sina + shift_y * cosa;
}
......@@ -38,13 +36,13 @@ __device__ inline int check_pt_in_box3d(const float *pt, const float *box3d,
// bottom center
float x = pt[0], y = pt[1], z = pt[2];
float cx = box3d[0], cy = box3d[1], cz = box3d[2];
float w = box3d[3], l = box3d[4], h = box3d[5], rz = box3d[6];
cz += h / 2.0; // shift to the center since cz in box3d is the bottom center
float dx = box3d[3], dy = box3d[4], dz = box3d[5], rz = box3d[6];
cz += dz / 2.0; // shift to the center since cz in box3d is the bottom center
if (fabsf(z - cz) > h / 2.0) return 0;
if (fabsf(z - cz) > dz / 2.0) return 0;
lidar_to_local_coords(x - cx, y - cy, rz, local_x, local_y);
float in_flag = (local_x > -l / 2.0) & (local_x < l / 2.0) &
(local_y > -w / 2.0) & (local_y < w / 2.0);
float in_flag = (local_x > -dx / 2.0) & (local_x < dx / 2.0) &
(local_y > -dy / 2.0) & (local_y < dy / 2.0);
return in_flag;
}
......@@ -52,7 +50,7 @@ __global__ void points_in_boxes_kernel(int batch_size, int boxes_num,
int pts_num, const float *boxes,
const float *pts,
int *box_idx_of_points) {
// params boxes: (B, N, 7) [x, y, z, w, l, h, rz] in LiDAR coordinate, z is
// params boxes: (B, N, 7) [x, y, z, dx, dy, dz, rz] in LiDAR coordinate, z is
// the bottom center, each box DO NOT overlaps params pts: (B, npoints, 3) [x,
// y, z] in LiDAR coordinate params boxes_idx_of_points: (B, npoints), default
// -1
......@@ -80,7 +78,7 @@ __global__ void points_in_boxes_batch_kernel(int batch_size, int boxes_num,
int pts_num, const float *boxes,
const float *pts,
int *box_idx_of_points) {
// params boxes: (B, N, 7) [x, y, z, w, l, h, rz] in LiDAR coordinate, z is
// params boxes: (B, N, 7) [x, y, z, dx, dy, dz, rz] in LiDAR coordinate, z is
// the bottom center, each box DO NOT overlaps params pts: (B, npoints, 3) [x,
// y, z] in LiDAR coordinate params boxes_idx_of_points: (B, npoints), default
// -1
......@@ -107,7 +105,7 @@ __global__ void points_in_boxes_batch_kernel(int batch_size, int boxes_num,
void points_in_boxes_launcher(int batch_size, int boxes_num, int pts_num,
const float *boxes, const float *pts,
int *box_idx_of_points) {
// params boxes: (B, N, 7) [x, y, z, w, l, h, rz] in LiDAR coordinate, z is
// params boxes: (B, N, 7) [x, y, z, dx, dy, dz, rz] in LiDAR coordinate, z is
// the bottom center, each box DO NOT overlaps params pts: (B, npoints, 3) [x,
// y, z] in LiDAR coordinate params boxes_idx_of_points: (B, npoints), default
// -1
......@@ -132,7 +130,7 @@ void points_in_boxes_launcher(int batch_size, int boxes_num, int pts_num,
void points_in_boxes_batch_launcher(int batch_size, int boxes_num, int pts_num,
const float *boxes, const float *pts,
int *box_idx_of_points) {
// params boxes: (B, N, 7) [x, y, z, w, l, h, rz] in LiDAR coordinate, z is
// params boxes: (B, N, 7) [x, y, z, dx, dy, dz, rz] in LiDAR coordinate, z is
// the bottom center, each box params pts: (B, npoints, 3) [x, y, z] in
// LiDAR coordinate params boxes_idx_of_points: (B, npoints), default -1
cudaError_t err;
......@@ -155,7 +153,7 @@ void points_in_boxes_batch_launcher(int batch_size, int boxes_num, int pts_num,
int points_in_boxes_gpu(at::Tensor boxes_tensor, at::Tensor pts_tensor,
at::Tensor box_idx_of_points_tensor) {
// params boxes: (B, N, 7) [x, y, z, w, l, h, rz] in LiDAR coordinate, z is
// params boxes: (B, N, 7) [x, y, z, dx, dy, dz, rz] in LiDAR coordinate, z is
// the bottom center, each box DO NOT overlaps params pts: (B, npoints, 3) [x,
// y, z] in LiDAR coordinate params boxes_idx_of_points: (B, npoints), default
// -1
......@@ -180,7 +178,7 @@ int points_in_boxes_gpu(at::Tensor boxes_tensor, at::Tensor pts_tensor,
int points_in_boxes_batch(at::Tensor boxes_tensor, at::Tensor pts_tensor,
at::Tensor box_idx_of_points_tensor) {
// params boxes: (B, N, 7) [x, y, z, w, l, h, rz] in LiDAR coordinate, z is
// params boxes: (B, N, 7) [x, y, z, dx, dy, dz, rz] in LiDAR coordinate, z is
// the bottom center. params pts: (B, npoints, 3) [x, y, z] in LiDAR
// coordinate params boxes_idx_of_points: (B, npoints), default -1
......
......@@ -17,9 +17,7 @@
__device__ inline void lidar_to_local_coords(float shift_x, float shift_y,
float rz, float &local_x,
float &local_y) {
// should rotate pi/2 + alpha to translate LiDAR to local
float rot_angle = rz + M_PI / 2;
float cosa = cos(rot_angle), sina = sin(rot_angle);
float cosa = cos(-rz), sina = sin(-rz);
local_x = shift_x * cosa + shift_y * (-sina);
local_y = shift_x * sina + shift_y * cosa;
}
......@@ -27,17 +25,17 @@ __device__ inline void lidar_to_local_coords(float shift_x, float shift_y,
__device__ inline int check_pt_in_box3d(const float *pt, const float *box3d,
float &local_x, float &local_y) {
// param pt: (x, y, z)
// param box3d: (cx, cy, cz, w, l, h, rz) in LiDAR coordinate, cz in the
// param box3d: (cx, cy, cz, dx, dy, dz, rz) in LiDAR coordinate, cz in the
// bottom center
float x = pt[0], y = pt[1], z = pt[2];
float cx = box3d[0], cy = box3d[1], cz = box3d[2];
float w = box3d[3], l = box3d[4], h = box3d[5], rz = box3d[6];
cz += h / 2.0; // shift to the center since cz in box3d is the bottom center
float dx = box3d[3], dy = box3d[4], dz = box3d[5], rz = box3d[6];
cz += dz / 2.0; // shift to the center since cz in box3d is the bottom center
if (fabsf(z - cz) > h / 2.0) return 0;
if (fabsf(z - cz) > dz / 2.0) return 0;
lidar_to_local_coords(x - cx, y - cy, rz, local_x, local_y);
float in_flag = (local_x > -l / 2.0) & (local_x < l / 2.0) &
(local_y > -w / 2.0) & (local_y < w / 2.0);
float in_flag = (local_x > -dx / 2.0) & (local_x < dx / 2.0) &
(local_y > -dy / 2.0) & (local_y < dy / 2.0);
return in_flag;
}
......@@ -45,9 +43,9 @@ __global__ void generate_pts_mask_for_box3d(int boxes_num, int pts_num,
int out_x, int out_y, int out_z,
const float *rois, const float *pts,
int *pts_mask) {
// params rois: (N, 7) [x, y, z, w, l, h, rz] in LiDAR coordinate
// params rois: (N, 7) [x, y, z, dx, dy, dz, rz] in LiDAR coordinate
// params pts: (npoints, 3) [x, y, z]
// params pts_mask: (N, npoints): -1 means point doesnot in this box,
// params pts_mask: (N, npoints): -1 means point does not in this box,
// otherwise: encode (x_idxs, y_idxs, z_idxs) by binary bit
int pt_idx = blockIdx.x * blockDim.x + threadIdx.x;
int box_idx = blockIdx.y;
......@@ -63,14 +61,14 @@ __global__ void generate_pts_mask_for_box3d(int boxes_num, int pts_num,
pts_mask[0] = -1;
if (cur_in_flag > 0) {
float local_z = pts[2] - rois[2];
float w = rois[3], l = rois[4], h = rois[5];
float dx = rois[3], dy = rois[4], dz = rois[5];
float x_res = l / out_x;
float y_res = w / out_y;
float z_res = h / out_z;
float x_res = dx / out_x;
float y_res = dy / out_y;
float z_res = dz / out_z;
unsigned int x_idx = int((local_x + l / 2) / x_res);
unsigned int y_idx = int((local_y + w / 2) / y_res);
unsigned int x_idx = int((local_x + dx / 2) / x_res);
unsigned int y_idx = int((local_y + dy / 2) / y_res);
unsigned int z_idx = int(local_z / z_res);
x_idx = min(max(x_idx, 0), out_x - 1);
......@@ -231,7 +229,7 @@ void roiaware_pool3d_launcher(int boxes_num, int pts_num, int channels,
const float *pts_feature, int *argmax,
int *pts_idx_of_voxels, float *pooled_features,
int pool_method) {
// params rois: (N, 7) [x, y, z, w, l, h, rz] in LiDAR coordinate
// params rois: (N, 7) [x, y, z, dx, dy, dz, rz] in LiDAR coordinate
// params pts: (npoints, 3) [x, y, z] in LiDAR coordinate
// params pts_feature: (npoints, C)
// params argmax: (N, out_x, out_y, out_z, C)
......
# Copyright (c) OpenMMLab. All rights reserved.
import math
import numpy as np
import os
import pytest
import tempfile
import torch
from mmdet3d.core.bbox import LiDARInstance3DBoxes
from mmdet3d.core.bbox import LiDARInstance3DBoxes, limit_period
from mmdet3d.datasets import KittiDataset
......@@ -113,6 +114,7 @@ def test_getitem():
type='ObjectSample',
db_sampler=dict(
data_root='tests/data/kitti/',
# in coordinate system refactor, this test file is modified
info_path='tests/data/kitti/kitti_dbinfos_train.pkl',
rate=1.0,
prepare=dict(
......@@ -151,8 +153,29 @@ def test_getitem():
gt_bboxes_3d = data['gt_bboxes_3d']._data
gt_labels_3d = data['gt_labels_3d']._data
expected_gt_bboxes_3d = torch.tensor(
[[9.5081, -5.2269, -1.1370, 0.4915, 1.2288, 1.9353, -2.7136]])
[[9.5081, -5.2269, -1.1370, 1.2288, 0.4915, 1.9353, 1.9988]])
expected_gt_labels_3d = torch.tensor([0])
rot_matrix = data['img_metas']._data['pcd_rotation']
rot_angle = data['img_metas']._data['pcd_rotation_angle']
horizontal_flip = data['img_metas']._data['pcd_horizontal_flip']
vertical_flip = data['img_metas']._data['pcd_vertical_flip']
expected_rot_matrix = torch.tensor([[0.8018, 0.5976, 0.0000],
[-0.5976, 0.8018, 0.0000],
[0.0000, 0.0000, 1.0000]])
expected_rot_angle = 0.6404654291602163
noise_angle = 0.20247319
assert torch.allclose(expected_rot_matrix, rot_matrix, atol=1e-4)
assert math.isclose(expected_rot_angle, rot_angle, abs_tol=1e-4)
assert horizontal_flip is True
assert vertical_flip is False
# after coord system refactor
expected_gt_bboxes_3d[:, :3] = \
expected_gt_bboxes_3d[:, :3] @ rot_matrix @ rot_matrix
expected_gt_bboxes_3d[:, -1:] = -np.pi - expected_gt_bboxes_3d[:, -1:] \
+ 2 * rot_angle - 2 * noise_angle
expected_gt_bboxes_3d[:, -1:] = limit_period(
expected_gt_bboxes_3d[:, -1:], period=np.pi * 2)
assert points.shape == (780, 4)
assert torch.allclose(
gt_bboxes_3d.tensor, expected_gt_bboxes_3d, atol=1e-4)
......@@ -346,9 +369,10 @@ def test_format_results():
pipeline, modality, split = _generate_kitti_dataset_config()
kitti_dataset = KittiDataset(data_root, ann_file, split, pts_prefix,
pipeline, classes, modality)
# coord system refactor
boxes_3d = LiDARInstance3DBoxes(
torch.tensor(
[[8.7314, -1.8559, -1.5997, 0.4800, 1.2000, 1.8900, 0.0100]]))
[[8.7314, -1.8559, -1.5997, 1.2000, 0.4800, 1.8900, -1.5808]]))
labels_3d = torch.tensor([
0,
])
......@@ -359,21 +383,23 @@ def test_format_results():
expected_name = np.array(['Pedestrian'])
expected_truncated = np.array([0.])
expected_occluded = np.array([0])
expected_alpha = np.array([-3.3410306])
# coord sys refactor
expected_alpha = np.array(-3.3410306 + np.pi)
expected_bbox = np.array([[710.443, 144.00221, 820.29114, 307.58667]])
expected_dimensions = np.array([[1.2, 1.89, 0.48]])
expected_location = np.array([[1.8399826, 1.4700007, 8.410018]])
expected_rotation_y = np.array([-3.1315928])
expected_rotation_y = np.array([0.0100])
expected_score = np.array([0.5])
expected_sample_idx = np.array([0])
assert np.all(result_files[0]['name'] == expected_name)
assert np.allclose(result_files[0]['truncated'], expected_truncated)
assert np.all(result_files[0]['occluded'] == expected_occluded)
assert np.allclose(result_files[0]['alpha'], expected_alpha)
assert np.allclose(result_files[0]['alpha'], expected_alpha, 1e-3)
assert np.allclose(result_files[0]['bbox'], expected_bbox)
assert np.allclose(result_files[0]['dimensions'], expected_dimensions)
assert np.allclose(result_files[0]['location'], expected_location)
assert np.allclose(result_files[0]['rotation_y'], expected_rotation_y)
assert np.allclose(result_files[0]['rotation_y'], expected_rotation_y,
1e-3)
assert np.allclose(result_files[0]['score'], expected_score)
assert np.allclose(result_files[0]['sample_idx'], expected_sample_idx)
tmp_dir.cleanup()
......@@ -386,7 +412,7 @@ def test_bbox2result_kitti():
pipeline, classes, modality)
boxes_3d = LiDARInstance3DBoxes(
torch.tensor(
[[8.7314, -1.8559, -1.5997, 0.4800, 1.2000, 1.8900, 0.0100]]))
[[8.7314, -1.8559, -1.5997, 1.2000, 0.4800, 1.8900, -1.5808]]))
labels_3d = torch.tensor([
0,
])
......@@ -400,10 +426,11 @@ def test_bbox2result_kitti():
expected_file_path = os.path.join(temp_kitti_result_dir, '000000.txt')
expected_name = np.array(['Pedestrian'])
expected_dimensions = np.array([1.2000, 1.8900, 0.4800])
expected_rotation_y = np.array([0.0100]) - np.pi
# coord system refactor (reverse sign)
expected_rotation_y = 0.0100
expected_score = np.array([0.5])
assert np.all(det_annos[0]['name'] == expected_name)
assert np.allclose(det_annos[0]['rotation_y'], expected_rotation_y)
assert np.allclose(det_annos[0]['rotation_y'], expected_rotation_y, 1e-3)
assert np.allclose(det_annos[0]['score'], expected_score)
assert np.allclose(det_annos[0]['dimensions'], expected_dimensions)
assert os.path.exists(expected_file_path)
......
......@@ -4,6 +4,7 @@ import numpy as np
import tempfile
import torch
from mmdet3d.core import limit_period
from mmdet3d.datasets import LyftDataset
......@@ -11,6 +12,7 @@ def test_getitem():
np.random.seed(0)
torch.manual_seed(0)
root_path = './tests/data/lyft'
# in coordinate system refactor, this test file is modified
ann_file = './tests/data/lyft/lyft_infos.pkl'
class_names = ('car', 'truck', 'bus', 'emergency_vehicle', 'other_vehicle',
'motorcycle', 'bicycle', 'pedestrian', 'animal')
......@@ -49,9 +51,11 @@ def test_getitem():
pcd_horizontal_flip = data['img_metas']._data['pcd_horizontal_flip']
pcd_scale_factor = data['img_metas']._data['pcd_scale_factor']
pcd_rotation = data['img_metas']._data['pcd_rotation']
pcd_rotation_angle = data['img_metas']._data['pcd_rotation_angle']
sample_idx = data['img_metas']._data['sample_idx']
pcd_rotation_expected = np.array([[0.99869376, -0.05109515, 0.],
[0.05109515, 0.99869376, 0.],
# coord sys refactor
pcd_rotation_expected = np.array([[0.99869376, 0.05109515, 0.],
[-0.05109515, 0.99869376, 0.],
[0., 0., 1.]])
assert pts_filename == \
'tests/data/lyft/lidar/host-a017_lidar1_1236118886901125926.bin'
......@@ -82,6 +86,21 @@ def test_getitem():
expected_gt_labels = np.array([0, 4, 7])
original_classes = lyft_dataset.CLASSES
# manually go through pipeline
expected_points[:, :3] = (
(expected_points[:, :3] * torch.tensor([1, -1, 1]))
@ pcd_rotation_expected @ pcd_rotation_expected) * torch.tensor(
[1, -1, 1])
expected_gt_bboxes_3d[:, :3] = (
(expected_gt_bboxes_3d[:, :3] * torch.tensor([1, -1, 1]))
@ pcd_rotation_expected @ pcd_rotation_expected) * torch.tensor(
[1, -1, 1])
expected_gt_bboxes_3d[:, 3:6] = expected_gt_bboxes_3d[:, [4, 3, 5]]
expected_gt_bboxes_3d[:, 6:] = -expected_gt_bboxes_3d[:, 6:] \
- np.pi / 2 - pcd_rotation_angle * 2
expected_gt_bboxes_3d[:, 6:] = limit_period(
expected_gt_bboxes_3d[:, 6:], period=np.pi * 2)
assert torch.allclose(points, expected_points, 1e-2)
assert torch.allclose(gt_bboxes_3d.tensor, expected_gt_bboxes_3d, 1e-3)
assert np.all(gt_labels_3d.numpy() == expected_gt_labels)
......@@ -110,8 +129,10 @@ def test_getitem():
def test_evaluate():
root_path = './tests/data/lyft'
# in coordinate system refactor, this test file is modified
ann_file = './tests/data/lyft/lyft_infos_val.pkl'
lyft_dataset = LyftDataset(ann_file, None, root_path)
# in coordinate system refactor, this test file is modified
results = mmcv.load('./tests/data/lyft/sample_results.pkl')
ap_dict = lyft_dataset.evaluate(results, 'bbox')
car_precision = ap_dict['pts_bbox_Lyft/car_AP']
......@@ -149,11 +170,11 @@ def test_show():
kitti_dataset = LyftDataset(ann_file, None, root_path)
boxes_3d = LiDARInstance3DBoxes(
torch.tensor(
[[46.1218, -4.6496, -0.9275, 0.5316, 1.4442, 1.7450, 1.1749],
[33.3189, 0.1981, 0.3136, 0.5656, 1.2301, 1.7985, 1.5723],
[46.1366, -4.6404, -0.9510, 0.5162, 1.6501, 1.7540, 1.3778],
[33.2646, 0.2297, 0.3446, 0.5746, 1.3365, 1.7947, 1.5430],
[58.9079, 16.6272, -1.5829, 1.5656, 3.9313, 1.4899, 1.5505]]))
[[46.1218, -4.6496, -0.9275, 1.4442, 0.5316, 1.7450, -2.7457],
[33.3189, 0.1981, 0.3136, 1.2301, 0.5656, 1.7985, 3.1401],
[46.1366, -4.6404, -0.9510, 1.6501, 0.5162, 1.7540, -2.9486],
[33.2646, 0.2297, 0.3446, 1.3365, 0.5746, 1.7947, -3.1138],
[58.9079, 16.6272, -1.5829, 3.9313, 1.5656, 1.4899, -3.1213]]))
scores_3d = torch.tensor([0.1815, 0.1663, 0.5792, 0.2194, 0.2780])
labels_3d = torch.tensor([0, 0, 1, 1, 2])
result = dict(boxes_3d=boxes_3d, scores_3d=scores_3d, labels_3d=labels_3d)
......
......@@ -8,6 +8,7 @@ from mmdet3d.datasets import SUNRGBDDataset
def _generate_sunrgbd_dataset_config():
root_path = './tests/data/sunrgbd'
# in coordinate system refactor, this test file is modified
ann_file = './tests/data/sunrgbd/sunrgbd_infos.pkl'
class_names = ('bed', 'table', 'sofa', 'chair', 'toilet', 'desk',
'dresser', 'night_stand', 'bookshelf', 'bathtub')
......@@ -120,6 +121,8 @@ def test_getitem():
[[0.8308, 4.1168, -1.2035, 2.2493, 1.8444, 1.9245, 1.6486],
[2.3002, 4.8149, -1.2442, 0.5718, 0.8629, 0.9510, 1.6030],
[-1.1477, 1.8090, -1.1725, 0.6965, 1.5273, 2.0563, 0.0552]])
# coord sys refactor (rotation is correct but yaw has to be reversed)
expected_gt_bboxes_3d[:, 6:] = -expected_gt_bboxes_3d[:, 6:]
expected_gt_labels = np.array([0, 7, 6])
original_classes = sunrgbd_dataset.CLASSES
......
......@@ -16,6 +16,7 @@ def _generate_waymo_train_dataset_config():
file_client_args = dict(backend='disk')
db_sampler = dict(
data_root=data_root,
# in coordinate system refactor, this test file is modified
info_path=data_root + 'waymo_dbinfos_train.pkl',
rate=1.0,
prepare=dict(
......@@ -114,7 +115,7 @@ def test_getitem():
gt_bboxes_3d = data['gt_bboxes_3d']._data
gt_labels_3d = data['gt_labels_3d']._data
expected_gt_bboxes_3d = torch.tensor(
[[31.4750, -4.5690, 2.1857, 2.3519, 6.0931, 3.1756, -1.2895]])
[[31.8048, -0.1002, 2.1857, 6.0931, 2.3519, 3.1756, -0.1403]])
expected_gt_labels_3d = torch.tensor([0])
assert points.shape == (765, 5)
assert torch.allclose(
......@@ -132,8 +133,8 @@ def test_evaluate():
pipeline, classes, modality)
boxes_3d = LiDARInstance3DBoxes(
torch.tensor([[
6.9684e+01, 3.3335e+01, 4.1465e-02, 2.0100e+00, 4.3600e+00,
1.4600e+00, -9.0000e-02
6.9684e+01, 3.3335e+01, 4.1465e-02, 4.3600e+00, 2.0100e+00,
1.4600e+00, 9.0000e-02 - np.pi / 2
]]))
labels_3d = torch.tensor([0])
scores_3d = torch.tensor([0.5])
......@@ -150,8 +151,8 @@ def test_evaluate():
metric = ['waymo']
boxes_3d = LiDARInstance3DBoxes(
torch.tensor([[
6.9684e+01, 3.3335e+01, 4.1465e-02, 2.0100e+00, 4.3600e+00,
1.4600e+00, -9.0000e-02
6.9684e+01, 3.3335e+01, 4.1465e-02, 4.3600e+00, 2.0100e+00,
1.4600e+00, 9.0000e-02 - np.pi / 2
]]))
labels_3d = torch.tensor([0])
scores_3d = torch.tensor([0.8])
......@@ -178,11 +179,11 @@ def test_show():
data_root, ann_file, split=split, modality=modality, pipeline=pipeline)
boxes_3d = LiDARInstance3DBoxes(
torch.tensor(
[[46.1218, -4.6496, -0.9275, 0.5316, 1.4442, 1.7450, 1.1749],
[33.3189, 0.1981, 0.3136, 0.5656, 1.2301, 1.7985, 1.5723],
[46.1366, -4.6404, -0.9510, 0.5162, 1.6501, 1.7540, 1.3778],
[33.2646, 0.2297, 0.3446, 0.5746, 1.3365, 1.7947, 1.5430],
[58.9079, 16.6272, -1.5829, 1.5656, 3.9313, 1.4899, 1.5505]]))
[[46.1218, -4.6496, -0.9275, 1.4442, 0.5316, 1.7450, 1.1749],
[33.3189, 0.1981, 0.3136, 1.2301, 0.5656, 1.7985, 1.5723],
[46.1366, -4.6404, -0.9510, 1.6501, 0.5162, 1.7540, 1.3778],
[33.2646, 0.2297, 0.3446, 1.3365, 0.5746, 1.7947, 1.5430],
[58.9079, 16.6272, -1.5829, 3.9313, 1.5656, 1.4899, 1.5505]]))
scores_3d = torch.tensor([0.1815, 0.1663, 0.5792, 0.2194, 0.2780])
labels_3d = torch.tensor([0, 0, 1, 1, 2])
result = dict(boxes_3d=boxes_3d, scores_3d=scores_3d, labels_3d=labels_3d)
......@@ -231,8 +232,8 @@ def test_format_results():
pipeline, classes, modality)
boxes_3d = LiDARInstance3DBoxes(
torch.tensor([[
6.9684e+01, 3.3335e+01, 4.1465e-02, 2.0100e+00, 4.3600e+00,
1.4600e+00, -9.0000e-02
6.9684e+01, 3.3335e+01, 4.1465e-02, 4.3600e+00, 2.0100e+00,
1.4600e+00, 9.0000e-02 - np.pi / 2
]]))
labels_3d = torch.tensor([0])
scores_3d = torch.tensor([0.5])
......@@ -252,11 +253,11 @@ def test_format_results():
assert np.all(result_files[0]['name'] == expected_name)
assert np.allclose(result_files[0]['truncated'], expected_truncated)
assert np.all(result_files[0]['occluded'] == expected_occluded)
assert np.allclose(result_files[0]['alpha'], expected_alpha)
assert np.allclose(result_files[0]['bbox'], expected_bbox)
assert np.allclose(result_files[0]['bbox'], expected_bbox, 1e-3)
assert np.allclose(result_files[0]['dimensions'], expected_dimensions)
assert np.allclose(result_files[0]['location'], expected_location)
assert np.allclose(result_files[0]['rotation_y'], expected_rotation_y)
assert np.allclose(result_files[0]['score'], expected_score)
assert np.allclose(result_files[0]['sample_idx'], expected_sample_idx)
assert np.allclose(result_files[0]['alpha'], expected_alpha)
tmp_dir.cleanup()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment