def _ensure_calib_is_populated(self) -> None: """load up calibration object for all logs Returns: None """ if self._calib is None: self._calib = {} for log in self.log_list: calib_filename = os.path.join(self.root_dir, log, "vehicle_calibration_info.json") self._calib[log] = load_calib(calib_filename)
total_number = total_number * 7 bar = progressbar.ProgressBar(maxval=total_number, \ widgets=[progressbar.Bar('=', '[', ']'), ' ', progressbar.Percentage()]) print('Total number of files: {}. Translation starts...'.format(total_number)) print('Progress:') bar.start() i = 0 for log_id in argoverse_loader.log_list: argoverse_data = argoverse_loader.get(log_id) for cam in cams: # Recreate the calibration file content calibration_data = calibration.load_calib( data_dir + log_id + '/vehicle_calibration_info.json')[cam] L3 = 'P2: ' for j in calibration_data.K.reshape(1, 12)[0]: L3 = L3 + str(j) + ' ' L3 = L3[:-1] L6 = 'Tr_velo_to_cam: ' for k in calibration_data.extrinsic.reshape(1, 16)[0][0:12]: L6 = L6 + str(k) + ' ' L6 = L6[:-1] L1 = 'P0: 0 0 0 0 0 0 0 0 0 0 0 0' L2 = 'P1: 0 0 0 0 0 0 0 0 0 0 0 0' L4 = 'P3: 0 0 0 0 0 0 0 0 0 0 0 0' L5 = 'R0_rect: 1 0 0 0 1 0 0 0 1' L7 = 'Tr_imu_to_velo: 0 0 0 0 0 0 0 0 0 0 0 0'
from argoverse.utils.frustum_clipping import generate_frustum_planes from argoverse.utils.plane_visualization_utils import ( get_perpendicular, plot_frustum_planes_and_normals, populate_frustum_voxels, ) except ImportError: MAYAVI_MISSING = True else: MAYAVI_MISSING = False _TEST_DIR = pathlib.Path(__file__).parent.parent / "tests" if not MAYAVI_MISSING: calib = load_calib( os.fspath(_TEST_DIR / "test_data/tracking/1/vehicle_calibration_info.json") )["ring_front_center"] planes = generate_frustum_planes(calib.K, calib.camera) assert planes is not None skip_if_mayavi_missing = pytest.mark.skipif( MAYAVI_MISSING, reason= "Could not test functionality that depends on mayavi because mayavi is missing.", ) @skip_if_mayavi_missing # type: ignore def test_plot_frustum_planes_and_normals() -> None: """"""
dataset_name = 'argoverse' ts1 = 315975640448534784 # nano-second timestamp ts2 = 315975643412234000 img1_fpath = f'{img_dir}/ring_front_center_{ts1}.jpg' img2_fpath = f'{img_dir}/ring_front_center_{ts2}.jpg' img1 = imageio.imread(img1_fpath).astype(np.float32) / 255 img2 = imageio.imread(img2_fpath).astype(np.float32) / 255 # plt.imshow(img) # plt.show() if dataset_name == 'argoverse': calib_fpath = '/Users/johnlambert/Downloads/visual-odometry-tutorial/train1/273c1883-673a-36bf-b124-88311b1a80be/vehicle_calibration_info.json' calib_dict = load_calib(calib_fpath) K = calib_dict['ring_front_center'].K[:3,:3] # get the ground truth pose # timestamps # ts1 = Path(img1_fpath).stem.split('_')[-1] # ts2 = Path(img2_fpath).stem.split('_')[-1] #plot_argoverse_trajectory(ts1, ts2, dataset_dir, log_id) #plot_argoverse_epilines_from_ground_truth_poses(ts1, ts2, img1, img2, K) #plot_argoverse_epilines_from_annotated_correspondences(img1, img2, K, False) plot_argoverse_epilines_from_annotated_correspondences(img1, img2, K, True) # plot_backyard_epilines()
def process_a_split(data_dir, target_data_dir, split_file_path, bev_bnds, bev_meter_per_pixel, bev_wanted_classes, offset=0): """ Args: data_dir: directory that contains data corresponding to A SPECIFIC SPLIT (train, validation, test) target_data_dir: the dir to write to. Contains data corresponding to A SPECIFIC SPLIT in KITTI (training, testing) split_file_path: location to write all the sample_idx of a split bev_bnds: [4] containing [x_min, x_max, y_min, y_max] in meter for the bev bev_meter_per_pixel: number of meters in a pixel in bev, most often fractional bev_wanted_classes: [VEHICLE, BICYCLIST, PEDESTRIAN, ...] the classes to be for bev offset: first sample_idx to start counting from, needed to differentiate training and validation sample_idx because in KITTI they are under the same dir """ print("Processing", data_dir) target_velodyne_dir = os.path.join(target_data_dir, 'velodyne') target_velodyne_reduced_dir = os.path.join(target_data_dir, 'velodyne_reduced') target_calib_dir = os.path.join(target_data_dir, 'calib') target_image_2_dir = os.path.join(target_data_dir, 'image_2') if 'test' not in split_file_path: target_label_2_dir = os.path.join(target_data_dir, 'label_2') os.makedirs(target_velodyne_dir, exist_ok=True) os.makedirs(target_velodyne_reduced_dir, exist_ok=True) os.makedirs(target_calib_dir, exist_ok=True) os.makedirs(target_image_2_dir, exist_ok=True) if 'test' not in split_file_path: os.makedirs(target_label_2_dir, exist_ok=True) ############################## for saving BEV segmentation masks paths target_bev_drivable_dir = os.path.join(target_data_dir, 'bev_DRIVABLE') os.makedirs(target_bev_drivable_dir, exist_ok=True) target_bev_fov_dir = os.path.join(target_data_dir, 'bev_FOV') os.makedirs(target_bev_fov_dir, exist_ok=True) target_bev_cls_dirs = [] for wanted_cls in bev_wanted_classes: target_bev_cls_dir = os.path.join(target_data_dir, 'bev_{}'.format(wanted_cls)) os.makedirs(target_bev_cls_dir, exist_ok=True) target_bev_cls_dirs.append(target_bev_cls_dir) ############################## end for saving BEV segmentation masks paths # Check the number of logs, defined as one continuous trajectory argoverse_loader = ArgoverseTrackingLoader(data_dir) print('Total number of logs:', len(argoverse_loader)) argoverse_loader.print_all() print('\n') cams = [ 'ring_front_center', 'ring_front_left', 'ring_front_right', 'ring_rear_left', 'ring_rear_right', 'ring_side_left', 'ring_side_right' ] # count total number of files total_number = 0 for q in argoverse_loader.log_list: log_lidar_path = os.path.join(data_dir, q, 'lidar') path, dirs, files = next(os.walk(log_lidar_path)) total_number = total_number + len(files) total_number = total_number * len(cams) print('Now write sample indices to split file.') write_split_file(split_file_path, offset, total_number) bar = progressbar.ProgressBar(maxval=total_number, \ widgets=[progressbar.Bar('=', '[', ']'), ' ', progressbar.Percentage()]) print('Total number of files: {}. Translation starts...'.format( total_number)) print('Progress:') bar.start() i = 0 kitti_to_argo_mapping = {} for log_id in sorted(argoverse_loader.log_list): argoverse_data = argoverse_loader.get(log_id) from argoverse.map_representation.map_api import ArgoverseMap argoverse_map = ArgoverseMap() for cam in cams: ############################## Calibration for this whole log ############################## log_calib_path = os.path.join(data_dir, log_id, 'vehicle_calibration_info.json') calibration_data = calibration.load_calib(log_calib_path)[cam] calib_file_content = construct_calib_str(calibration_data, pts_in_cam_ego_coord=True) log_lidar_dir = os.path.join(data_dir, log_id, 'lidar') # Loop through the each lidar frame (10Hz) to rename, copy, and adapt # all images, lidars, calibration files, and label files. for frame_idx, timestamp in enumerate( sorted(argoverse_data.lidar_timestamp_list)): idx = str(i + offset).zfill(9) # recording the mapping from kitti to argo # (log index, the lidar frame index) uniquely identify a sample kitti_to_argo_mapping[idx] = (log_id, frame_idx) i += 1 if i < total_number: bar.update(i + 1) ############################## Lidar ############################## # Save lidar file into .bin format under the new directory lidar_file_path = os.path.join( log_lidar_dir, 'PC_{}.ply'.format(str(timestamp))) target_lidar_file_path = os.path.join(target_velodyne_dir, idx + '.bin') lidar_data = load_ply(lidar_file_path) # run this block of code only if we are using the cam coord instead of the ego coord if True: in_cam_coord = calibration_data.project_ego_to_cam( lidar_data) in_cam_coord = in_cam_coord[:, [2, 0, 1]] # tranpose the xyz in_cam_coord[:, [1, 2]] *= -1 # flip 2 of the axes lidar_data = in_cam_coord lidar_data_augmented = np.concatenate( (lidar_data, np.zeros([lidar_data.shape[0], 1])), axis=1) lidar_data_augmented = lidar_data_augmented.astype('float32') lidar_data_augmented.tofile(target_lidar_file_path) ############################## Image ############################## # Save the image file into .png format under the new directory cam_file_path = argoverse_data.image_list_sync[cam][frame_idx] target_cam_file_path = os.path.join(target_image_2_dir, idx + '.png') copyfile(cam_file_path, target_cam_file_path) target_calib_file_path = os.path.join(target_calib_dir, idx + '.txt') file = open(target_calib_file_path, 'w+') file.write(calib_file_content) file.close() ############################## BEV binary masks ############################## bev_drivable_save_path = os.path.join(target_bev_drivable_dir, idx + '.png') bev_wanted_save_paths = [ os.path.join(cls_dir, idx + '.png') for cls_dir in target_bev_cls_dirs ] bev_fov_save_path = os.path.join(target_bev_fov_dir, idx + '.png') get_bev(argoverse_data, argoverse_map, log_id, frame_idx, bev_bnds, bev_meter_per_pixel, bev_drivable_save_path, bev_wanted_classes, bev_wanted_save_paths, bev_fov_save_path, visualize=False, camera_calib=calibration_data) ############################## Labels ############################## if 'test' in split_file_path: continue label_object_list = argoverse_data.get_label_object(frame_idx) target_label_2_file_path = os.path.join( target_label_2_dir, idx + '.txt') file = open(target_label_2_file_path, 'w+') # DontCare objects must appear at the end as per KITTI label files object_lines = [] dontcare_lines = [] for detected_object in label_object_list: classes = detected_object.label_class classes = OBJ_CLASS_MAPPING_DICT[ classes] # map class type from artoverse to KITTI occulusion = round(detected_object.occlusion / 25) height = detected_object.height length = detected_object.length width = detected_object.width truncated = 0 center = detected_object.translation # in ego frame corners_ego_frame = detected_object.as_3d_bbox( ) # all eight points in ego frame corners_cam_frame = calibration_data.project_ego_to_cam( corners_ego_frame ) # all eight points in the camera frame image_corners = calibration_data.project_ego_to_image( corners_ego_frame) image_bbox = [ min(image_corners[:, 0]), min(image_corners[:, 1]), max(image_corners[:, 0]), max(image_corners[:, 1]) ] # the four coordinates we need for KITTI image_bbox = [round(x) for x in image_bbox] center_cam_frame = calibration_data.project_ego_to_cam( np.array([center])) # if 0 < center_cam_frame[0][2] < max_d and 0 < image_bbox[0] < 1920 and 0 < image_bbox[1] < 1200 and 0 < \ # image_bbox[2] < 1920 and 0 < image_bbox[3] < 1200: if True: # the center coordinates in cam frame we need for KITTI # for the orientation, we choose point 1 and point 5 for application p1 = corners_cam_frame[1] p5 = corners_cam_frame[5] # dz = p1[2] - p5[2] # dx = p1[0] - p5[0] # angle = math.atan2(dz, dx) angle_vec = p1 - p5 # norm vec along the x axis, points to the right in KITTI cam rect coordinate origin_vec = np.array([1, 0, 0]) import vg angle = vg.signed_angle(origin_vec, angle_vec, look=vg.basis.y, units='rad') # the orientation angle of the car beta = math.atan2(center_cam_frame[0][2], center_cam_frame[0][0]) alpha = angle + beta - math.pi / 2 line = classes + ' {} {} {} {} {} {} {} {} {} {} {} {} {} {} \n'.format( round(truncated, 2), occulusion, round(alpha, 2), round(image_bbox[0], 2), round(image_bbox[1], 2), round(image_bbox[2], 2), round(image_bbox[3], 2), round(height, 2), round(width, 2), round( length, 2), round(center_cam_frame[0][0], 2), round(center_cam_frame[0][1], 2) + height / 2, round(center_cam_frame[0][2], 2), round(angle, 2)) # separate the object lines so we can move all the dontcare lines at the end if classes == DONT_CARE: dontcare_lines.append(line) else: object_lines.append(line) for line in object_lines: file.write(line) for line in dontcare_lines: file.write(line) file.close() # write kitti_to_argo_mapping to a file split_dir = os.path.dirname(split_file_path) split_name = os.path.basename(split_file_path) split_name = os.path.splitext(split_name)[0] prefix = 'kitti_to_argo_mapping' kitti_to_argo_mapping_path = os.path.join( split_dir, "{}_{}.json".format(prefix, split_name)) file_handle = open(kitti_to_argo_mapping_path, 'w') json.dump(kitti_to_argo_mapping, file_handle) file_handle.close() bar.finish() print('Translation finished, processed {} files'.format(i))