From 1429784012134b7db2154fca7011df61ab6f5294 Mon Sep 17 00:00:00 2001 From: Yunchu Lee Date: Tue, 23 Jan 2024 16:04:08 +0900 Subject: [PATCH] Mergeback releases/1.5.0 to develop (#2830) * Update MAPI version (#2730) * Update dependency for exportable code (#2732) * Filter invalid polygon shapes (#2795) --------- Co-authored-by: Vladislav Sovrasov Co-authored-by: Eugene Liu --- requirements/openvino.txt | 2 +- src/otx/algorithms/anomaly/tasks/openvino.py | 11 +++++++---- .../usecases/exportable_code/demo/requirements.txt | 2 +- .../prediction_to_annotation_converter.py | 2 +- src/otx/core/data/adapter/base_dataset_adapter.py | 13 +++++++++---- .../core/data/adapter/detection_dataset_adapter.py | 7 +++++-- .../adapter/visual_prompting_dataset_adapter.py | 2 +- .../mmseg/datasets/pipelines/test_transforms.py | 4 ++-- 8 files changed, 27 insertions(+), 16 deletions(-) diff --git a/requirements/openvino.txt b/requirements/openvino.txt index c77e9981128..cdc824ae0f2 100644 --- a/requirements/openvino.txt +++ b/requirements/openvino.txt @@ -2,7 +2,7 @@ # OpenVINO Requirements. # nncf==2.7.0 onnx==1.13.0 -openvino-model-api==0.1.7 +openvino-model-api==0.1.8 openvino==2023.2.0 openvino-dev==2023.2.0 openvino-telemetry==2023.2.* diff --git a/src/otx/algorithms/anomaly/tasks/openvino.py b/src/otx/algorithms/anomaly/tasks/openvino.py index 931f325f373..a5db9c21894 100644 --- a/src/otx/algorithms/anomaly/tasks/openvino.py +++ b/src/otx/algorithms/anomaly/tasks/openvino.py @@ -188,13 +188,17 @@ def infer(self, dataset: DatasetEntity, inference_parameters: InferenceParameter label = self.anomalous_label if image_result.pred_score >= 0.5 else self.normal_label elif self.task_type == TaskType.ANOMALY_SEGMENTATION: annotations = create_annotation_from_segmentation_map( - pred_mask, image_result.anomaly_map.squeeze(), {0: self.normal_label, 1: self.anomalous_label} + pred_mask, + image_result.anomaly_map.squeeze() / 255.0, + {0: self.normal_label, 1: self.anomalous_label}, ) dataset_item.append_annotations(annotations) label = self.normal_label if len(annotations) == 0 else self.anomalous_label elif self.task_type == TaskType.ANOMALY_DETECTION: annotations = create_detection_annotation_from_anomaly_heatmap( - pred_mask, image_result.anomaly_map.squeeze(), {0: self.normal_label, 1: self.anomalous_label} + pred_mask, + image_result.anomaly_map.squeeze() / 255.0, + {0: self.normal_label, 1: self.anomalous_label}, ) dataset_item.append_annotations(annotations) label = self.normal_label if len(annotations) == 0 else self.anomalous_label @@ -202,13 +206,12 @@ def infer(self, dataset: DatasetEntity, inference_parameters: InferenceParameter raise ValueError(f"Unknown task type: {self.task_type}") dataset_item.append_labels([ScoredLabel(label=label, probability=float(probability))]) - anomaly_map = (image_result.anomaly_map * 255).astype(np.uint8) heatmap_media = ResultMediaEntity( name="Anomaly Map", type="anomaly_map", label=label, annotation_scene=dataset_item.annotation_scene, - numpy=anomaly_map, + numpy=image_result.anomaly_map, ) dataset_item.append_metadata_item(heatmap_media) update_progress_callback(int((idx + 1) / len(dataset) * 100)) diff --git a/src/otx/api/usecases/exportable_code/demo/requirements.txt b/src/otx/api/usecases/exportable_code/demo/requirements.txt index bf94f349fda..2389bc66a8b 100644 --- a/src/otx/api/usecases/exportable_code/demo/requirements.txt +++ b/src/otx/api/usecases/exportable_code/demo/requirements.txt @@ -1,4 +1,4 @@ openvino==2023.2.0 -openvino-model-api==0.1.7 +openvino-model-api==0.1.8 otx @ git+https://github.com/openvinotoolkit/training_extensions/@2988fdc51ef7e4a136a9d4e09602b3844d7bafec#egg=otx numpy>=1.21.0,<=1.23.5 # np.bool was removed in 1.24.0 which was used in openvino runtime diff --git a/src/otx/api/usecases/exportable_code/prediction_to_annotation_converter.py b/src/otx/api/usecases/exportable_code/prediction_to_annotation_converter.py index 73f8b95be0e..f84c2b0facf 100644 --- a/src/otx/api/usecases/exportable_code/prediction_to_annotation_converter.py +++ b/src/otx/api/usecases/exportable_code/prediction_to_annotation_converter.py @@ -380,7 +380,7 @@ def convert_to_annotation(self, predictions: AnomalyResult, metadata: Dict[str, assert predictions.pred_mask is not None assert predictions.anomaly_map is not None annotations = create_annotation_from_segmentation_map( - predictions.pred_mask, predictions.anomaly_map, self.label_map + predictions.pred_mask, predictions.anomaly_map / 255.0, self.label_map ) if len(annotations) == 0: # TODO: add confidence to this label diff --git a/src/otx/core/data/adapter/base_dataset_adapter.py b/src/otx/core/data/adapter/base_dataset_adapter.py index 52195de4d0f..af87695bd66 100644 --- a/src/otx/core/data/adapter/base_dataset_adapter.py +++ b/src/otx/core/data/adapter/base_dataset_adapter.py @@ -273,11 +273,16 @@ def _prepare_label_information( return {"category_items": category_items, "label_groups": label_groups, "label_entities": label_entities} - def _is_normal_polygon(self, annotation: DatumAnnotationType.polygon) -> bool: + def _is_normal_polygon(self, annotation: DatumAnnotationType.polygon, width: int, height: int) -> bool: """To filter out the abnormal polygon.""" - x_points = [annotation.points[i] for i in range(0, len(annotation.points), 2)] - y_points = [annotation.points[i + 1] for i in range(0, len(annotation.points), 2)] - return min(x_points) < max(x_points) and min(y_points) < max(y_points) + x_points = annotation.points[::2] # Extract x-coordinates + y_points = annotation.points[1::2] # Extract y-coordinates + + return ( + min(x_points) < max(x_points) < width + and min(y_points) < max(y_points) < height + and annotation.get_area() > 0 + ) def _is_normal_bbox(self, x1: float, y1: float, x2: float, y2: float) -> bool: """To filter out the abrnormal bbox.""" diff --git a/src/otx/core/data/adapter/detection_dataset_adapter.py b/src/otx/core/data/adapter/detection_dataset_adapter.py index 612ab303f23..963b7dafd73 100644 --- a/src/otx/core/data/adapter/detection_dataset_adapter.py +++ b/src/otx/core/data/adapter/detection_dataset_adapter.py @@ -37,8 +37,11 @@ def get_otx_dataset(self) -> DatasetEntity: assert isinstance(image, Image) shapes = [] for ann in datumaro_item.annotations: - if self.task_type in (TaskType.INSTANCE_SEGMENTATION, TaskType.ROTATED_DETECTION): - if ann.type == DatumAnnotationType.polygon and self._is_normal_polygon(ann): + if ( + self.task_type in (TaskType.INSTANCE_SEGMENTATION, TaskType.ROTATED_DETECTION) + and ann.type == DatumAnnotationType.polygon + ): + if self._is_normal_polygon(ann, image.width, image.height): shapes.append(self._get_polygon_entity(ann, image.width, image.height)) elif ann.type == DatumAnnotationType.ellipse: shapes.append(self._get_ellipse_entity(ann, image.width, image.height)) diff --git a/src/otx/core/data/adapter/visual_prompting_dataset_adapter.py b/src/otx/core/data/adapter/visual_prompting_dataset_adapter.py index d428dc6afad..7a5c235f792 100644 --- a/src/otx/core/data/adapter/visual_prompting_dataset_adapter.py +++ b/src/otx/core/data/adapter/visual_prompting_dataset_adapter.py @@ -53,7 +53,7 @@ def get_otx_dataset(self) -> DatasetEntity: for ann in datumaro_item.annotations: if ann.type == DatumAnnotationType.polygon: # save polygons as-is, they will be converted to masks. - if self._is_normal_polygon(ann): + if self._is_normal_polygon(ann, image.width, image.height): shapes.append(self._get_polygon_entity(ann, image.width, image.height)) if ann.type == DatumAnnotationType.mask: diff --git a/tests/unit/algorithms/segmentation/adapters/mmseg/datasets/pipelines/test_transforms.py b/tests/unit/algorithms/segmentation/adapters/mmseg/datasets/pipelines/test_transforms.py index c1404deb76c..5187a0f507d 100644 --- a/tests/unit/algorithms/segmentation/adapters/mmseg/datasets/pipelines/test_transforms.py +++ b/tests/unit/algorithms/segmentation/adapters/mmseg/datasets/pipelines/test_transforms.py @@ -110,8 +110,8 @@ class TestNormalize: @pytest.mark.parametrize( "mean,std,to_rgb,expected", [ - ([1.0 for _ in range(3)], [1.0 for _ in range(3)], True, np.array([[[1.0, 0.0, -1.0]]], dtype=np.float32)), - ([1.0 for _ in range(3)], [1.0 for _ in range(3)], False, np.array([[[-1.0, 0.0, 1.0]]], dtype=np.float32)), + ([[[1.0, 1.0, 1.0]]], [[[1.0, 1.0, 1.0]]], True, np.array([[[1.0, 0.0, -1.0]]], dtype=np.float32)), + ([[[1.0, 1.0, 1.0]]], [[[1.0, 1.0, 1.0]]], False, np.array([[[-1.0, 0.0, 1.0]]], dtype=np.float32)), ], ) def test_call(self, mean: List[float], std: List[float], to_rgb: bool, expected: np.array) -> None: