diff --git a/README.md b/README.md index fc1aeeb..918ed66 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,10 @@ # Temporal Logic Video (TLV) Dataset -
-[![Contributors][contributors-shield]][contributors-url] -[![Forks][forks-shield]][forks-url] -[![Stargazers][stars-shield]][stars-url] -[![MIT License][license-shield]][license-url] -
+| [![Contributors][contributors-shield]][contributors-url] | [![Forks][forks-shield]][forks-url] | [![Stargazers][stars-shield]][stars-url] | [![MIT License][license-shield]][license-url] | +|:--:|:--:|:--:|:--:| + +## Overview
@@ -86,12 +84,42 @@ Each serialized object contains the following attributes: You can download a dataset from here. The structure of dataset is as follows: serializer ``` - ILSVRC/ - ├── Annotations/ - ├── Data/ - ├── ImageSets/ - └── LOC_synset_mapping.txt + tlv-dataset-v1/ + ├── tlv_real_dataset/ + ├──── prop1Uprop2/ + ├──── (prop1&prop2)Uprop3/ + ├── tlv_synthetic_dataset/ + ├──── Fprop1/ + ├──── Gprop1/ + ├──── prop1&prop2/ + ├──── prop1Uprop2/ + └──── (prop1&prop2)Uprop3/ ``` +#### Dataset Statistics +1. Total Number of Frames + +| Ground Truth TL Specifications | Synthetic TLV Dataset | | Real TLV Dataset | | +| --- | ---: | ---: | ---: | ---: | +| | COCO | ImageNet | Waymo | Nuscenes | +|---|---|---|---|---| +| Eventually Event A | - | 15,750 | - | - | +| Always Event A | - | 15,750 | - | - | +| Event A And Event B | 31,500 | - | - | - | +| Event A Until Event B | 15,750 | 15,750 | 8,736 | 19,808 | +| (Event A And Event B) Until Event C | 5,789 | - | 7,459 | 7,459 | + +2. Total Number of datasets + +| Ground Truth TL Specifications | Synthetic TLV Dataset | | Real TLV Dataset | | +| --- | ---: | ---: | ---: | ---: | +| | COCO | ImageNet | Waymo | Nuscenes | +|---|---|---|---|---| +| Eventually Event A | - | 60 | - | - | +| Always Event A | - | 60 | - | - | +| Event A And Event B | 120 | - | - | - | +| Event A Until Event B | 60| 60 | 45| 494 | +| (Event A And Event B) Until Event C | 97 | - | 30 | 186| + ## Installation diff --git a/run_scripts/run_synthetic_tlv_coco.py b/run_scripts/run_synthetic_tlv_coco.py index f93a460..d50a5bd 100644 --- a/run_scripts/run_synthetic_tlv_coco.py +++ b/run_scripts/run_synthetic_tlv_coco.py @@ -78,7 +78,9 @@ coco_image_source=args.coco_image_source, ) - TLV_generator = SyntheticTLVGenerator(dataloader=dataloader, save_dir=args.save_dir) + TLV_generator = SyntheticTLVGenerator( + dataloader=dataloader, save_dir=args.save_dir + ) if args.ltl_logic == "all": available_tl = [ diff --git a/run_scripts/run_synthetic_tlv_coco_until_long_horizon.py b/run_scripts/run_synthetic_tlv_coco_until_long_horizon.py index b69ef13..2936d2b 100644 --- a/run_scripts/run_synthetic_tlv_coco_until_long_horizon.py +++ b/run_scripts/run_synthetic_tlv_coco_until_long_horizon.py @@ -73,7 +73,9 @@ coco_image_source=args.coco_image_source, ) - TLV_generator = SyntheticTLVGenerator(dataloader=dataloader, save_dir=args.save_dir) + TLV_generator = SyntheticTLVGenerator( + dataloader=dataloader, save_dir=args.save_dir + ) TLV_generator.generate_until_time_delta( initial_number_of_frame=args.initial_number_of_frame, diff --git a/run_scripts/run_synthetic_tlv_imagenet.py b/run_scripts/run_synthetic_tlv_imagenet.py index 3d696d5..32a29ff 100644 --- a/run_scripts/run_synthetic_tlv_imagenet.py +++ b/run_scripts/run_synthetic_tlv_imagenet.py @@ -77,7 +77,9 @@ batch_id=args.batch_id, ) - TLV_generator = SyntheticTLVGenerator(dataloader=dataloader, save_dir=args.save_dir) + TLV_generator = SyntheticTLVGenerator( + dataloader=dataloader, save_dir=args.save_dir + ) if args.ltl_logic == "all": available_tl = [ diff --git a/run_scripts/run_synthetic_tlv_imagenet_until_long_horizon.py b/run_scripts/run_synthetic_tlv_imagenet_until_long_horizon.py index 8de136d..6f8784f 100644 --- a/run_scripts/run_synthetic_tlv_imagenet_until_long_horizon.py +++ b/run_scripts/run_synthetic_tlv_imagenet_until_long_horizon.py @@ -74,7 +74,9 @@ batch_id=args.batch_id, ) - TLV_generator = SyntheticTLVGenerator(dataloader=dataloader, save_dir=args.save_dir) + TLV_generator = SyntheticTLVGenerator( + dataloader=dataloader, save_dir=args.save_dir + ) TLV_generator.generate_until_time_delta( initial_number_of_frame=args.initial_number_of_frame, diff --git a/tlv_dataset/__init__.py b/tlv_dataset/__init__.py index 6d58208..d842ebf 100644 --- a/tlv_dataset/__init__.py +++ b/tlv_dataset/__init__.py @@ -1,2 +1,3 @@ """Package containing your_project name.""" + __version__ = "1.0.0" diff --git a/tlv_dataset/common/ltl_utility.py b/tlv_dataset/common/ltl_utility.py index 1f90f31..982faaa 100644 --- a/tlv_dataset/common/ltl_utility.py +++ b/tlv_dataset/common/ltl_utility.py @@ -20,7 +20,9 @@ def get_not_operator_mapping(ltl_formula): return not_operator_proposition_list -def verification_result_eval(verification_result: ExplicitQualitativeCheckResult): +def verification_result_eval( + verification_result: ExplicitQualitativeCheckResult, +): # string result is "true" when is absolutely true # but it returns "true, false" when we have some true and false verification_result_str = str(verification_result) diff --git a/tlv_dataset/common/omegaconf.py b/tlv_dataset/common/omegaconf.py index cf3e35b..780a426 100644 --- a/tlv_dataset/common/omegaconf.py +++ b/tlv_dataset/common/omegaconf.py @@ -2,6 +2,7 @@ from pathlib import Path from omegaconf import DictConfig, ListConfig, OmegaConf + def load_config_from_yaml(config_path: str, read_only=False) -> DictConfig: """Load a yaml config file and return a DictConfig object.""" config = OmegaConf.load(config_path) @@ -9,6 +10,7 @@ def load_config_from_yaml(config_path: str, read_only=False) -> DictConfig: OmegaConf.set_readonly(config, True) return config + def load_config_from_dict(config_dict: dict, read_only=False) -> DictConfig: """Load a dictionary and return a DictConfig object.""" config = OmegaConf.create(config_dict) @@ -16,7 +18,8 @@ def load_config_from_dict(config_dict: dict, read_only=False) -> DictConfig: OmegaConf.set_readonly(config, True) return config + def save_config_to_yaml(config: DictConfig, config_path: str) -> None: """Save a DictConfig object to a yaml file.""" with Path(config_path) as fp: - OmegaConf.save(config=config, f=fp) \ No newline at end of file + OmegaConf.save(config=config, f=fp) diff --git a/tlv_dataset/common/utility.py b/tlv_dataset/common/utility.py index e581f7a..bd639fe 100644 --- a/tlv_dataset/common/utility.py +++ b/tlv_dataset/common/utility.py @@ -22,7 +22,9 @@ def get_file_or_dir_with_datetime(base_name, ext="."): def save_frames( - frames: list, path="/opt/Neuro-Symbolic-Video-Frame-Search/artifacts/result", file_label: str = "" + frames: list, + path="/opt/Neuro-Symbolic-Video-Frame-Search/artifacts/result", + file_label: str = "", ) -> None: """Save image to path. @@ -37,7 +39,9 @@ def save_frames( Image.fromarray(img).save(f"{path}/{file_label}_{idx}.png") -def save_dict_to_pickle(dict_obj: dict | object, path: str, file_name: str = "data.pkl"): +def save_dict_to_pickle( + dict_obj: dict | object, path: str, file_name: str = "data.pkl" +): # Decode the JSON data into a Python object # data_python = json.loads(dict_obj) full_path = Path(path) / file_name diff --git a/tlv_dataset/data/tlv_raw_image.py b/tlv_dataset/data/tlv_raw_image.py index 453ec13..7052acd 100644 --- a/tlv_dataset/data/tlv_raw_image.py +++ b/tlv_dataset/data/tlv_raw_image.py @@ -14,7 +14,9 @@ class TLVRawImage: labels: List[List[str]] images: List[np.ndarray] - def sample_image_from_label(self, labels: list, proposition: list) -> np.ndarray: + def sample_image_from_label( + self, labels: list, proposition: list + ) -> np.ndarray: """Sample image from label.""" image_of_frame = [] img_to_label = {} @@ -60,7 +62,9 @@ def sample_image_from_label(self, labels: list, proposition: list) -> np.ndarray for i, value in enumerate(self.labels) if all(prop in value for prop in label) ] - random_idx = random.choice(img_to_label_list[tuple(sorted(label))]) + random_idx = random.choice( + img_to_label_list[tuple(sorted(label))] + ) image_of_frame.append(self.images[random_idx]) label_idx += 1 return labels, image_of_frame @@ -74,7 +78,9 @@ class TLVRawImageDataset: labels: List[List[str]] images: torch.utils.data.Dataset - def sample_image_from_label(self, labels: list, proposition: list) -> np.ndarray: + def sample_image_from_label( + self, labels: list, proposition: list + ) -> np.ndarray: """Sample image from label.""" image_of_frame = [] img_to_label = {} diff --git a/tlv_dataset/generator/real_tlv_generator.py b/tlv_dataset/generator/real_tlv_generator.py index ae44a1e..fa6e331 100644 --- a/tlv_dataset/generator/real_tlv_generator.py +++ b/tlv_dataset/generator/real_tlv_generator.py @@ -51,7 +51,9 @@ def generate(self): benchmark_frame: TLVDataset = load_pickle_to_dict(file) self.generate_ltl_ground_truth(benchmark_frame) else: - self._dataloader.loading_data(generate_func=self.generate_ltl_ground_truth) + self._dataloader.loading_data( + generate_func=self.generate_ltl_ground_truth + ) def get_label_count(self, lst): output = Counter() diff --git a/tlv_dataset/generator/synthetic_tlv_generator.py b/tlv_dataset/generator/synthetic_tlv_generator.py index 88ddbab..85942b2 100644 --- a/tlv_dataset/generator/synthetic_tlv_generator.py +++ b/tlv_dataset/generator/synthetic_tlv_generator.py @@ -327,15 +327,15 @@ def ltl_function( else: proposition_set = [proposition_1, proposition_2] if temporal_property == "U": - assert proposition_2 is not None, "proposition 2 must be not None" + assert ( + proposition_2 is not None + ), "proposition 2 must be not None" u_index = logic_component.index("U") pre_u_index = logic_component[u_index - 1] post_u_index = logic_component[u_index + 1] if post_u_index == "prop2": # TODO: F & G... - ltl_formula = ( - f'"{proposition_1}" {temporal_property} "{proposition_2}"' - ) + ltl_formula = f'"{proposition_1}" {temporal_property} "{proposition_2}"' post_u_label_idx = [] for idx in list(set(random_frame_idx_selection)): temp_frames_of_interest.append(idx) @@ -349,7 +349,9 @@ def ltl_function( post_u_label_idx.append(prop2_idx) labels_of_frame[prop2_idx] = proposition_2 else: - prop2_idx = random.randrange(idx + 1, number_of_frame - 1) + prop2_idx = random.randrange( + idx + 1, number_of_frame - 1 + ) temp_frames_of_interest.append(prop2_idx) post_u_label_idx.append(prop2_idx) labels_of_frame[prop2_idx] = proposition_2 @@ -386,7 +388,9 @@ def ltl_function( post_u_label_idx.append(prop3_idx) labels_of_frame[prop3_idx] = proposition_3 else: - prop3_idx = random.randrange(idx + 1, number_of_frame - 1) + prop3_idx = random.randrange( + idx + 1, number_of_frame - 1 + ) temp_frames_of_interest.append(prop3_idx) post_u_label_idx.append(prop3_idx) labels_of_frame[prop3_idx] = proposition_3 @@ -423,9 +427,7 @@ def ltl_function( assert ( conditional_property == "!" ), "conditional_property must be ! with one proposition" - ltl_formula = ( - f'{temporal_property} {conditional_property} "{proposition_1}"' - ) + ltl_formula = f'{temporal_property} {conditional_property} "{proposition_1}"' # 1. F "prop1" frame_index = [] if temporal_property == "F": diff --git a/tlv_dataset/label_mapper/mapper_utils.py b/tlv_dataset/label_mapper/mapper_utils.py index 64286bc..06c661e 100644 --- a/tlv_dataset/label_mapper/mapper_utils.py +++ b/tlv_dataset/label_mapper/mapper_utils.py @@ -2,7 +2,9 @@ def get_mapper_metadata(loader_name: str, mapping_to: str): loader_name = loader_name.split(".py")[0] if loader_name == "imagenet": valid_mapper = ["coco"] - assert mapping_to in valid_mapper, "please use valid mapper for ImageNet: coco" + assert ( + mapping_to in valid_mapper + ), "please use valid mapper for ImageNet: coco" if mapping_to == "coco": from tlv_dataset.label_mapper.metadata.imagenet_to_coco import ( MAPPER_METADATA, diff --git a/tlv_dataset/loader/imagenet.py b/tlv_dataset/loader/imagenet.py index 3eae8c0..cf4b48d 100644 --- a/tlv_dataset/loader/imagenet.py +++ b/tlv_dataset/loader/imagenet.py @@ -102,7 +102,9 @@ def __getitem__(self, index): class_id = 0 while ( index - >= self._num_images_per_class[self.mapping_number_to_class[class_id]] + >= self._num_images_per_class[ + self.mapping_number_to_class[class_id] + ] ): index -= self._num_images_per_class[ self.mapping_number_to_class[class_id] @@ -123,15 +125,21 @@ def __getitem__(self, index): else: # Obtain the metaclass where the index is located metaclass_id = 0 - metaclassname = list(self.metaclass_imagenetclass.keys())[metaclass_id] + metaclassname = list(self.metaclass_imagenetclass.keys())[ + metaclass_id + ] cum_count = 0 while index >= self._num_images_per_metaclass[metaclassname]: index -= self._num_images_per_metaclass[metaclassname] cum_count += self._num_images_per_metaclass[metaclassname] metaclass_id += 1 - metaclassname = list(self.metaclass_imagenetclass.keys())[metaclass_id] + metaclassname = list(self.metaclass_imagenetclass.keys())[ + metaclass_id + ] - imagenet_class_for_metaclass = self.metaclass_imagenetclass[metaclassname] + imagenet_class_for_metaclass = self.metaclass_imagenetclass[ + metaclassname + ] index = index_copy - cum_count class_id_val = 0 @@ -264,7 +272,9 @@ def __init__( self.imagenet = ImageNetDS(imagenet_dir_path, is_mapping=is_mapping) # Get text labels from metadata self.class_labels = list(self.imagenet.classnames) - self.data: TLVRawImageDataset = self.process_data(raw_data=self.load_data()) + self.data: TLVRawImageDataset = self.process_data( + raw_data=self.load_data() + ) def load_data(self) -> dict: """Load the labels of the data @@ -274,7 +284,9 @@ def load_data(self) -> dict: labels = [0 for _ in range(len(self.imagenet))] mapped_labels = [0 for _ in range(len(self.imagenet))] cum_count = 0 - for idx, (class_, count) in enumerate(self.imagenet.class_counts.items()): + for idx, (class_, count) in enumerate( + self.imagenet.class_counts.items() + ): cum_count += count for j in range(cum_count - count, cum_count): labels[j] = idx diff --git a/tlv_dataset/loader/nuscenes.py b/tlv_dataset/loader/nuscenes.py index 6ecd8e0..ad683c4 100644 --- a/tlv_dataset/loader/nuscenes.py +++ b/tlv_dataset/loader/nuscenes.py @@ -28,7 +28,9 @@ def __init__( from tlv_dataset.label_mapper.metadata.nuscenes_to_coco import ( MAPPER_METADATA, ) - self._nusc = NuScenes(version=version, dataroot=dataroot, verbose=verbose) + self._nusc = NuScenes( + version=version, dataroot=dataroot, verbose=verbose + ) self._nuscene: list = self._nusc.scene # self._scene_data = self.loading_data(self._nuscene) @@ -87,7 +89,9 @@ def loading_data(self, generate_func: callable = None): for data in self._nusc.sample: if scene_token == data["scene_token"]: front_cam_frame = cv2.imread( - self._nusc.get_sample_data_path(data["data"]["CAM_FRONT"]) + self._nusc.get_sample_data_path( + data["data"]["CAM_FRONT"] + ) ) labels = self.parse_object_class(data["anns"]) # cv2.imwrite("test__.png", front_cam_frame) @@ -95,12 +99,16 @@ def loading_data(self, generate_func: callable = None): scene_data[scene_token]["images_of_frame"].append( front_cam_frame ) - scene_data[scene_token]["labels_of_frame"].append(labels) + scene_data[scene_token]["labels_of_frame"].append( + labels + ) else: data_validation = False if data_validation: if generate_func is not None: - generate_func(self.convert_to_tlv_dataset(scene_data[scene_token])) + generate_func( + self.convert_to_tlv_dataset(scene_data[scene_token]) + ) else: save_dict_to_pickle( dict_obj=scene_data[scene_token], diff --git a/tlv_dataset/loader/waymo.py b/tlv_dataset/loader/waymo.py index a170e93..6a618e6 100644 --- a/tlv_dataset/loader/waymo.py +++ b/tlv_dataset/loader/waymo.py @@ -52,8 +52,13 @@ def ungroup_row( def load_data_set_parquet( - config: omegaconf, context_name: str, validation=False, context_frames: List = None -) -> Tuple[List[open_dataset.CameraImage], List[open_dataset.CameraSegmentationLabel]]: + config: omegaconf, + context_name: str, + validation=False, + context_frames: List = None, +) -> Tuple[ + List[open_dataset.CameraImage], List[open_dataset.CameraSegmentationLabel] +]: """Load datset from parquet files for segmentation and camera images Args: @@ -94,7 +99,9 @@ def load_data_set_parquet( cam_box_list = [] image_list = [] - for i, (key_values, r) in enumerate(cam_segmentation_per_frame_df.iterrows()): + for i, (key_values, r) in enumerate( + cam_segmentation_per_frame_df.iterrows() + ): # Read three sequences of 5 camera images for this demo. # Store a segmentation label component for each camera. cam_box_list.append( @@ -244,7 +251,9 @@ def __init__(self, config=None, validation=False) -> None: context_frame = line.strip().split(",")[1] self.context_set.add(context_name) if self.context_count.get(context_name) is None: - self.context_count[context_name] = {(j + 1): 0 for j in range(5)} + self.context_count[context_name] = { + (j + 1): 0 for j in range(5) + } camera_ids = [] available_camera_ids = line.strip().split(",")[2:-1] for camera_id in available_camera_ids: @@ -296,7 +305,13 @@ def __init__(self, config=None, validation=False) -> None: "static": [102, 102, 102], } - self.OBJECT_CLASSES = ["undefined", "vehicle", "pedestrian", "sign", "cyclist"] + self.OBJECT_CLASSES = [ + "undefined", + "vehicle", + "pedestrian", + "sign", + "cyclist", + ] self.CLASSES = list(self.CLASSES_TO_PALLETTE.keys()) self.PALLETE = list(self.CLASSES_TO_PALLETTE.values()) @@ -332,7 +347,9 @@ def __getitem__( # Load all the frames from the context file frames_with_box, camera_images = load_data_set_parquet( - config=self.ds_config, context_name=context_name, validation=self.validation + config=self.ds_config, + context_name=context_name, + validation=self.validation, ) class_types, _ = read_box_labels(self.ds_config, frames_with_box) @@ -342,14 +359,18 @@ def __getitem__( # All semantic labels are in the form of object indices defined by the PALLETE # flatten list and remvoe empty sublists camera_images_frame = [ - x[camera_id - 1] for x in camera_images_frame if x[camera_id - 1] != [] + x[camera_id - 1] + for x in camera_images_frame + if x[camera_id - 1] != [] ] class_types_frame = class_types[camera_id - 1] class_types_frame = [x for x in class_types_frame if x != []] for i in range(len(class_types_frame)): for j in range(len(class_types_frame[i])): - class_types_frame[i][j] = self.OBJECT_CLASSES[class_types_frame[i][j]] + class_types_frame[i][j] = self.OBJECT_CLASSES[ + class_types_frame[i][j] + ] class_types_frame[i] = list(set(class_types_frame[i])) return camera_images_frame, class_types_frame