From 2f5d878ff17535ddb9d02be4cf91712f1c5b11f6 Mon Sep 17 00:00:00 2001 From: kymillev Date: Tue, 13 Aug 2024 16:47:37 +0200 Subject: [PATCH 1/6] Fix mask_annotate for int dtypes --- supervision/annotators/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/supervision/annotators/core.py b/supervision/annotators/core.py index ca2a71f86..495ab05e6 100644 --- a/supervision/annotators/core.py +++ b/supervision/annotators/core.py @@ -357,7 +357,7 @@ def annotate( else custom_color_lookup, ) mask = detections.mask[detection_idx] - colored_mask[mask] = color.as_bgr() + colored_mask[mask.astype(bool)] = color.as_bgr() cv2.addWeighted( colored_mask, self.opacity, scene, 1 - self.opacity, 0, dst=scene From c4e8037451da0dc2e28d078285264b19c00ef590 Mon Sep 17 00:00:00 2001 From: kymillev Date: Fri, 16 Aug 2024 18:51:55 +0200 Subject: [PATCH 2/6] Revert conversion to bool --- supervision/annotators/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/supervision/annotators/core.py b/supervision/annotators/core.py index 495ab05e6..ca2a71f86 100644 --- a/supervision/annotators/core.py +++ b/supervision/annotators/core.py @@ -357,7 +357,7 @@ def annotate( else custom_color_lookup, ) mask = detections.mask[detection_idx] - colored_mask[mask.astype(bool)] = color.as_bgr() + colored_mask[mask] = color.as_bgr() cv2.addWeighted( colored_mask, self.opacity, scene, 1 - self.opacity, 0, dst=scene From 36d0d524b70de31c72b07e11b2701f5fec8235fb Mon Sep 17 00:00:00 2001 From: kymillev Date: Fri, 16 Aug 2024 18:53:29 +0200 Subject: [PATCH 3/6] Add depreciation warning - Warning is raised when creating a Detections object with non-bool masks --- supervision/validators/__init__.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/supervision/validators/__init__.py b/supervision/validators/__init__.py index 44cfcb988..f2cf81856 100644 --- a/supervision/validators/__init__.py +++ b/supervision/validators/__init__.py @@ -2,6 +2,8 @@ import numpy as np +from supervision.utils.internal import warn_deprecated + def validate_xyxy(xyxy: Any) -> None: expected_shape = "(_, 4)" @@ -15,16 +17,31 @@ def validate_xyxy(xyxy: Any) -> None: def validate_mask(mask: Any, n: int) -> None: + if mask is None: + return + expected_shape = f"({n}, H, W)" actual_shape = str(getattr(mask, "shape", None)) - is_valid = mask is None or ( + actual_dtype = getattr(mask, "dtype", None) + + is_valid_shape = ( isinstance(mask, np.ndarray) and len(mask.shape) == 3 and mask.shape[0] == n ) - if not is_valid: + if not is_valid_shape: raise ValueError( - f"mask must be a 3D np.ndarray with shape {expected_shape}, but got shape " - f"{actual_shape}" + "Mask must be a 3D np.ndarray with shape " + + f"{expected_shape}, but got shape {actual_shape}" + ) + if not np.issubdtype(mask.dtype, bool): + warn_deprecated( + f"A `Detections` object was created with a mask of type {actual_dtype}." + " Masks of type other than `bool` are deprecated and may produce unexpected" + " behavior. Stricter type checking will be introduced in" + " `supervision-0.28.0`. Please use `mask = np.array(..., dtype=bool)` when" + " creating the mask manually. If you did not create the mask manually," + " please report the issue to the `supervision` team." ) + raise ValueError("Mask must be a boolean np.ndarray") def validate_class_id(class_id: Any, n: int) -> None: From 3a555c818c5a9db45099fa6f391968ccf0c5a673 Mon Sep 17 00:00:00 2001 From: kymillev Date: Fri, 16 Aug 2024 18:54:15 +0200 Subject: [PATCH 4/6] Add dtype=bool to test masks --- test/dataset/formats/test_coco.py | 21 ++++++++++++++------- test/utils/test_internal.py | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/test/dataset/formats/test_coco.py b/test/dataset/formats/test_coco.py index 7e269dae4..dc98ad323 100644 --- a/test/dataset/formats/test_coco.py +++ b/test/dataset/formats/test_coco.py @@ -227,7 +227,8 @@ def test_group_coco_annotations_by_image_id( [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], ] - ] + ], + dtype=bool, ), ), DoesNotRaise(), @@ -259,7 +260,8 @@ def test_group_coco_annotations_by_image_id( [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], ] - ] + ], + dtype=bool, ), ), DoesNotRaise(), @@ -304,7 +306,8 @@ def test_group_coco_annotations_by_image_id( [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], ], - ] + ], + dtype=bool, ), ), DoesNotRaise(), @@ -349,7 +352,8 @@ def test_group_coco_annotations_by_image_id( [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], ], - ] + ], + dtype=bool, ), ), DoesNotRaise(), @@ -461,7 +465,8 @@ def test_build_coco_class_index_mapping( [1, 1, 1, 1, 0], [1, 1, 1, 1, 0], ] - ] + ], + dtype=bool, ), ), 0, @@ -490,7 +495,8 @@ def test_build_coco_class_index_mapping( [0, 0, 0, 1, 1], [0, 0, 0, 1, 1], ] - ] + ], + dtype=bool, ), ), 0, @@ -522,7 +528,8 @@ def test_build_coco_class_index_mapping( [1, 1, 0, 0, 1], [1, 1, 1, 1, 1], ] - ] + ], + dtype=bool, ), ), 0, diff --git a/test/utils/test_internal.py b/test/utils/test_internal.py index eee614e6c..d90236619 100644 --- a/test/utils/test_internal.py +++ b/test/utils/test_internal.py @@ -157,7 +157,7 @@ def __private_property(self): xyxy=np.array([[1, 2, 3, 4], [5, 6, 7, 8]]), class_id=np.array([1, 2]), confidence=np.array([0.1, 0.2]), - mask=np.array([[[1]], [[2]]]), + mask=np.array([[[1]], [[2]]], dtype=bool), tracker_id=np.array([1, 2]), data={"key_1": [1, 2], "key_2": [3, 4]}, ), From f8d46965edcc15f3d55538f49ef15b1c95bf8645 Mon Sep 17 00:00:00 2001 From: kymillev Date: Fri, 16 Aug 2024 19:04:30 +0200 Subject: [PATCH 5/6] Remove ValueError (testing) --- supervision/validators/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/supervision/validators/__init__.py b/supervision/validators/__init__.py index f2cf81856..82b4d9503 100644 --- a/supervision/validators/__init__.py +++ b/supervision/validators/__init__.py @@ -41,7 +41,6 @@ def validate_mask(mask: Any, n: int) -> None: " creating the mask manually. If you did not create the mask manually," " please report the issue to the `supervision` team." ) - raise ValueError("Mask must be a boolean np.ndarray") def validate_class_id(class_id: Any, n: int) -> None: From 27c66a3f1cfe49c909dca94e775f3e2f1053c8d7 Mon Sep 17 00:00:00 2001 From: kymillev Date: Fri, 16 Aug 2024 19:30:48 +0200 Subject: [PATCH 6/6] use actual_dtype in check --- supervision/validators/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/supervision/validators/__init__.py b/supervision/validators/__init__.py index 82b4d9503..1788708e2 100644 --- a/supervision/validators/__init__.py +++ b/supervision/validators/__init__.py @@ -32,7 +32,7 @@ def validate_mask(mask: Any, n: int) -> None: "Mask must be a 3D np.ndarray with shape " + f"{expected_shape}, but got shape {actual_shape}" ) - if not np.issubdtype(mask.dtype, bool): + if not np.issubdtype(actual_dtype, bool): warn_deprecated( f"A `Detections` object was created with a mask of type {actual_dtype}." " Masks of type other than `bool` are deprecated and may produce unexpected"