def noise_per_object_v4_(gt_boxes, points=None, valid_mask=None, rotation_perturb=np.pi / 4, center_noise_std=1.0,\ global_random_rot_range=np.pi / 4, num_try=5, group_ids=None, data_aug_with_context=-1.0,\ data_aug_random_drop=-1.0): """ perform random rotation and translation on each groundtruth independently. Args: gt_boxes: [N, 7], gt box in lidar, [x, y, z, w, l, h, ry] points: [M, 4], point cloud in lidar, all points in the scene. rotation_perturb: [-0.785, 0.785], center_noise_std: [1.0, 1.0, 0.5], global_random_rot_range: [0, 0] num_try: 100 """ num_boxes = gt_boxes.shape[0] center_noise_std = np.array(center_noise_std, dtype=gt_boxes.dtype) loc_noises = np.random.normal(scale=center_noise_std, size=[num_boxes, num_try, 3]) rot_noises = np.random.uniform(rotation_perturb[0], rotation_perturb[1], size=[num_boxes, num_try]) origin = [0.5, 0.5, 0.5] offset = [0.0, 0.0, 0.0, 0.0, 0.0] if data_aug_with_context > 0: # to enlarge boxes and keep context offset = [0.0, 0.0, data_aug_with_context, data_aug_with_context, 0.0] # gt_boxes: x,y,z(lidar), w, l, h, ry(cam). gt_box_corners = box_np_ops.center_to_corner_box3d(gt_boxes[:, :3], gt_boxes[:, 3:6] + offset[2:5], gt_boxes[:, 6], origin=origin, axis=2) # noise on bev_box (x, y, w, l, ry). # todo: seems without noise in z-axis velo, because only cal bev iou, but z-axis noise added later. selected_noise = noise_per_box(gt_boxes[:, [0, 1, 3, 4, 6]] + offset, valid_mask, loc_noises, rot_noises) # loc_transforms = _select_transform(loc_noises, selected_noise) rot_transforms = _select_transform(rot_noises, selected_noise) surfaces = box_np_ops.corner_to_surfaces_3d_jit(gt_box_corners) if points is not None: point_masks = points_in_convex_polygon_3d_jit(points[:, :3], surfaces) # todo: perform random drop here. if data_aug_random_drop > 0.0: point_masks = point_masks points_transform_( points, gt_boxes[:, :3], point_masks, loc_transforms, rot_transforms, valid_mask, ) box3d_transform_(gt_boxes, loc_transforms, rot_transforms, valid_mask)
def points_in_rbbox(points, rbbox, z_axis=2, origin=(0.5, 0.5, 0.5)): rbbox_corners = center_to_corner_box3d( rbbox[:, :3], rbbox[:, 3:6], rbbox[:, -1], origin=origin, axis=z_axis ) surfaces = corner_to_surfaces_3d(rbbox_corners) indices = points_in_convex_polygon_3d_jit(points[:, :3], surfaces) return indices
def points_in_pyramids_mask(points, pyramids): ''' pyramids: [N', 15] surfaces: [N', 5, 3, 3] N': num of pyramids, '5: num of surfaces per pyramid, 3: num of corners per surface, 3: dim of each corner ''' indices = [1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 1, 0, 4, 3, 2] surfaces = np.concatenate([pyramids[:, 3 * k:3 * k + 3] for k in indices], axis=1).reshape(-1, 5, 3, 3) point_masks = points_in_convex_polygon_3d_jit(points[:, :3], surfaces) return point_masks
def remove_outside_points(points, rect, Trv2c, P2, image_shape): # 5x faster than remove_outside_points_v1(2ms vs 10ms) C, R, T = projection_matrix_to_CRT_kitti(P2) image_bbox = [0, 0, image_shape[1], image_shape[0]] frustum = get_frustum(image_bbox, C) frustum -= T frustum = np.linalg.inv(R) @ frustum.T frustum = camera_to_lidar(frustum.T, rect, Trv2c) frustum_surfaces = corner_to_surfaces_3d_jit(frustum[np.newaxis, ...]) indices = points_in_convex_polygon_3d_jit(points[:, :3], frustum_surfaces) points = points[indices.reshape([-1])] return points
def assign_label_to_voxel(gt_boxes, coors, voxel_size, coors_range): """assign a 0/1 label to each voxel based on whether the center of voxel is in gt_box. LIDAR. """ voxel_size = np.array(voxel_size, dtype=gt_boxes.dtype) coors_range = np.array(coors_range, dtype=gt_boxes.dtype) shift = coors_range[:3] voxel_origins = coors[:, ::-1] * voxel_size + shift voxel_centers = voxel_origins + voxel_size * 0.5 gt_box_corners = center_to_corner_box3d( gt_boxes[:, :3] - voxel_size * 0.5, gt_boxes[:, 3:6] + voxel_size, gt_boxes[:, 6], origin=[0.5, 0.5, 0.5], axis=2, ) gt_surfaces = corner_to_surfaces_3d(gt_box_corners) ret = points_in_convex_polygon_3d_jit(voxel_centers, gt_surfaces) return np.any(ret, axis=1).astype(np.int64)
def assign_label_to_voxel_v3(gt_boxes, coors, voxel_size, coors_range): """assign a 0/1 label to each voxel based on whether the center of voxel is in gt_box. LIDAR. """ voxel_size = np.array(voxel_size, dtype=gt_boxes.dtype) coors_range = np.array(coors_range, dtype=gt_boxes.dtype) shift = coors_range[:3] voxel_origins = coors[:, ::-1] * voxel_size + shift voxel_maxes = voxel_origins + voxel_size voxel_minmax = np.concatenate([voxel_origins, voxel_maxes], axis=-1) voxel_corners = minmax_to_corner_3d(voxel_minmax) gt_box_corners = center_to_corner_box3d( gt_boxes[:, :3], gt_boxes[:, 3:6], gt_boxes[:, 6], origin=[0.5, 0.5, 0.5], axis=2, ) gt_surfaces = corner_to_surfaces_3d(gt_box_corners) voxel_corners_flat = voxel_corners.reshape([-1, 3]) ret = points_in_convex_polygon_3d_jit(voxel_corners_flat, gt_surfaces) ret = ret.reshape([-1, 8, ret.shape[-1]]) return ret.any(-1).any(-1).astype(np.int64)
def noise_per_object_v2_( gt_boxes, points=None, valid_mask=None, rotation_perturb=np.pi / 4, center_noise_std=1.0, global_random_rot_range=np.pi / 4, num_try=100, ): """random rotate or remove each groundtrutn independently. use kitti viewer to test this function points_transform_ Args: gt_boxes: [N, 7], gt box in lidar.points_transform_ points: [M, 4], point cloud in lidar. """ num_boxes = gt_boxes.shape[0] if not isinstance(rotation_perturb, (list, tuple, np.ndarray)): rotation_perturb = [-rotation_perturb, rotation_perturb] if not isinstance(global_random_rot_range, (list, tuple, np.ndarray)): global_random_rot_range = [ -global_random_rot_range, global_random_rot_range ] if not isinstance(center_noise_std, (list, tuple, np.ndarray)): center_noise_std = [ center_noise_std, center_noise_std, center_noise_std ] if valid_mask is None: valid_mask = np.ones((num_boxes, ), dtype=np.bool_) center_noise_std = np.array(center_noise_std, dtype=gt_boxes.dtype) loc_noises = np.random.normal(scale=center_noise_std, size=[num_boxes, num_try, 3]) # loc_noises = np.random.uniform( # -center_noise_std, center_noise_std, size=[num_boxes, num_try, 3]) rot_noises = np.random.uniform(rotation_perturb[0], rotation_perturb[1], size=[num_boxes, num_try]) gt_grots = np.arctan2(gt_boxes[:, 0], gt_boxes[:, 1]) grot_lowers = global_random_rot_range[0] - gt_grots grot_uppers = global_random_rot_range[1] - gt_grots global_rot_noises = np.random.uniform( grot_lowers[..., np.newaxis], grot_uppers[..., np.newaxis], size=[num_boxes, num_try], ) origin = [0.5, 0.5, 0] gt_box_corners = box_np_ops.center_to_corner_box3d(gt_boxes[:, :3], gt_boxes[:, 3:6], gt_boxes[:, 6], origin=origin, axis=2) if np.abs(global_random_rot_range[0] - global_random_rot_range[1]) < 1e-3: selected_noise = noise_per_box(gt_boxes[:, [0, 1, 3, 4, 6]], valid_mask, loc_noises, rot_noises) else: selected_noise = noise_per_box_v2_( gt_boxes[:, [0, 1, 3, 4, 6]], valid_mask, loc_noises, rot_noises, global_rot_noises, ) loc_transforms = _select_transform(loc_noises, selected_noise) rot_transforms = _select_transform(rot_noises, selected_noise) if points is not None: surfaces = box_np_ops.corner_to_surfaces_3d_jit(gt_box_corners) point_masks = points_in_convex_polygon_3d_jit(points[:, :3], surfaces) points_transform_( points, gt_boxes[:, :3], point_masks, loc_transforms, rot_transforms, valid_mask, ) box3d_transform_(gt_boxes, loc_transforms, rot_transforms, valid_mask)
def mask_points_in_corners(points, box_corners): surfaces = box_np_ops.corner_to_surfaces_3d(box_corners) mask = points_in_convex_polygon_3d_jit(points[:, :3], surfaces) return mask
def get_task_detections(self, task_id, num_class_with_bg, test_cfg, batch_cls_preds, batch_reg_preds, batch_dir_preds=None, batch_iou_preds=None, batch_anchors=None, batch_anchors_mask=None, meta_list=None, batch_valid_frustum=None): predictions_dicts = [] post_center_range = self.post_center_range anchors = batch_anchors[0][0] for box_preds, cls_preds, dir_preds, iou_preds, a_mask, meta, valid_frustum in zip(batch_reg_preds, batch_cls_preds, batch_dir_preds, batch_iou_preds, batch_anchors_mask, meta_list, batch_valid_frustum): # get dir labels if self.use_direction_classifier: dir_labels = torch.max(dir_preds, dim=-1)[1] # [70400] # get scores from cls_preds total_scores = torch.sigmoid(cls_preds) # [70400, 1] top_scores = total_scores.squeeze(-1) # [70400] top_labels = self.top_labels # SCORE_THRESHOLD: REMOVE those boxes lower than 0.3. if test_cfg.score_threshold > 0.0: thresh = self.thresh # thresh = 0.4 top_scores_keep = top_scores >= thresh top_scores = top_scores.masked_select(top_scores_keep) # todo: replace classification score with iou prediction. iou_preds = (iou_preds.squeeze() + 1) * 0.5 top_scores *= torch.pow(iou_preds.masked_select(top_scores_keep), 4) # extra centerness from dinms # dist_boxes_anchors = torch.abs(box_preds[top_scores_keep] - anchors[top_scores_keep]) # dist_metric = torch.softmax(torch.pow(torch.pow(dist_boxes_anchors[:, 0:2], 2).sum(-1), 0.5), dim=0) # dist_metric = torch.ones_like(dist_metric) - dist_metric # top_scores *= torch.pow(dist_metric, 2) # NMS: obtain remained box_preds & dir_labels & cls_labels after score threshold. if top_scores.shape[0] != 0: if test_cfg.score_threshold > 0.0: box_preds = box_preds[top_scores_keep] if self.use_direction_classifier: dir_labels = dir_labels[top_scores_keep] top_labels = top_labels[top_scores_keep] boxes_for_nms = box_preds[:, [0, 1, 3, 4, -1]] # REMOVE overlap boxes by bev rotate-nms. nms_type = "rotate_weighted_nms" if nms_type == "rotate_nms": nms_func = box_torch_ops.rotate_nms selected = nms_func(boxes_for_nms, top_scores, pre_max_size=test_cfg.nms.nms_pre_max_size, post_max_size=test_cfg.nms.nms_post_max_size, iou_threshold=test_cfg.nms.nms_iou_threshold, ) box_preds = box_preds[selected] if self.use_direction_classifier: dir_labels = dir_labels[selected] label_preds = top_labels[selected] scores = top_scores[selected] elif nms_type == 'rotate_weighted_nms': nms_func = box_torch_ops.rotate_weighted_nms box_preds, dir_labels, label_preds, scores, selected = nms_func(box_preds, boxes_for_nms, dir_labels, top_labels, top_scores, iou_preds[top_scores_keep], anchors[top_scores_keep], pre_max_size=test_cfg.nms.nms_pre_max_size, post_max_size=test_cfg.nms.nms_post_max_size, iou_threshold=test_cfg.nms.nms_iou_threshold, enable_centerness=True, centerness_pow=2, nms_cnt_thresh=2.6, # 2.6 nms_sigma_dist_interval=(0, 20, 40, 60), nms_sigma_square=(0.0009, 0.009, 0.1, 1), suppressed_thresh=0.3, ) else: raise NotImplementedError else: box_preds = torch.zeros([0, 7], dtype=float) if box_preds.shape[0] > 0: from det3d.core.bbox.geometry import points_in_convex_polygon_3d_jit indices = points_in_convex_polygon_3d_jit(box_preds[:, :3].cpu().numpy(), valid_frustum.cpu().numpy()) box_preds = box_preds[indices.reshape([-1])] dir_labels = dir_labels[indices.reshape([-1])] label_preds = label_preds[indices.reshape([-1])] scores = scores[indices.reshape([-1])] # POST-PROCESSING of predictions. if box_preds.shape[0] != 0: # move pred boxes direction by pi, eg. pred_ry < 0 while pred_dir_label > 0. if self.use_direction_classifier: opp_labels = ((box_preds[..., -1] - self.direction_offset) > 0) ^ (dir_labels.byte() == 1) box_preds[..., -1] += torch.where(opp_labels, torch.tensor(np.pi).type_as(box_preds), torch.tensor(0.0).type_as(box_preds), ) # useful for dir accuracy, but has no impact on localization # remove pred boxes out of POST_VALID_RANGE mask = (box_preds[:, :3] >= post_center_range[:3]).all(1) mask &= (box_preds[:, :3] <= post_center_range[3:]).all(1) predictions_dict = {"box3d_lidar": box_preds[mask], "scores": scores[mask], "label_preds": label_preds[mask], "metadata": meta, } else: # TODO: what can zero_pred can be used for? and how to eval zero results? dtype = batch_reg_preds.dtype device = batch_reg_preds.device predictions_dict = { "box3d_lidar": torch.zeros([0, self.box_n_dim], dtype=dtype, device=device), "scores": torch.zeros([0], dtype=dtype, device=device), "label_preds": torch.zeros([0], dtype=top_labels.dtype, device=device), "metadata": meta, } predictions_dicts.append(predictions_dict) return predictions_dicts
def noise_per_object_v3_( gt_boxes, points=None, valid_mask=None, rotation_perturb=np.pi / 4, center_noise_std=1.0,\ global_random_rot_range=np.pi / 4, num_try=5, group_ids=None,): """random rotate or remove each groundtruth independently. use kitti viewer to test this function points_transform_ Args: gt_boxes: [N, 7], gt box in lidar.points_transform_ points: [M, 4], point cloud in lidar. rotation_perturb: [-0.785, 0.785], center_noise_std: [1.0, 1.0, 0.5], global_random_rot_range: [0, 0] num_try: 100 """ num_boxes = gt_boxes.shape[0] if not isinstance(rotation_perturb, (list, tuple, np.ndarray)): # False rotation_perturb = [-rotation_perturb, rotation_perturb] if not isinstance(global_random_rot_range, (list, tuple, np.ndarray)): # False global_random_rot_range = [ -global_random_rot_range, global_random_rot_range ] enable_grot = ( np.abs(global_random_rot_range[0] - global_random_rot_range[1]) >= 1e-3 ) # False if not isinstance(center_noise_std, (list, tuple, np.ndarray)): # False center_noise_std = [ center_noise_std, center_noise_std, center_noise_std ] if valid_mask is None: # False valid_mask = np.ones((num_boxes, ), dtype=np.bool_) center_noise_std = np.array(center_noise_std, dtype=gt_boxes.dtype) loc_noises = np.random.normal(scale=center_noise_std, size=[num_boxes, num_try, 3]) rot_noises = np.random.uniform(rotation_perturb[0], rotation_perturb[1], size=[num_boxes, num_try]) gt_grots = np.arctan2(gt_boxes[:, 0], gt_boxes[:, 1]) grot_lowers = global_random_rot_range[0] - gt_grots grot_uppers = global_random_rot_range[1] - gt_grots global_rot_noises = np.random.uniform( grot_lowers[..., np.newaxis], grot_uppers[..., np.newaxis], size=[num_boxes, num_try], ) if group_ids is not None: # False if enable_grot: set_group_noise_same_v2_(loc_noises, rot_noises, global_rot_noises, group_ids) else: set_group_noise_same_(loc_noises, rot_noises, group_ids) group_centers, group_id_num_dict = get_group_center( gt_boxes[:, :3], group_ids) if enable_grot: group_transform_v2_( loc_noises, rot_noises, gt_boxes[:, :3], gt_boxes[:, 6], group_centers, global_rot_noises, valid_mask, ) else: group_transform_( loc_noises, rot_noises, gt_boxes[:, :3], gt_boxes[:, 6], group_centers, valid_mask, ) group_nums = np.array(list(group_id_num_dict.values()), dtype=np.int64) origin = [0.5, 0.5, 0.5] gt_box_corners = box_np_ops.center_to_corner_box3d(gt_boxes[:, :3], gt_boxes[:, 3:6], gt_boxes[:, 6], origin=origin, axis=2) if group_ids is not None: if not enable_grot: selected_noise = noise_per_box_group( gt_boxes[:, [0, 1, 3, 4, 6]], valid_mask, loc_noises, rot_noises, group_nums, ) else: selected_noise = noise_per_box_group_v2_( gt_boxes[:, [0, 1, 3, 4, 6]], valid_mask, loc_noises, rot_noises, group_nums, global_rot_noises, ) else: if not enable_grot: # True selected_noise = noise_per_box( gt_boxes[:, [0, 1, 3, 4, 6]], valid_mask, loc_noises, rot_noises) # todo: seems without noise in z-axis velo else: selected_noise = noise_per_box_v2_( gt_boxes[:, [0, 1, 3, 4, 6]], valid_mask, loc_noises, rot_noises, global_rot_noises, ) loc_transforms = _select_transform(loc_noises, selected_noise) rot_transforms = _select_transform(rot_noises, selected_noise) surfaces = box_np_ops.corner_to_surfaces_3d_jit(gt_box_corners) if points is not None: point_masks = points_in_convex_polygon_3d_jit(points[:, :3], surfaces) points_transform_( points, gt_boxes[:, :3], point_masks, loc_transforms, rot_transforms, valid_mask, ) box3d_transform_(gt_boxes, loc_transforms, rot_transforms, valid_mask)
def noise_per_object_v3_( gt_boxes, gt_boxes_1, gt_boxes_2, gt_boxes_3, points=None, points_1=None, points_2=None, valid_mask=None, rotation_perturb=np.pi / 4, center_noise_std=1.0, global_random_rot_range=np.pi / 4, num_try=5, group_ids=None, ): """random rotate or remove each groundtruth independently. use kitti viewer to test this function points_transform_ Args: gt_boxes: [N, 7], gt box in lidar.points_transform_ points: [M, 4], point cloud in lidar. """ num_boxes = gt_boxes.shape[0] if not isinstance(rotation_perturb, (list, tuple, np.ndarray)): rotation_perturb = [-rotation_perturb, rotation_perturb] if not isinstance(global_random_rot_range, (list, tuple, np.ndarray)): global_random_rot_range = [ -global_random_rot_range, global_random_rot_range ] enable_grot = (np.abs(global_random_rot_range[0] - global_random_rot_range[1]) >= 1e-3) if not isinstance(center_noise_std, (list, tuple, np.ndarray)): center_noise_std = [ center_noise_std, center_noise_std, center_noise_std ] if valid_mask is None: valid_mask = np.ones((num_boxes, ), dtype=np.bool_) center_noise_std = np.array(center_noise_std, dtype=gt_boxes.dtype) loc_noises = np.random.normal(scale=center_noise_std, size=[num_boxes, num_try, 3]) # loc_noises = np.random.uniform( # -center_noise_std, center_noise_std, size=[num_boxes, num_try, 3]) rot_noises = np.random.uniform(rotation_perturb[0], rotation_perturb[1], size=[num_boxes, num_try]) gt_grots = np.arctan2(gt_boxes[:, 0], gt_boxes[:, 1]) grot_lowers = global_random_rot_range[0] - gt_grots grot_uppers = global_random_rot_range[1] - gt_grots global_rot_noises = np.random.uniform( grot_lowers[..., np.newaxis], grot_uppers[..., np.newaxis], size=[num_boxes, num_try], ) if group_ids is not None: if enable_grot: set_group_noise_same_v2_(loc_noises, rot_noises, global_rot_noises, group_ids) else: set_group_noise_same_(loc_noises, rot_noises, group_ids) group_centers, group_id_num_dict = get_group_center( gt_boxes[:, :3], group_ids) if enable_grot: group_transform_v2_( loc_noises, rot_noises, gt_boxes[:, :3], gt_boxes[:, 6], group_centers, global_rot_noises, valid_mask, ) else: group_transform_( loc_noises, rot_noises, gt_boxes[:, :3], gt_boxes[:, 6], group_centers, valid_mask, ) group_nums = np.array(list(group_id_num_dict.values()), dtype=np.int64) origin = [0.5, 0.5, 0.5] # TODO: 3个gt_box gt_box_corners = box_np_ops.center_to_corner_box3d(gt_boxes[:, :3], gt_boxes[:, 3:6], gt_boxes[:, 6], origin=origin, axis=2) # T-1 gt_box_corners_1 = box_np_ops.center_to_corner_box3d(gt_boxes_1[:, :3], gt_boxes_1[:, 3:6], gt_boxes_1[:, 6], origin=origin, axis=2) # T+1 gt_box_corners_2 = box_np_ops.center_to_corner_box3d(gt_boxes_2[:, :3], gt_boxes_2[:, 3:6], gt_boxes_2[:, 6], origin=origin, axis=2) # T-2 gt_box_corners_3 = box_np_ops.center_to_corner_box3d(gt_boxes_3[:, :3], gt_boxes_3[:, 3:6], gt_boxes_3[:, 6], origin=origin, axis=2) if group_ids is not None: if not enable_grot: selected_noise = noise_per_box_group( gt_boxes[:, [0, 1, 3, 4, 6]], valid_mask, loc_noises, rot_noises, group_nums, ) else: selected_noise = noise_per_box_group_v2_( gt_boxes[:, [0, 1, 3, 4, 6]], valid_mask, loc_noises, rot_noises, group_nums, global_rot_noises, ) else: if not enable_grot: selected_noise = noise_per_box(gt_boxes[:, [0, 1, 3, 4, 6]], gt_boxes_1[:, [0, 1, 3, 4, 6]], gt_boxes_2[:, [0, 1, 3, 4, 6]], gt_boxes_3[:, [0, 1, 3, 4, 6]], valid_mask, loc_noises, rot_noises) else: selected_noise = noise_per_box_v2_( gt_boxes[:, [0, 1, 3, 4, 6]], valid_mask, loc_noises, rot_noises, global_rot_noises, ) loc_transforms = _select_transform(loc_noises, selected_noise) rot_transforms = _select_transform(rot_noises, selected_noise) surfaces = box_np_ops.corner_to_surfaces_3d_jit(gt_box_corners) if points is not None: point_masks = points_in_convex_polygon_3d_jit(points[:, :3], surfaces) points_transform_( points, gt_boxes[:, :3], point_masks, loc_transforms, rot_transforms, valid_mask, ) # T-1 帧的增广 loc_transforms_1 = get_loc_transform(loc_transforms, rot_transforms, gt_boxes, gt_boxes_1) surfaces = box_np_ops.corner_to_surfaces_3d_jit(gt_box_corners_1) if points_1 is not None: point_masks = points_in_convex_polygon_3d_jit(points_1[:, :3], surfaces) points_transform_( points_1, gt_boxes_1[:, :3], point_masks, loc_transforms_1, rot_transforms, valid_mask, ) box3d_transform_(gt_boxes_1, loc_transforms_1, rot_transforms, valid_mask) # T+1帧的增广 loc_transforms_2 = get_loc_transform(loc_transforms, rot_transforms, gt_boxes, gt_boxes_2) box3d_transform_(gt_boxes_2, loc_transforms_2, rot_transforms, valid_mask) # T-2帧的增广 loc_transforms_3 = get_loc_transform(loc_transforms, rot_transforms, gt_boxes, gt_boxes_3) if points_2 is not None: point_masks = points_in_convex_polygon_3d_jit(points_2[:, :3], surfaces) points_transform_( points_2, gt_boxes_3[:, :3], point_masks, loc_transforms_3, rot_transforms, valid_mask, ) # T帧的box需要做为基准,所以最后变换 box3d_transform_(gt_boxes, loc_transforms, rot_transforms, valid_mask)