예제 #1
0
    def __init__(self, experiment_config_path, planes_dir, calib_dir):
        model_config, _, eval_config, dataset_config = \
            config_builder.get_configs_from_pipeline_file(
                experiment_config_path, is_training=False)
        self.dataset_config = config_builder.proto_to_obj(dataset_config)
        dataset_config.data_split_dir = 'testing'
        # These two lines below are necessary for KittiUtils to function properly
        self.cluster_split = self.dataset_config.cluster_split
        self.config = dataset_config

        self.data_split = self.config.data_split
        self.name = self.config.name
        self.dataset_dir = os.path.expanduser(self.config.dataset_dir)
        self.has_labels = self.config.has_labels
        self.cluster_split = self.config.cluster_split
        self.classes = list(self.config.classes)
        self.num_classes = len(self.classes)
        self.num_clusters = np.asarray(self.config.num_clusters)
        self.model_config = config_builder.proto_to_obj(model_config)
        self.paths_config = self.model_config.paths_config
        self.checkpoint_dir = self.paths_config.checkpoint_dir
        # Build the dataset object
        self.dataset = DatasetBuilder.build_kitti_dataset(dataset_config,
                                                          use_defaults=False)
        self.dataset.train_val_test = "test"

        # Score threshold for drawing bounding boxes
        self.avod_score_threshold = 0.25
예제 #2
0
def set_up_model(pipeline_config, data_split):

    model_config, train_config, _, dataset_config = \
        config_builder.get_configs_from_pipeline_file(
            pipeline_config, is_training=False)

    dataset_config = config_builder.proto_to_obj(dataset_config)

    train_val_test = data_split
    # Always run in test mode
    dataset_config.data_split = 'test'
    dataset_config.data_split_dir = 'testing'
    dataset_config.has_labels = False
    dataset_config.aug_list = []

    dataset = DatasetBuilder.build_kitti_dataset(dataset_config,
                                                 use_defaults=False)

    model_name = model_config.model_name
    if model_name == 'rpn_model':
        model = RpnModel(model_config,
                         train_val_test=train_val_test,
                         dataset=dataset)
    elif model_name == 'avod_model':
        model = AvodModel(model_config,
                          train_val_test=train_val_test,
                          dataset=dataset)
    elif model_name == 'avod_ssd_model':
        model = AvodSSDModel(model_config,
                             train_val_test=train_val_test,
                             dataset=dataset)
    else:
        raise ValueError('Invalid model_name')

    return model
예제 #3
0
def main(_):
    parser = argparse.ArgumentParser()

    # Example usage
    # --checkpoint_name='avod_cars_example'
    # --data_split='test'
    # --ckpt_indices=50 100 112
    # Optional arg:
    # --device=0

    parser.add_argument('--checkpoint_name',
                        type=str,
                        dest='checkpoint_name',
                        required=True,
                        help='Checkpoint name must be specified as a str\
                        and must match the experiment config file name.')

    parser.add_argument('--data_split',
                        type=str,
                        dest='data_split',
                        required=True,
                        help='Data split must be specified e.g. val or test')

    parser.add_argument('--ckpt_indices',
                        type=int,
                        nargs='+',
                        dest='ckpt_indices',
                        required=True,
                        help='Checkpoint indices must be a set of \
        integers with space in between -> 0 10 20 etc')

    parser.add_argument('--device',
                        type=str,
                        dest='device',
                        default='0',
                        help='CUDA device id')

    args = parser.parse_args()
    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)

    experiment_config = args.checkpoint_name + '.config'

    # Read the config from the experiment folder
    experiment_config_path = avod.root_dir() + '/data/outputs/' +\
        args.checkpoint_name + '/' + experiment_config

    model_config, _, eval_config, dataset_config = \
        config_builder.get_configs_from_pipeline_file(
            experiment_config_path, is_training=False)

    os.environ['CUDA_VISIBLE_DEVICES'] = args.device
    inference(model_config, eval_config, dataset_config, args.data_split,
              args.ckpt_indices)

    # Visualize
    show_predictions_2d_jhuang.main(args.checkpoint_name)
예제 #4
0
def test():
    parser = argparse.ArgumentParser()
    parser.add_argument('--avod_config_path',
                    type=str,
                    dest='avod_config_path',
                    required=True,
                    help='avod_config_path')
    parser.add_argument('--sample_idx',
                    type=str,
                    dest='sample_idx',
                    required=True,
                    help='sample id')
    args = parser.parse_args()
    _, _, _, dataset_config = \
    config_builder.get_configs_from_pipeline_file(
        args.avod_config_path, is_training=False)
    dataset = get_dataset(dataset_config, 'val')

    idx = np.argwhere(dataset.sample_names==args.sample_idx).squeeze()
    # print(idx)
    kitti_samples = dataset.load_samples([idx])
    sample = kitti_samples[0]

    label_mask = np.equal(sample[constants.KEY_LABEL_CLASSES], g_type2onehotclass['Car']+1)
    gt_cls = sample[constants.KEY_LABEL_CLASSES][label_mask]
    gt_boxes_3d = sample[constants.KEY_LABEL_BOXES_3D][label_mask]
    gt_boxes_bev = []
    for i in range(len(gt_cls)):
        gt_obj = box_3d_encoder.box_3d_to_object_label(gt_boxes_3d[i], gt_cls[i])
        gt_corner_3d = compute_box_3d(gt_obj)
        gt_boxes_bev.append(gt_corner_3d[:4, [0,2]])
    print(gt_boxes_bev)

    rpn_out = pickle.load(open("rpn_out/%s" % sample[constants.KEY_SAMPLE_NAME], "rb"))
    pos_prop = []
    for prop in rpn_out['proposals_and_scores']:
        corners = compute_box_3d(box_3d_encoder.box_3d_to_object_label(prop[:7]))
        label_idx, iou = find_match_label(corners[:4, [0,2]], gt_boxes_bev)
        if iou > 0.65:
            pos_prop.append(corners)
    pc = sample[constants.KEY_POINT_CLOUD].T
    import mayavi.mlab as mlab
    from viz_util import draw_lidar, draw_gt_boxes3d
    fig = draw_lidar(pc)
    fig = draw_gt_boxes3d(pos_prop, fig, draw_text=False, color=(1, 1, 1))
    input()

    # visualize_rpn_out(sample, rpn_out['proposals_and_scores'])
    prediction = pickle.load(open("%s"%sample[constants.KEY_SAMPLE_NAME], "rb"))
    print(prediction)
    visualize(dataset, sample, prediction)
예제 #5
0
def main(_):

    experiment_config = 'avod_cars_example.config'

    # Read the config from the experiment folder
    experiment_config_path = avod.root_dir() + '/data/outputs/' +\
        'avod_cars_example' + '/' + experiment_config

    model_config, _, eval_config, dataset_config = \
        config_builder.get_configs_from_pipeline_file(
            experiment_config_path, is_training=False)

    os.environ['CUDA_VISIBLE_DEVICES'] = '0'
    test(model_config, eval_config, dataset_config, 'val', -1)
예제 #6
0
    def setUp(self):
        tf.test.TestCase.setUp(self)

        test_pipeline_config_path = avod.root_dir() + \
            '/configs/unittest_pipeline.config'

        self.model_config, self.train_config, _,  dataset_config = \
            config_builder.get_configs_from_pipeline_file(
                test_pipeline_config_path, is_training=True)

        # Generate dataset
        self.dataset = DatasetBuilder.build_kitti_dataset(
            DatasetBuilder.KITTI_UNITTEST, use_defaults=False,
            new_cfg=dataset_config)
예제 #7
0
def main(_):
    parser = argparse.ArgumentParser()

    default_pipeline_config_path = avod.root_dir() + \
        '/configs/avod_cars_example.config'

    default_output_dir = '/data/kitti_avod/object/outputs'

    parser.add_argument('--pipeline_config',
                        type=str,
                        dest='pipeline_config_path',
                        default=default_pipeline_config_path,
                        help='Path to the pipeline config')

    parser.add_argument('--data_split',
                        type=str,
                        dest='data_split',
                        default='val',
                        help='Data split for evaluation')

    parser.add_argument('--device',
                        type=str,
                        dest='device',
                        default=None,
                        help='CUDA device id')

    parser.add_argument('--output_dir',
                        type=str,
                        dest='output_dir',
                        default=default_output_dir,
                        help='output dir to save checkpoints')

    args = parser.parse_args()

    # Parse pipeline config
    model_config, _, eval_config, dataset_config = \
        config_builder.get_configs_from_pipeline_file(
            args.pipeline_config_path,
            is_training=False,
            output_dir=args.output_dir)

    # Overwrite data split
    dataset_config.data_split = args.data_split

    # Set CUDA device id
    if args.device:
        os.environ['CUDA_VISIBLE_DEVICES'] = args.device

    evaluate(model_config, eval_config, dataset_config,
             output_dir=args.output_dir)
예제 #8
0
def main(_):
    parser = argparse.ArgumentParser()

    # Defaults
    default_pipeline_config_path = avod.root_dir() + \
        '/configs/avod_cars_example.config'
    default_data_split = 'train'
    default_device = '1'

    parser.add_argument('--pipeline_config',
                        type=str,
                        dest='pipeline_config_path',
                        default=default_pipeline_config_path,
                        help='Path to the pipeline config')

    parser.add_argument('--data_split',
                        type=str,
                        dest='data_split',
                        default=default_data_split,
                        help='Data split for training')

    parser.add_argument('--device',
                        type=str,
                        dest='device',
                        default=default_device,
                        help='CUDA device id')

    parser.add_argument('--output_dir',
                        type=str,
                        help='out dir')


    args = parser.parse_args()

    # Parse pipeline config
    output = args.output_dir
    is_training=True
    model_config, train_config, _, dataset_config = \
        config_builder.get_configs_from_pipeline_file(
            args.pipeline_config_path, is_training, output)

    # Overwrite data split
    dataset_config.data_split = args.data_split

    # Set CUDA device id
    os.environ['CUDA_VISIBLE_DEVICES'] = args.device

    train(model_config, train_config, dataset_config)
def main(args):
    model_config, _, eval_config, dataset_config = \
        config_builder.get_configs_from_pipeline_file(
            args.experiment_config_path, is_training=False,
            output_dir=args.output_dir)

    assert eval_config.do_eval_sin or eval_config.do_eval_ain, \
        "This code only supports repeated evaluation in eval_sin or eval_ain modes"
    if eval_config.do_eval_sin and eval_config.do_eval_ain:
        raise ValueError('only one mode can be executed: (eval_sin) or (eval_ain)')

    print('..Working on {}'.format(args.experiment_config_path))
    calc_avg_scores(args.output_dir,model_config,eval_config,dataset_config,args.data_split)
    
    print('..Working on {} (iou05)'.format(args.experiment_config_path))
    calc_avg_scores(args.output_dir,model_config,eval_config,dataset_config,args.data_split,iou05=True)
예제 #10
0
def set_up_model_train_mode(pipeline_config_path, data_split):
    """Returns the model and its train_op."""

    model_config, train_config, _,  dataset_config = \
        config_builder.get_configs_from_pipeline_file(
            pipeline_config_path, is_training=True)

    dataset = DatasetBuilder.build_kitti_dataset(dataset_config,
                                                 use_defaults=False)

    model_name = model_config.model_name
    if model_name == 'rpn_model':
        model = RpnModel(model_config,
                         train_val_test=data_split,
                         dataset=dataset)
    elif model_name == 'avod_model':
        model = AvodModel(model_config,
                          train_val_test=data_split,
                          dataset=dataset)
    elif model_name == 'avod_ssd_model':
        model = AvodSSDModel(model_config,
                             train_val_test=data_split,
                             dataset=dataset)
    else:
        raise ValueError('Invalid model_name')

    prediction_dict = model.build()
    losses_dict, total_loss = model.loss(prediction_dict)

    # These parameters are required to set up the optimizer
    global_summaries = set([])
    global_step_tensor = tf.Variable(0, trainable=False)
    training_optimizer = optimizer_builder.build(train_config.optimizer,
                                                 global_summaries,
                                                 global_step_tensor)

    # Set up the train op
    train_op = slim.learning.create_train_op(total_loss, training_optimizer)

    return model, train_op
예제 #11
0
def main(_):
    parser = argparse.ArgumentParser()

    default_pipeline_config_path = avod.root_dir() + \
        '/configs/avod_cars_example.config'

    parser.add_argument('--pipeline_config',
                        type=str,
                        dest='pipeline_config_path',
                        default=default_pipeline_config_path,
                        help='Path to the pipeline config')

    parser.add_argument('--data_split',
                        type=str,
                        dest='data_split',
                        default='val',
                        help='Data split for evaluation')

    parser.add_argument('--device',
                        type=str,
                        dest='device',
                        default='0',
                        help='CUDA device id')

    args = parser.parse_args()

    # Parse pipeline config
    model_config, _, eval_config, dataset_config = \
        config_builder.get_configs_from_pipeline_file(
            args.pipeline_config_path,
            is_training=False)

    # Overwrite data split
    dataset_config.data_split = args.data_split

    # Set CUDA device id
    os.environ['CUDA_VISIBLE_DEVICES'] = args.device

    evaluate(model_config, eval_config, dataset_config)
예제 #12
0
def set_up_model_test_mode(pipeline_config_path, data_split):
    """Returns the model and its config in test mode."""

    model_config, _, _,  dataset_config = \
        config_builder.get_configs_from_pipeline_file(
            pipeline_config_path, is_training=False)

    dataset = DatasetBuilder.build_kitti_dataset(dataset_config,
                                                 use_defaults=False)

    # Overwrite the defaults
    dataset_config = config_builder.proto_to_obj(dataset_config)

    # Use the validation set
    dataset_config.data_split = data_split
    dataset_config.data_split_dir = 'training'
    if data_split == 'test':
        dataset_config.data_split_dir = 'testing'

    # Remove augmentation when in test mode
    dataset_config.aug_list = []

    # Build the dataset object
    dataset = DatasetBuilder.build_kitti_dataset(dataset_config,
                                                 use_defaults=False)

    model_name = model_config.model_name
    if model_name == 'rpn_model':
        model = RpnModel(model_config, train_val_test='test', dataset=dataset)
    elif model_name == 'avod_model':
        model = AvodModel(model_config, train_val_test='test', dataset=dataset)
    elif model_name == 'avod_ssd_model':
        model = AvodSSDModel(model_config,
                             train_val_test='test',
                             dataset=dataset)
    else:
        raise ValueError('Invalid model_name')

    return model, model_config
def main():
    parser = argparse.ArgumentParser()

    # Example usage
    # --checkpoint_name='avod_exp_example'
    # --base_dir='/home/<username>/GTAData/'

    parser.add_argument('--checkpoint_name',
                        type=str,
                        dest='checkpoint_name',
                        required=True,
                        help='Checkpoint name must be specified as a str\
                        and must match the experiment config file name.')

    parser.add_argument('--base_dir',
                        type=str,
                        dest='base_dir',
                        required=True,
                        help='Base data directory must be specified')

    args = parser.parse_args()
    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)

    experiment_config = args.checkpoint_name + '.config'

    # Read the config from the experiment folder
    experiment_config_path = avod.root_dir() + '/data/outputs/' +\
        args.checkpoint_name + '/' + experiment_config

    model_config, _, eval_config, dataset_config = \
        config_builder.get_configs_from_pipeline_file(
            experiment_config_path, is_training=False)

    filter_gt_labels(dataset_config, args.base_dir)
예제 #14
0
def infer_main(checkpoint_name,
               ckpt_indices,
               additional_cls,
               start_perspective=0):
    experiment_config = checkpoint_name + '.config'

    # Read the config from the experiment folder
    experiment_config_path = avod.root_dir() + '/data/outputs/' +\
        checkpoint_name + '/' + experiment_config

    model_config, _, eval_config, dataset_config = \
        config_builder.get_configs_from_pipeline_file(
            experiment_config_path, is_training=False)

    base_dir = os.path.split(cfg.DATASET_DIR)[0] + '/'

    os.environ['CUDA_VISIBLE_DEVICES'] = cfg.CUDA_DEVICE
    inference(model_config,
              eval_config,
              dataset_config,
              base_dir,
              ckpt_indices,
              additional_cls,
              start_perspective=start_perspective)
예제 #15
0
def main():
    """This demo shows RPN proposals and AVOD predictions in the
    3D point cloud.

    Keys:
        F1: Toggle proposals
        F2: Toggle predictions
        F3: Toggle 3D voxel grid
        F4: Toggle point cloud

        F5: Toggle easy ground truth objects (Green)
        F6: Toggle medium ground truth objects (Orange)
        F7: Toggle hard ground truth objects (Red)
        F8: Toggle all ground truth objects (default off)

        F9: Toggle ground slice filter (default off)
        F10: Toggle offset slice filter (default off)
    """

    ##############################
    # Options
    ##############################
    rpn_score_threshold = 0.1
    avod_score_threshold = 0.1

    proposals_line_width = 1.0
    predictions_line_width = 3.0
    show_orientations = True

    point_cloud_source = 'depth'

    # Config file folder, default (<avod_root>/data/outputs/<checkpoint_name>)
    config_dir = None

    checkpoint_name = 'pyramid_cars_with_aug_example'
    global_step = None  # Latest checkpoint
    global_step = 83000

    #data_split = 'val_half'
    data_split = 'val'
    # data_split = 'test'

    # Show 3D iou text
    draw_ious_3d = True

    name_list =[]


    #name_file = '/media/wavelab/d3cd89ab-7705-4996-94f3-01da25ba8f50/moosey/val.txt'

    #with open(name_file) as f:
        #for line in f:
            #newline = line.replace("\n","")
            #name_list.append(newline)


    #name_list =['0000000003','0000000009','0000000016','0000000233','0000000234','0000000236','0000000422','0000000473','0000000490','0000000494','0000000547','0000000655',\
                #'0000000679','0000000690','0000000692','0000000781']
    name_list =['0000000004']

    for names in name_list:

        sample_name = names
        #sample_name = None

        # # # Cars # # #
        # sample_name = '000050'
        # sample_name = '000104'
        # sample_name = '000169'
        # sample_name = '000191'
        # sample_name = '000360'
        # sample_name = '001783'
        # sample_name = '001820'

        # val split
        # sample_name = '000181'
        # sample_name = '000751'
        # sample_name = '000843'
        # sample_name = '000944'
        # sample_name = '006338'

        # # # People # # #
        # val_half split
        # sample_name = '000001'  # Hard, 1 far cyc
        # sample_name = '000005'  # Easy, 1 ped
        # sample_name = '000122'  # Easy, 1 cyc
        # sample_name = '000134'  # Hard, lots of people
        # sample_name = '000167'  # Medium, 1 ped, 2 cycs
        # sample_name = '000187'  # Medium, 1 ped on left
        # sample_name = '000381'  # Easy, 1 ped
        # sample_name = '000398'  # Easy, 1 ped
        # sample_name = '000401'  # Hard, obscured peds
        # sample_name = '000407'  # Easy, 1 ped
        # sample_name = '000448'  # Hard, several far people
        # sample_name = '000486'  # Hard 2 obscured peds
        # sample_name = '000509'  # Easy, 1 ped
        # sample_name = '000718'  # Hard, lots of people
        # sample_name = '002216'  # Easy, 1 cyc

        # val split
        # sample_name = '000015'
        # sample_name = '000048'
        # sample_name = '000058'
        # sample_name = '000076'    # Medium, few ped, 1 cyc
        # sample_name = '000108'
        # sample_name = '000118'
        # sample_name = '000145'
        # sample_name = '000153'
        # sample_name = '000186'
        # sample_name = '000195'
        # sample_name = '000199'
        # sample_name = '000397'
        # sample_name = '004425'
        # sample_name = '004474'    # Hard, many ped, 1 cyc
        # sample_name = '004657'    # Hard, Few cycl, few ped
        # sample_name = '006071'
        # sample_name = '006828'    # Hard, Few cycl, few ped
        # sample_name = '006908'    # Hard, Few cycl, few ped
        # sample_name = '007412'
        # sample_name = '007318'    # Hard, Few cycl, few ped

        ##############################
        # End of Options
        ##############################

        if data_split == 'test':
            draw_ious_3d = False

        if config_dir is None:
            config_dir = avod.root_dir() + '/data/outputs/' + checkpoint_name

        # Parse experiment config
        pipeline_config_file = \
            config_dir + '/' + checkpoint_name + '.config'
        _, _, _, dataset_config = \
            config_builder_util.get_configs_from_pipeline_file(
                pipeline_config_file, is_training=False)

        dataset_config.data_split = data_split

        if data_split == 'test':
            dataset_config.data_split_dir = 'testing'
            dataset_config.has_labels = False

        dataset = DatasetBuilder.build_kitti_dataset(dataset_config,
                                                     use_defaults=False)

        # Random sample
        if sample_name is None:
            sample_idx = np.random.randint(0, dataset.num_samples)
            sample_name = dataset.sample_names[sample_idx]

        ##############################
        # Setup Paths
        ##############################
        img_idx = int(sample_name)

        # Text files directory
        proposals_and_scores_dir = avod.root_dir() + \
            '/data/outputs/' + checkpoint_name + '/predictions' +  \
            '/proposals_and_scores/' + dataset.data_split

        predictions_and_scores_dir = avod.root_dir() + \
            '/data/outputs/' + checkpoint_name + '/predictions' +  \
            '/final_predictions_and_scores/' + dataset.data_split

        # Get checkpoint step
        steps = os.listdir(proposals_and_scores_dir)
        steps.sort(key=int)
        print('Available steps: {}'.format(steps))

        # Use latest checkpoint if no index provided
        if global_step is None:
            global_step = steps[-1]

        # Output images directory
        img_out_dir = avod.root_dir() + '/data/outputs/' + checkpoint_name + \
            '/predictions/images_3d/{}/{}/{}'.format(dataset.data_split,
                                                     global_step,
                                                     rpn_score_threshold)

        if not os.path.exists(img_out_dir):
            os.makedirs(img_out_dir)

        ##############################
        # Proposals
        ##############################
        # Load proposals from files
        proposals_and_scores = np.loadtxt(proposals_and_scores_dir +
                                          "/{}/{}.txt".format(global_step,
                                                              sample_name))

        proposals = proposals_and_scores[:, 0:7]
        proposal_scores = proposals_and_scores[:, 7]

        rpn_score_mask = proposal_scores > rpn_score_threshold

        proposals = proposals[rpn_score_mask]
        proposal_scores = proposal_scores[rpn_score_mask]
        print('Proposals:', len(proposal_scores), proposal_scores)

        proposal_objs = \
            [box_3d_encoder.box_3d_to_object_label(proposal,
                                                   obj_type='Proposal')
             for proposal in proposals]

        ##############################
        # Predictions
        ##############################
        # Load proposals from files
        predictions_and_scores = np.loadtxt(predictions_and_scores_dir +
                                            "/{}/{}.txt".format(
                                                global_step,
                                                sample_name)).reshape(-1, 9)

        prediction_boxes_3d = predictions_and_scores[:, 0:7]
        prediction_scores = predictions_and_scores[:, 7]
        prediction_types = np.asarray(predictions_and_scores[:, 8], dtype=np.int32)

        avod_score_mask = prediction_scores >= avod_score_threshold
        prediction_boxes_3d = prediction_boxes_3d[avod_score_mask]
        prediction_scores = prediction_scores[avod_score_mask]
        print('Predictions: ', len(prediction_scores), prediction_scores)

        final_predictions = np.copy(prediction_boxes_3d)

        # # Swap l, w for predictions where w > l
        # swapped_indices = predictions[:, 4] > predictions[:, 3]
        # final_predictions[swapped_indices, 3] = predictions[swapped_indices, 4]
        # final_predictions[swapped_indices, 4] = predictions[swapped_indices, 3]

        prediction_objs = []
        for pred_idx in range(len(final_predictions)):
            prediction_box_3d = final_predictions[pred_idx]
            prediction_type = dataset.classes[prediction_types[pred_idx]]
            prediction_obj = box_3d_encoder.box_3d_to_object_label(
                prediction_box_3d, obj_type=prediction_type)
            prediction_objs.append(prediction_obj)

        ##############################
        # Ground Truth
        ##############################
        if dataset.has_labels:
            # Get ground truth labels
            easy_gt_objs, medium_gt_objs, \
                hard_gt_objs, all_gt_objs = \
                demo_utils.get_gts_based_on_difficulty(dataset, img_idx)
        else:
            easy_gt_objs = medium_gt_objs = hard_gt_objs = all_gt_objs = []

        ##############################
        # 3D IoU
        ##############################
        if draw_ious_3d:
            # Convert to box_3d
            all_gt_boxes_3d = [box_3d_encoder.object_label_to_box_3d(gt_obj)
                               for gt_obj in all_gt_objs]
            pred_boxes_3d = [box_3d_encoder.object_label_to_box_3d(pred_obj)
                             for pred_obj in prediction_objs]
            max_ious_3d = demo_utils.get_max_ious_3d(all_gt_boxes_3d,
                                                     pred_boxes_3d)

        ##############################
        # Point Cloud
        ##############################
        image_path = dataset.get_rgb_image_path(sample_name)
        image = cv2.imread(image_path)

        print("***************")
        print(point_cloud_source)
        print(img_idx)
        print(image.shape)

        point_cloud = dataset.kitti_utils.get_point_cloud(point_cloud_source,
                                                          img_idx,
                                                          image_shape=image.shape)


        print("This is the shape of the point_cloud")
        print(point_cloud.shape)
        point_cloud = np.asarray(point_cloud)

        # Filter point cloud to extents
        area_extents = np.asarray([[-40, 40], [-5, 3], [0, 70]])
        bev_extents = area_extents[[0, 2]]

        points = point_cloud.T
        point_filter = obj_utils.get_point_filter(point_cloud, area_extents)
        points = points[point_filter]

        point_colours = vis_utils.project_img_to_point_cloud(points,
                                                             image,
                                                             dataset.calib_dir,
                                                             img_idx)

        # Voxelize the point cloud for visualization
        voxel_grid = VoxelGrid()
        voxel_grid.voxelize(points, voxel_size=0.1,
                            create_leaf_layout=False)

        # Ground plane
        ground_plane = obj_utils.get_road_plane(img_idx, dataset.planes_dir)

        ##############################
        # Visualization
        ##############################
        # Create VtkVoxelGrid
        vtk_voxel_grid = VtkVoxelGrid()
        vtk_voxel_grid.set_voxels(voxel_grid)

        vtk_point_cloud = VtkPointCloud()
        vtk_point_cloud.set_points(points, point_colours)

        # Create VtkAxes
        vtk_axes = vtk.vtkAxesActor()
        vtk_axes.SetTotalLength(5, 5, 5)

        # Create VtkBoxes for proposal boxes
        vtk_proposal_boxes = VtkBoxes()
        vtk_proposal_boxes.set_line_width(proposals_line_width)
        vtk_proposal_boxes.set_objects(proposal_objs,
                                       COLOUR_SCHEME_PREDICTIONS)

        # Create VtkBoxes for prediction boxes
        vtk_prediction_boxes = VtkPyramidBoxes()
        vtk_prediction_boxes.set_line_width(predictions_line_width)
        vtk_prediction_boxes.set_objects(prediction_objs,
                                         COLOUR_SCHEME_PREDICTIONS,
                                         show_orientations)

        # Create VtkBoxes for ground truth
        vtk_hard_gt_boxes = VtkBoxes()
        vtk_medium_gt_boxes = VtkBoxes()
        vtk_easy_gt_boxes = VtkBoxes()
        vtk_all_gt_boxes = VtkBoxes()

        vtk_hard_gt_boxes.set_objects(hard_gt_objs, COLOUR_SCHEME_PREDICTIONS,
                                      show_orientations)
        vtk_medium_gt_boxes.set_objects(medium_gt_objs, COLOUR_SCHEME_PREDICTIONS,
                                        show_orientations)
        vtk_easy_gt_boxes.set_objects(easy_gt_objs, COLOUR_SCHEME_PREDICTIONS,
                                      show_orientations)
        vtk_all_gt_boxes.set_objects(all_gt_objs, VtkBoxes.COLOUR_SCHEME_KITTI,
                                     show_orientations)

        # Create VtkTextLabels for 3D ious
        vtk_text_labels = VtkTextLabels()

        if draw_ious_3d and len(all_gt_boxes_3d) > 0:
            gt_positions_3d = np.asarray(all_gt_boxes_3d)[:, 0:3]
            vtk_text_labels.set_text_labels(
                gt_positions_3d,
                ['{:0.3f}'.format(iou_3d) for iou_3d in max_ious_3d])

        # Create VtkGroundPlane
        vtk_ground_plane = VtkGroundPlane()
        vtk_slice_bot_plane = VtkGroundPlane()
        vtk_slice_top_plane = VtkGroundPlane()

        vtk_ground_plane.set_plane(ground_plane, bev_extents)
        vtk_slice_bot_plane.set_plane(ground_plane + [0, 0, 0, -0.2], bev_extents)
        vtk_slice_top_plane.set_plane(ground_plane + [0, 0, 0, -2.0], bev_extents)

        # Create Voxel Grid Renderer in bottom half
        vtk_renderer = vtk.vtkRenderer()
        vtk_renderer.AddActor(vtk_voxel_grid.vtk_actor)
        vtk_renderer.AddActor(vtk_point_cloud.vtk_actor)

        vtk_renderer.AddActor(vtk_proposal_boxes.vtk_actor)
        vtk_renderer.AddActor(vtk_prediction_boxes.vtk_actor)

        vtk_renderer.AddActor(vtk_hard_gt_boxes.vtk_actor)
        vtk_renderer.AddActor(vtk_medium_gt_boxes.vtk_actor)
        vtk_renderer.AddActor(vtk_easy_gt_boxes.vtk_actor)
        vtk_renderer.AddActor(vtk_all_gt_boxes.vtk_actor)

        vtk_renderer.AddActor(vtk_text_labels.vtk_actor)

        # Add ground plane and slice planes
        vtk_renderer.AddActor(vtk_ground_plane.vtk_actor)
        vtk_renderer.AddActor(vtk_slice_bot_plane.vtk_actor)
        vtk_renderer.AddActor(vtk_slice_top_plane.vtk_actor)

        vtk_renderer.AddActor(vtk_axes)
        vtk_renderer.SetBackground(0.2, 0.3, 0.4)

        # Set initial properties for some actors
        vtk_point_cloud.vtk_actor.GetProperty().SetPointSize(3)
        vtk_proposal_boxes.vtk_actor.SetVisibility(0)
        vtk_voxel_grid.vtk_actor.SetVisibility(0)
        vtk_all_gt_boxes.vtk_actor.SetVisibility(0)

        vtk_ground_plane.vtk_actor.SetVisibility(0)
        vtk_slice_bot_plane.vtk_actor.SetVisibility(0)
        vtk_slice_top_plane.vtk_actor.SetVisibility(0)
        vtk_ground_plane.vtk_actor.GetProperty().SetOpacity(0.9)
        vtk_slice_bot_plane.vtk_actor.GetProperty().SetOpacity(0.9)
        vtk_slice_top_plane.vtk_actor.GetProperty().SetOpacity(0.9)

        # Setup Camera
        current_cam = vtk_renderer.GetActiveCamera()
        current_cam.Pitch(140.0)
        current_cam.Roll(180.0)

        # Zooms out to fit all points on screen
        vtk_renderer.ResetCamera()
        # Zoom in slightly
        current_cam.Zoom(2)

        # Reset the clipping range to show all points
        vtk_renderer.ResetCameraClippingRange()

        # Setup Render Window
        vtk_render_window = vtk.vtkRenderWindow()
        vtk_render_window.SetWindowName(
            "Predictions: Step {}, Sample {}, Min Score {}".format(
                global_step,
                sample_name,
                avod_score_threshold,
            ))
        vtk_render_window.SetSize(900, 600)
        vtk_render_window.AddRenderer(vtk_renderer)

        # Setup custom interactor style, which handles mouse and key events
        vtk_render_window_interactor = vtk.vtkRenderWindowInteractor()
        vtk_render_window_interactor.SetRenderWindow(vtk_render_window)

        # Add custom interactor to toggle actor visibilities
        custom_interactor = vis_utils.CameraInfoInteractorStyle([
            vtk_proposal_boxes.vtk_actor,
            vtk_prediction_boxes.vtk_actor,
            vtk_voxel_grid.vtk_actor,
            vtk_point_cloud.vtk_actor,

            vtk_easy_gt_boxes.vtk_actor,
            vtk_medium_gt_boxes.vtk_actor,
            vtk_hard_gt_boxes.vtk_actor,
            vtk_all_gt_boxes.vtk_actor,

            vtk_ground_plane.vtk_actor,
            vtk_slice_bot_plane.vtk_actor,
            vtk_slice_top_plane.vtk_actor,
            vtk_text_labels.vtk_actor,
        ])

        vtk_render_window_interactor.SetInteractorStyle(custom_interactor)
        # Render in VTK
        vtk_render_window.Render()

        # Take a screenshot
        window_to_image_filter = vtk.vtkWindowToImageFilter()
        window_to_image_filter.SetInput(vtk_render_window)
        window_to_image_filter.Update()

        png_writer = vtk.vtkPNGWriter()
        file_name = img_out_dir + "/{}.png".format(sample_name)
        png_writer.SetFileName(file_name)
        png_writer.SetInputData(window_to_image_filter.GetOutput())
        png_writer.Write()

        print('Screenshot saved to ', file_name)

        #vtk_render_window_interactor.Start()  # Blocking


        vtk_render_window_interactor.Initialize()   # Non-Blocking
예제 #16
0
def main():
    """ Converts a set of network predictions into text files required for
    KITTI evaluation.
    """

    ##############################
    # Options
    ##############################
    checkpoint_name = 'fpn_people_dual_NHSP_train'#'fpn_people_dual_SHPL_train'#'pyramid_people_with_NHSP_example_train'#'pyramid_people_with_NHSP_example'

    data_split = 'val'#'test'#'val'

    global_steps = None
    # global_steps = [28000, 19000, 33000, 34000]

    score_threshold = 0.1

    save_2d = False  # Save 2D predictions
    save_3d = True   # Save 2D and 3D predictions together
    save_alphas = True  # Save alphas (observation angles)

    # Checkpoints below this are skipped
    min_step = 20000

    ##############################
    # End of Options
    ##############################

    # Parse experiment config
    pipeline_config_file = \
        avod.root_dir() + '/data/outputs/' + checkpoint_name + \
        '/' + checkpoint_name + '.config'
    _, _, _, dataset_config = \
        config_builder_util.get_configs_from_pipeline_file(
            pipeline_config_file, is_training=False)

    # Overwrite defaults
    dataset_config = config_builder_util.proto_to_obj(dataset_config)
    dataset_config.data_split = data_split
    dataset_config.aug_list = []

    if data_split == 'test':
        dataset_config.data_split_dir = 'testing'

    dataset = DatasetBuilder.build_kitti_dataset(dataset_config,
                                                 use_defaults=False)

    # Get available prediction folders
    predictions_root_dir = avod.root_dir() + '/data/outputs/' + \
        checkpoint_name + '/predictions'

    final_predictions_root_dir = predictions_root_dir + \
        '/final_predictions_and_scores/' + dataset.data_split

    print('Converting detections from', final_predictions_root_dir)

    if not global_steps:
        global_steps = os.listdir(final_predictions_root_dir)
        global_steps.sort(key=int)
        print('Checkpoints found ', global_steps)

    for step_idx in range(len(global_steps)):

        global_step = global_steps[step_idx]

        # Skip first checkpoint
        if int(global_step) < min_step:
            continue

        final_predictions_dir = final_predictions_root_dir + \
            '/' + str(global_step)

        # 2D and 3D prediction directories
        kitti_predictions_2d_dir = predictions_root_dir + \
            '/kitti_predictions_2d/' + \
            dataset.data_split + '/' + \
            str(score_threshold) + '/' + \
            str(global_step) + '/data'
        kitti_predictions_3d_dir = predictions_root_dir + \
            '/kitti_predictions_3d/' + \
            dataset.data_split + '/' + \
            str(score_threshold) + '/' + \
            str(global_step) + '/data'

        if save_2d and not os.path.exists(kitti_predictions_2d_dir):
            os.makedirs(kitti_predictions_2d_dir)
        if save_3d and not os.path.exists(kitti_predictions_3d_dir):
            os.makedirs(kitti_predictions_3d_dir)

        # Do conversion
        num_samples = dataset.num_samples
        num_valid_samples = 0

        print('\nGlobal step:', global_step)
        print('Converting detections from:', final_predictions_dir)

        if save_2d:
            print('2D Detections saved to:', kitti_predictions_2d_dir)
        if save_3d:
            print('3D Detections saved to:', kitti_predictions_3d_dir)

        for sample_idx in range(num_samples):

            # Print progress
            sys.stdout.write('\rConverting {} / {}'.format(
                sample_idx + 1, num_samples))
            sys.stdout.flush()

            sample_name = dataset.sample_names[sample_idx]

            prediction_file = sample_name + '.txt'

            kitti_predictions_2d_file_path = kitti_predictions_2d_dir + \
                '/' + prediction_file
            kitti_predictions_3d_file_path = kitti_predictions_3d_dir + \
                '/' + prediction_file

            predictions_file_path = final_predictions_dir + \
                '/' + prediction_file

            # If no predictions, skip to next file
            if not os.path.exists(predictions_file_path):
                if save_2d:
                    np.savetxt(kitti_predictions_2d_file_path, [])
                if save_3d:
                    np.savetxt(kitti_predictions_3d_file_path, [])
                continue

            all_predictions = np.loadtxt(predictions_file_path)

            # # Swap l, w for predictions where w > l
            # swapped_indices = all_predictions[:, 4] > all_predictions[:, 3]
            # fixed_predictions = np.copy(all_predictions)
            # fixed_predictions[swapped_indices, 3] = all_predictions[
            #     swapped_indices, 4]
            # fixed_predictions[swapped_indices, 4] = all_predictions[
            #     swapped_indices, 3]

            score_filter = all_predictions[:, 7] >= score_threshold
            all_predictions = all_predictions[score_filter]

            # If no predictions, skip to next file
            if len(all_predictions) == 0:
                if save_2d:
                    np.savetxt(kitti_predictions_2d_file_path, [])
                if save_3d:
                    np.savetxt(kitti_predictions_3d_file_path, [])
                continue

            # Project to image space
            sample_name = prediction_file.split('.')[0]
            img_idx = int(sample_name)

            # Load image for truncation
            image = Image.open(dataset.get_rgb_image_path(sample_name))

            stereo_calib_p2 = calib_utils.read_calibration(dataset.calib_dir,
                                                           img_idx).p2

            boxes = []
            image_filter = []
            for i in range(len(all_predictions)):
                box_3d = all_predictions[i, 0:7]
                img_box = box_3d_projector.project_to_image_space(
                    box_3d, stereo_calib_p2,
                    truncate=True, image_size=image.size)

                # Skip invalid boxes (outside image space)
                if img_box is None:
                    image_filter.append(False)
                else:
                    image_filter.append(True)
                    boxes.append(img_box)

            boxes = np.asarray(boxes)
            all_predictions = all_predictions[image_filter]

            # If no predictions, skip to next file
            if len(boxes) == 0:
                if save_2d:
                    np.savetxt(kitti_predictions_2d_file_path, [])
                if save_3d:
                    np.savetxt(kitti_predictions_3d_file_path, [])
                continue

            num_valid_samples += 1

            # To keep each value in its appropriate position, an array of zeros
            # (N, 16) is allocated but only values [4:16] are used
            kitti_predictions = np.zeros([len(boxes), 16])

            # Get object types
            all_pred_classes = all_predictions[:, 8].astype(np.int32)
            obj_types = [dataset.classes[class_idx]
                         for class_idx in all_pred_classes]

            # Truncation and Occlusion are always empty (see below)

            # Alpha
            if not save_alphas:
                kitti_predictions[:, 3] = -10 * \
                    np.ones((len(kitti_predictions)), dtype=np.int32)
            else:
                alphas = all_predictions[:, 6] - \
                    np.arctan2(all_predictions[:, 0], all_predictions[:, 2])
                kitti_predictions[:, 3] = alphas

            # 2D predictions
            kitti_predictions[:, 4:8] = boxes[:, 0:4]

            # 3D predictions
            # (l, w, h)
            kitti_predictions[:, 8] = all_predictions[:, 5]
            kitti_predictions[:, 9] = all_predictions[:, 4]
            kitti_predictions[:, 10] = all_predictions[:, 3]
            # (x, y, z)
            kitti_predictions[:, 11:14] = all_predictions[:, 0:3]
            # (ry, score)
            kitti_predictions[:, 14:16] = all_predictions[:, 6:8]

            # Round detections to 3 decimal places
            kitti_predictions = np.round(kitti_predictions, 3)

            # Empty Truncation, Occlusion
            kitti_empty_1 = -1 * np.ones((len(kitti_predictions), 2),
                                         dtype=np.int32)
            # Empty 3D (x, y, z)
            kitti_empty_2 = -1 * np.ones((len(kitti_predictions), 3),
                                         dtype=np.int32)
            # Empty 3D (h, w, l)
            kitti_empty_3 = -1000 * np.ones((len(kitti_predictions), 3),
                                            dtype=np.int32)
            # Empty 3D (ry)
            kitti_empty_4 = -10 * np.ones((len(kitti_predictions), 1),
                                          dtype=np.int32)

            # Stack 2D predictions text
            kitti_text_2d = np.column_stack([obj_types,
                                             kitti_empty_1,
                                             kitti_predictions[:, 3:8],
                                             kitti_empty_2,
                                             kitti_empty_3,
                                             kitti_empty_4,
                                             kitti_predictions[:, 15]])

            # Stack 3D predictions text
            kitti_text_3d = np.column_stack([obj_types,
                                             kitti_empty_1,
                                             kitti_predictions[:, 3:16]])

            # Save to text files
            if save_2d:
                np.savetxt(kitti_predictions_2d_file_path, kitti_text_2d,
                           newline='\r\n', fmt='%s')
            if save_3d:
                np.savetxt(kitti_predictions_3d_file_path, kitti_text_3d,
                           newline='\r\n', fmt='%s')

        print('\nNum valid:', num_valid_samples)
        print('Num samples:', num_samples)
예제 #17
0
def inference(rpn_model_path, detect_model_path, avod_config_path):
    model_config, _, eval_config, dataset_config = \
    config_builder.get_configs_from_pipeline_file(
        avod_config_path, is_training=False)

    # Setup the model
    model_name = model_config.model_name
    # Overwrite repeated field
    model_config = config_builder.proto_to_obj(model_config)
    # Switch path drop off during evaluation
    model_config.path_drop_probabilities = [1.0, 1.0]

    dataset = get_dataset(dataset_config, 'val')

    # run avod proposal network
    rpn_endpoints, sess1, rpn_model = get_proposal_network(model_config, dataset, rpn_model_path)
    end_points, sess2 = get_detection_network(detect_model_path)

    all_prediction = []
    all_id_list = None
    all_2d_boxes = []
    for idx in range(3769):
        feed_dict1 = rpn_model.create_feed_dict()
        kitti_samples = dataset.load_samples([idx])
        sample = kitti_samples[0]
        '''
        if sample[constants.KEY_SAMPLE_NAME] < '001100':
            continue
        if sample[constants.KEY_SAMPLE_NAME] > '001200':
            break
        '''
        start_time = time.time()
        rpn_predictions = sess1.run(rpn_endpoints, feed_dict=feed_dict1)
        top_anchors = rpn_predictions[RpnModel.PRED_TOP_ANCHORS]
        top_proposals = box_3d_encoder.anchors_to_box_3d(top_anchors)
        softmax_scores = rpn_predictions[RpnModel.PRED_TOP_OBJECTNESS_SOFTMAX]

        proposals_and_scores = np.column_stack((top_proposals,
                                                softmax_scores))
        top_img_roi = rpn_predictions[RpnModel.PRED_TOP_IMG_ROI]
        top_bev_roi = rpn_predictions[RpnModel.PRED_TOP_BEV_ROI]
        roi_num = len(top_img_roi)
        top_img_roi = np.reshape(top_img_roi, (roi_num, -1))
        top_bev_roi = np.reshape(top_bev_roi, (roi_num, -1))
        roi_features = np.column_stack((top_img_roi, top_bev_roi))
        '''
        # save proposal
        if os.path.exists(os.path.join('/data/ssd/public/jlliu/Kitti/object/training/proposal', '%s.txt'%(sample[constants.KEY_SAMPLE_NAME]))):
            continue
        np.savetxt(os.path.join('./proposals_and_scores/', '%s.txt'%sample[constants.KEY_SAMPLE_NAME]), proposals_and_scores, fmt='%.3f')
        np.savetxt(os.path.join('./roi_features/', '%s_roi.txt'%sample[constants.KEY_SAMPLE_NAME]), roi_features, fmt='%.5f')
        print('save ' + sample[constants.KEY_SAMPLE_NAME])
        '''
        # run frustum_pointnets_v2
        point_clouds, feature_vec, rot_angle_list, prop_cls_labels = get_pointnet_input(sample, proposals_and_scores, roi_features)
        try:
            prediction = detect_batch(sess2, end_points, point_clouds, feature_vec, rot_angle_list, prop_cls_labels)
        except:
            traceback.print_exc()
            continue

        elapsed_time = time.time() - start_time
        print(sample[constants.KEY_SAMPLE_NAME], elapsed_time)
        # concat all predictions for kitti eval
        id_list = np.ones((len(prediction),)) * int(sample[constants.KEY_SAMPLE_NAME])
        if all_id_list is None:
            all_id_list = id_list
        else:
            all_id_list = np.concatenate((all_id_list, id_list), axis=0)
        for pred in prediction:
            obj = box_3d_encoder.box_3d_to_object_label(np.array(pred[0:7]), obj_type=type_whitelist[pred[8]])
            corners = compute_box_3d(obj)
            projected = calib_utils.project_to_image(corners.T, sample[constants.KEY_STEREO_CALIB_P2])
            x1 = np.amin(projected[0])
            y1 = np.amin(projected[1])
            x2 = np.amax(projected[0])
            y2 = np.amax(projected[1])
            all_2d_boxes.append([x1, y1, x2, y2])
        all_prediction += prediction
        # save result
        pickle.dump({'proposals_and_scores': proposals_and_scores, 'roi_features': roi_features}, open("rpn_out/%s"%sample[constants.KEY_SAMPLE_NAME], "wb"))
        pickle.dump(prediction, open('final_out/%s' % sample[constants.KEY_SAMPLE_NAME], 'wb'))
        visualize(dataset, sample, prediction)
    # for kitti eval
    write_detection_results('./detection_results', all_prediction, all_id_list, all_2d_boxes)
예제 #18
0
def main(_):
    parser = argparse.ArgumentParser()

    # Example usage
    # --checkpoint_name='avod_cars_example'
    # --data_split='test'
    # --ckpt_indices=50 100 112
    # Optional arg:
    # --device=0
    default_output_dir = '/data/kitti_avod/object/outputs'

    # parser.add_argument('--checkpoint_name',
    #                     type=str,
    #                     dest='checkpoint_name',
    #                     required=True,
    #                     help='Checkpoint name must be specified as a str\
    #                     and must match the experiment config file name.')

    parser.add_argument('--experiment_config',
                        type=str,
                        required=True,
                        dest='experiment_config_path',
                        help='Path to the experiment config must be specified')

    parser.add_argument('--data_split',
                        type=str,
                        dest='data_split',
                        required=True,
                        help='Data split must be specified e.g. val or test')

    parser.add_argument('--ckpt_indices',
                        type=int,
                        nargs='+',
                        dest='ckpt_indices',
                        required=True,
                        help='Checkpoint indices must be a set of \
                        integers with space in between -> 0 10 20 etc')

    parser.add_argument('--device',
                        type=str,
                        dest='device',
                        default=None,
                        help='CUDA device id')

    parser.add_argument('--output_dir',
                        type=str,
                        dest='output_dir',
                        default=default_output_dir,
                        help='output dir to save checkpoints')

    parser.add_argument('--force_sin_input_name',
                        type=str,
                        dest='force_sin_input_name',
                        default=None,
                        help='force sin_input_name to run only for the given input')

    args = parser.parse_args()
    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)

    # experiment_config = args.checkpoint_name + '.config'

    # # Read the config from the experiment folder
    # experiment_config_path = avod.root_dir() + '/data/outputs/' +\
    #     args.checkpoint_name + '/' + experiment_config

    model_config, _, eval_config, dataset_config = \
        config_builder.get_configs_from_pipeline_file(
            args.experiment_config_path, is_training=False,
            output_dir=args.output_dir)

    if args.device:
        os.environ['CUDA_VISIBLE_DEVICES'] = args.device
    
    inference(model_config, eval_config,
              dataset_config, args.data_split,
              args.ckpt_indices,
              output_dir=args.output_dir,
              force_sin_input_name=args.force_sin_input_name)
예제 #19
0
def main(_):
    parser = argparse.ArgumentParser()

    # Example usage
    # --checkpoint_name='avod_exp_example'
    # --data_split='test'
    # --ckpt_indices=50 100 112
    # Optional arg:
    # --device=0
    # --additional_cls=False

    parser.add_argument('--checkpoint_name',
                        type=str,
                        dest='checkpoint_name',
                        required=True,
                        help='Checkpoint name must be specified as a str\
                        and must match the experiment config file name.')

    parser.add_argument('--base_dir',
                        type=str,
                        dest='base_dir',
                        required=True,
                        help='Base data directory must be specified')

    parser.add_argument('--ckpt_indices',
                        type=int,
                        nargs='+',
                        dest='ckpt_indices',
                        required=True,
                        help='Checkpoint indices must be a set of \
        integers with space in between -> 0 10 20 etc')

    parser.add_argument('--device',
                        type=str,
                        dest='device',
                        default='0',
                        help='CUDA device id')

    parser.add_argument('--additional_cls',
                        dest='additional_cls',
                        action='store_true',
                        default=False,
                        help='If detections are from an additional class\
                        i.e. another class has already been pre-processed.')

    args = parser.parse_args()
    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)

    experiment_config = args.checkpoint_name + '.config'

    # Read the config from the experiment folder
    experiment_config_path = avod.root_dir() + '/data/outputs/' +\
        args.checkpoint_name + '/' + experiment_config

    model_config, _, eval_config, dataset_config = \
        config_builder.get_configs_from_pipeline_file(
            experiment_config_path, is_training=False)

    os.environ['CUDA_VISIBLE_DEVICES'] = args.device
    inference(model_config, eval_config, dataset_config, args.base_dir,
              args.ckpt_indices, args.additional_cls)