import argparse import sys import ubelt import kwcoco from geowatch.utils import kwcoco_extensions def main(): parser = argparse.ArgumentParser( description="Concatenate KWCOCO datasets at the video level") parser.add_argument("--dst", type=str, help="Path to output KWCOCO dataset") parser.add_argument('src_kwcoco_datasets', type=str, nargs='+', help="Paths to input KWCOCO datasets to concatenate") concat_kwcoco_datasets(**vars(parser.parse_args())) def concat_kwcoco_datasets(src_kwcoco_datasets, dst): first, *rest = src_kwcoco_datasets out_dset = kwcoco.CocoDataset(first).copy() def _build_video_lookup(kwcoco_dset): video_metas = kwcoco_dset.videos().lookup(('id', 'name')) return dict(zip(video_metas['name'], video_metas['id'])) out_dset_videos_lookup = _build_video_lookup(out_dset) for dset_path in rest: out_dset_ids =\ list(ubelt.flatten(out_dset.videos().images.lookup('id'))) if len(out_dset_ids) > 0: next_id = max(out_dset_ids) else: next_id = 1 dset = kwcoco.CocoDataset(dset_path) dset_videos_lookup = _build_video_lookup(dset) for video_name, video_id in dset_videos_lookup.items(): if video_name in out_dset_videos_lookup: out_video_id = out_dset_videos_lookup[video_name] for image_group in dset.videos([video_id]).images: for image in image_group.objs: next_id += 1 image['id'] = next_id image['video_id'] = out_video_id out_dset.add_image(**image) else: out_dset.add_video(dset.videos([video_id])) # Ensure video frames are in the right order kwcoco_extensions.reorder_video_frames(out_dset) out_dset.dump(dst, indent=2, newlines=True) if __name__ == "__main__": sys.exit(main())