| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| """Script to generate test data for cityscapes.""" |
|
|
| import collections |
| import json |
| import os |
|
|
| from absl import app |
| from absl import flags |
| from absl import logging |
| import numpy as np |
| from PIL import Image |
| import tensorflow as tf |
|
|
| |
|
|
| from deeplab2.data import data_utils |
| from deeplab2.data import dataset |
|
|
| flags.DEFINE_string( |
| 'panoptic_annotation_path', |
| 'deeplab2/data/testdata/' |
| 'dummy_prediction.png', |
| 'Path to annotated test image with cityscapes encoding.') |
| flags.DEFINE_string( |
| 'panoptic_gt_output_path', |
| 'deeplab2/data/testdata/' |
| 'dummy_gt_for_vps.png', |
| 'Path to annotated test image with Video Panoptic Segmentation encoding.') |
| flags.DEFINE_string( |
| 'output_cityscapes_root', |
| 'deeplab2/data/testdata/', |
| 'Path to output root directory.') |
|
|
| FLAGS = flags.FLAGS |
|
|
| |
| _CITYSCAPES_IGNORE = 255 |
| |
| _CITYSCAPES_CAR = (13, 26) |
| _CITYSCAPES_TREE = (8, 21) |
| _CITYSCAPES_SKY = (10, 23) |
| _CITYSCAPES_BUILDING = (2, 11) |
| _CITYSCAPES_ROAD = (0, 7) |
|
|
| _IS_CROWD = 'is_crowd' |
| _NOT_CROWD = 'not_crowd' |
|
|
| _CLASS_HAS_INSTANCES_LIST = dataset.CITYSCAPES_PANOPTIC_INFORMATION.class_has_instances_list |
| _PANOPTIC_LABEL_DIVISOR = dataset.CITYSCAPES_PANOPTIC_INFORMATION.panoptic_label_divisor |
| _FILENAME_PREFIX = 'dummy_000000_000000' |
|
|
|
|
| def create_test_data(annotation_path): |
| """Creates cityscapes panoptic annotation, vps annotation and segment info. |
| |
| Our Video Panoptic Segmentation (VPS) encoding uses ID == semantic trainID * |
| 1000 + instance ID (starting at 1) with instance ID == 0 marking |
| crowd regions. |
| |
| Args: |
| annotation_path: The path to the annotation to be loaded. |
| |
| Returns: |
| A tuple of cityscape annotation, vps annotation and segment infos. |
| """ |
| |
|
|
| |
| |
| |
| panoptic_label_to_cityscapes_label = { |
| 0: (_CITYSCAPES_IGNORE, _NOT_CROWD), |
| 31110: (_CITYSCAPES_CAR, _NOT_CROWD), |
| 31354: (_CITYSCAPES_CAR, _IS_CROWD), |
| 35173: (_CITYSCAPES_CAR, _NOT_CROWD), |
| 488314: (_CITYSCAPES_CAR, _IS_CROWD), |
| 549788: (_CITYSCAPES_CAR, _IS_CROWD), |
| 1079689: (_CITYSCAPES_CAR, _IS_CROWD), |
| 1341301: (_CITYSCAPES_CAR, _NOT_CROWD), |
| 1544590: (_CITYSCAPES_CAR, _NOT_CROWD), |
| 1926498: (_CITYSCAPES_CAR, _NOT_CROWD), |
| 4218944: (_CITYSCAPES_TREE, _NOT_CROWD), |
| 4251840: (_CITYSCAPES_SKY, _NOT_CROWD), |
| 6959003: (_CITYSCAPES_BUILDING, _NOT_CROWD), |
| |
| 8396960: (_CITYSCAPES_BUILDING, _NOT_CROWD), |
| 8413312: (_CITYSCAPES_ROAD, _NOT_CROWD), |
| } |
| with tf.io.gfile.GFile(annotation_path, 'rb') as f: |
| panoptic = data_utils.read_image(f.read()) |
|
|
| |
| |
| panoptic = np.dot(panoptic, [1, 256, 256 * 256]) |
| |
| |
| |
| |
| cityscapes_panoptic = np.zeros_like(panoptic, dtype=np.int32) |
| |
| |
| |
| vps_panoptic = np.zeros_like(panoptic, dtype=np.int32) |
| num_instances_per_class = collections.defaultdict(int) |
| unique_labels = np.unique(panoptic) |
|
|
| |
| segments_info = {} |
| for label in unique_labels: |
| cityscapes_label, is_crowd = panoptic_label_to_cityscapes_label[label] |
| selected_pixels = panoptic == label |
|
|
| if cityscapes_label == _CITYSCAPES_IGNORE: |
| vps_panoptic[selected_pixels] = ( |
| _CITYSCAPES_IGNORE * _PANOPTIC_LABEL_DIVISOR) |
| continue |
|
|
| train_id, eval_id = tuple(cityscapes_label) |
| cityscapes_id = eval_id |
| vps_id = train_id * _PANOPTIC_LABEL_DIVISOR |
| if train_id in _CLASS_HAS_INSTANCES_LIST: |
| |
| if is_crowd != _IS_CROWD: |
| cityscapes_id = ( |
| eval_id * _PANOPTIC_LABEL_DIVISOR + |
| num_instances_per_class[train_id]) |
| |
| vps_id += num_instances_per_class[train_id] + 1 |
| num_instances_per_class[train_id] += 1 |
|
|
| cityscapes_panoptic[selected_pixels] = cityscapes_id |
| vps_panoptic[selected_pixels] = vps_id |
| pixel_area = int(np.sum(selected_pixels)) |
| if cityscapes_id in segments_info: |
| logging.info('Merging segments with label %d into segment %d', label, |
| cityscapes_id) |
| segments_info[cityscapes_id]['area'] += pixel_area |
| else: |
| segments_info[cityscapes_id] = { |
| 'area': pixel_area, |
| 'category_id': train_id, |
| 'id': cityscapes_id, |
| 'iscrowd': 1 if is_crowd == _IS_CROWD else 0, |
| } |
|
|
| cityscapes_panoptic = np.dstack([ |
| cityscapes_panoptic % 256, cityscapes_panoptic // 256, |
| cityscapes_panoptic // 256 // 256 |
| ]) |
| vps_panoptic = np.dstack( |
| [vps_panoptic % 256, vps_panoptic // 256, vps_panoptic // 256 // 256]) |
| return (cityscapes_panoptic.astype(np.uint8), vps_panoptic.astype(np.uint8), |
| list(segments_info.values())) |
|
|
|
|
| def main(argv): |
| if len(argv) > 1: |
| raise app.UsageError('Too many command-line arguments.') |
|
|
| data_path = FLAGS.panoptic_annotation_path |
| panoptic_map, vps_map, segments_info = create_test_data(data_path) |
| panoptic_map_filename = _FILENAME_PREFIX + '_gtFine_panoptic.png' |
| panoptic_map_path = os.path.join(FLAGS.output_cityscapes_root, 'gtFine', |
| 'cityscapes_panoptic_dummy_trainId', |
| panoptic_map_filename) |
|
|
| gt_output_path = FLAGS.panoptic_gt_output_path |
| with tf.io.gfile.GFile(gt_output_path, 'wb') as f: |
| Image.fromarray(vps_map).save(f, format='png') |
|
|
| panoptic_map_path = panoptic_map_path |
| with tf.io.gfile.GFile(panoptic_map_path, 'wb') as f: |
| Image.fromarray(panoptic_map).save(f, format='png') |
|
|
| json_annotation = { |
| 'annotations': [{ |
| 'file_name': _FILENAME_PREFIX + '_gtFine_panoptic.png', |
| 'image_id': _FILENAME_PREFIX, |
| 'segments_info': segments_info |
| }] |
| } |
| json_annotation_path = os.path.join(FLAGS.output_cityscapes_root, 'gtFine', |
| 'cityscapes_panoptic_dummy_trainId.json') |
| json_annotation_path = json_annotation_path |
| with tf.io.gfile.GFile(json_annotation_path, 'w') as f: |
| json.dump(json_annotation, f, indent=2) |
|
|
|
|
| if __name__ == '__main__': |
| app.run(main) |
|
|