From 9ca1204a4c0eb83ea4dff83f7c14d1893f984f67 Mon Sep 17 00:00:00 2001 From: Shubham Kanitkar Date: Fri, 18 Aug 2023 13:09:55 -0700 Subject: [PATCH 1/4] Empty numpy array check --- supervision/detection/utils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/supervision/detection/utils.py b/supervision/detection/utils.py index db631755..a3229650 100644 --- a/supervision/detection/utils.py +++ b/supervision/detection/utils.py @@ -20,7 +20,10 @@ def polygon_to_mask(polygon: np.ndarray, resolution_wh: Tuple[int, int]) -> np.n """ width, height = resolution_wh mask = np.zeros((height, width)) - cv2.fillPoly(mask, [polygon], color=1) + + # Empty numpy array check + if np.any(polygon): + cv2.fillPoly(mask, [polygon], color=1) return mask From 0f889935fdf07e2c8429b373872815effacece96 Mon Sep 17 00:00:00 2001 From: Shubham Kanitkar Date: Mon, 21 Aug 2023 16:38:30 -0700 Subject: [PATCH 2/4] filtering out invalid point key --- supervision/detection/utils.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/supervision/detection/utils.py b/supervision/detection/utils.py index a3229650..7e8a4ee9 100644 --- a/supervision/detection/utils.py +++ b/supervision/detection/utils.py @@ -21,9 +21,7 @@ def polygon_to_mask(polygon: np.ndarray, resolution_wh: Tuple[int, int]) -> np.n width, height = resolution_wh mask = np.zeros((height, width)) - # Empty numpy array check - if np.any(polygon): - cv2.fillPoly(mask, [polygon], color=1) + cv2.fillPoly(mask, [polygon], color=1) return mask @@ -364,12 +362,13 @@ def process_roboflow_result( if "points" not in prediction: continue - polygon = np.array( - [[point["x"], point["y"]] for point in prediction["points"]], dtype=int - ) + if len(prediction["points"]) >= 3: + polygon = np.array( + [[point["x"], point["y"]] for point in prediction["points"]], dtype=int + ) - mask = polygon_to_mask(polygon, resolution_wh=(image_width, image_height)) - masks.append(mask) + mask = polygon_to_mask(polygon, resolution_wh=(image_width, image_height)) + masks.append(mask) xyxy = np.array(xyxy) confidence = np.array(confidence) From 7de50e6b0b0806df69d7664a0fce84f2c78d18ee Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Tue, 22 Aug 2023 12:23:39 +0200 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=9B=A0=EF=B8=8F=20fix=20ready=20for?= =?UTF-8?q?=20merging?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- supervision/detection/utils.py | 29 +++--- test/detection/test_utils.py | 167 ++++++++++++++++++++++++++++++++- 2 files changed, 179 insertions(+), 17 deletions(-) diff --git a/supervision/detection/utils.py b/supervision/detection/utils.py index 7e8a4ee9..95d1fc26 100644 --- a/supervision/detection/utils.py +++ b/supervision/detection/utils.py @@ -355,24 +355,25 @@ def process_roboflow_result( x_max = x_min + width y_max = y_min + height - xyxy.append([x_min, y_min, x_max, y_max]) - class_id.append(class_list.index(prediction["class"])) - confidence.append(prediction["confidence"]) - if "points" not in prediction: - continue - - if len(prediction["points"]) >= 3: - polygon = np.array( - [[point["x"], point["y"]] for point in prediction["points"]], dtype=int - ) - + xyxy.append([x_min, y_min, x_max, y_max]) + class_id.append(class_list.index(prediction["class"])) + confidence.append(prediction["confidence"]) + elif len(prediction["points"]) >= 3: + polygon = np.array([ + [point["x"], point["y"]] + for point + in prediction["points"] + ], dtype=int) mask = polygon_to_mask(polygon, resolution_wh=(image_width, image_height)) + xyxy.append([x_min, y_min, x_max, y_max]) + class_id.append(class_list.index(prediction["class"])) + confidence.append(prediction["confidence"]) masks.append(mask) - xyxy = np.array(xyxy) - confidence = np.array(confidence) - class_id = np.array(class_id).astype(int) + xyxy = np.array(xyxy) if len(xyxy) > 0 else np.empty((0, 4)) + confidence = np.array(confidence) if len(confidence) > 0 else np.empty(0) + class_id = np.array(class_id).astype(int) if len(class_id) > 0 else np.empty(0) masks = np.array(masks, dtype=bool) if len(masks) > 0 else None return xyxy, confidence, class_id, masks diff --git a/test/detection/test_utils.py b/test/detection/test_utils.py index b096fd08..316f23e5 100644 --- a/test/detection/test_utils.py +++ b/test/detection/test_utils.py @@ -12,6 +12,10 @@ from supervision.detection.utils import ( ) +TEST_MASK = np.zeros((1, 1000, 1000), dtype=bool) +TEST_MASK[:, 300:351, 200:251] = True + + @pytest.mark.parametrize( "predictions, iou_threshold, expected_result, exception", [ @@ -259,9 +263,17 @@ def test_filter_polygons_by_area( "roboflow_result, class_list, expected_result, exception", [ ( - {"predictions": [], "image": {"width": 1000, "height": 1000}}, + { + "predictions": [], + "image": {"width": 1000, "height": 1000} + }, ["person", "car", "truck"], - (np.empty((0, 4)), np.empty(0), np.empty(0), None), + ( + np.empty((0, 4)), + np.empty(0), + np.empty(0), + None + ), DoesNotRaise(), ), # empty result ( @@ -286,7 +298,156 @@ def test_filter_polygons_by_area( None, ), DoesNotRaise(), - ), # single bounding box + ), # single correct object detection result +( + { + "predictions": [ + { + "x": 200.0, + "y": 300.0, + "width": 50.0, + "height": 50.0, + "confidence": 0.9, + "class": "person", + }, + { + "x": 500.0, + "y": 500.0, + "width": 100.0, + "height": 100.0, + "confidence": 0.8, + "class": "truck", + } + ], + "image": {"width": 1000, "height": 1000}, + }, + ["person", "car", "truck"], + ( + np.array([[175.0, 275.0, 225.0, 325.0], [450.0, 450.0, 550.0, 550.0]]), + np.array([0.9, 0.8]), + np.array([0, 2]), + None, + ), + DoesNotRaise(), + ), # two correct object detection result + ( + { + "predictions": [ + { + "x": 200.0, + "y": 300.0, + "width": 50.0, + "height": 50.0, + "confidence": 0.9, + "class": "person", + "points": [] + } + ], + "image": {"width": 1000, "height": 1000}, + }, + ["person", "car", "truck"], + ( + np.empty((0, 4)), + np.empty(0), + np.empty(0), + None + ), + DoesNotRaise(), + ), # single incorrect instance segmentation result with no points + ( + { + "predictions": [ + { + "x": 200.0, + "y": 300.0, + "width": 50.0, + "height": 50.0, + "confidence": 0.9, + "class": "person", + "points": [ + {"x": 200.0, "y": 300.0}, + {"x": 250.0, "y": 300.0} + ] + } + ], + "image": {"width": 1000, "height": 1000}, + }, + ["person", "car", "truck"], + ( + np.empty((0, 4)), + np.empty(0), + np.empty(0), + None + ), + DoesNotRaise(), + ), # single incorrect instance segmentation result with no enough points + ( + { + "predictions": [ + { + "x": 200.0, + "y": 300.0, + "width": 50.0, + "height": 50.0, + "confidence": 0.9, + "class": "person", + "points": [ + {"x": 200.0, "y": 300.0}, + {"x": 250.0, "y": 300.0}, + {"x": 250.0, "y": 350.0}, + {"x": 200.0, "y": 350.0}, + ] + } + ], + "image": {"width": 1000, "height": 1000}, + }, + ["person", "car", "truck"], + ( + np.array([[175.0, 275.0, 225.0, 325.0]]), + np.array([0.9]), + np.array([0]), + TEST_MASK + ), + DoesNotRaise(), + ), # single incorrect instance segmentation result with no enough points + ( + { + "predictions": [ + { + "x": 200.0, + "y": 300.0, + "width": 50.0, + "height": 50.0, + "confidence": 0.9, + "class": "person", + "points": [ + {"x": 200.0, "y": 300.0}, + {"x": 250.0, "y": 300.0}, + {"x": 250.0, "y": 350.0}, + {"x": 200.0, "y": 350.0}, + ] + }, + { + "x": 500.0, + "y": 500.0, + "width": 100.0, + "height": 100.0, + "confidence": 0.8, + "class": "truck", + "points": [] + } + ], + "image": {"width": 1000, "height": 1000}, + }, + ["person", "car", "truck"], + ( + np.array([[175.0, 275.0, 225.0, 325.0]]), + np.array([0.9]), + np.array([0]), + TEST_MASK + ), + DoesNotRaise(), + ), # two instance segmentation results - one correct, one incorrect ], ) def test_process_roboflow_result( From b86f8ccdb8922869d6361583d295affd092008d9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 22 Aug 2023 10:25:41 +0000 Subject: [PATCH 4/4] =?UTF-8?q?fix(pre=5Fcommit):=20=F0=9F=8E=A8=20auto=20?= =?UTF-8?q?format=20pre-commit=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- supervision/detection/utils.py | 8 +- test/detection/test_utils.py | 160 ++++++++++++++------------------- 2 files changed, 72 insertions(+), 96 deletions(-) diff --git a/supervision/detection/utils.py b/supervision/detection/utils.py index 95d1fc26..3d4309b9 100644 --- a/supervision/detection/utils.py +++ b/supervision/detection/utils.py @@ -360,11 +360,9 @@ def process_roboflow_result( class_id.append(class_list.index(prediction["class"])) confidence.append(prediction["confidence"]) elif len(prediction["points"]) >= 3: - polygon = np.array([ - [point["x"], point["y"]] - for point - in prediction["points"] - ], dtype=int) + polygon = np.array( + [[point["x"], point["y"]] for point in prediction["points"]], dtype=int + ) mask = polygon_to_mask(polygon, resolution_wh=(image_width, image_height)) xyxy.append([x_min, y_min, x_max, y_max]) class_id.append(class_list.index(prediction["class"])) diff --git a/test/detection/test_utils.py b/test/detection/test_utils.py index 316f23e5..26c682ce 100644 --- a/test/detection/test_utils.py +++ b/test/detection/test_utils.py @@ -11,7 +11,6 @@ from supervision.detection.utils import ( process_roboflow_result, ) - TEST_MASK = np.zeros((1, 1000, 1000), dtype=bool) TEST_MASK[:, 300:351, 200:251] = True @@ -263,17 +262,9 @@ def test_filter_polygons_by_area( "roboflow_result, class_list, expected_result, exception", [ ( - { - "predictions": [], - "image": {"width": 1000, "height": 1000} - }, + {"predictions": [], "image": {"width": 1000, "height": 1000}}, ["person", "car", "truck"], - ( - np.empty((0, 4)), - np.empty(0), - np.empty(0), - None - ), + (np.empty((0, 4)), np.empty(0), np.empty(0), None), DoesNotRaise(), ), # empty result ( @@ -299,7 +290,7 @@ def test_filter_polygons_by_area( ), DoesNotRaise(), ), # single correct object detection result -( + ( { "predictions": [ { @@ -317,7 +308,7 @@ def test_filter_polygons_by_area( "height": 100.0, "confidence": 0.8, "class": "truck", - } + }, ], "image": {"width": 1000, "height": 1000}, }, @@ -340,20 +331,34 @@ def test_filter_polygons_by_area( "height": 50.0, "confidence": 0.9, "class": "person", - "points": [] + "points": [], } ], "image": {"width": 1000, "height": 1000}, }, ["person", "car", "truck"], - ( - np.empty((0, 4)), - np.empty(0), - np.empty(0), - None - ), + (np.empty((0, 4)), np.empty(0), np.empty(0), None), DoesNotRaise(), ), # single incorrect instance segmentation result with no points + ( + { + "predictions": [ + { + "x": 200.0, + "y": 300.0, + "width": 50.0, + "height": 50.0, + "confidence": 0.9, + "class": "person", + "points": [{"x": 200.0, "y": 300.0}, {"x": 250.0, "y": 300.0}], + } + ], + "image": {"width": 1000, "height": 1000}, + }, + ["person", "car", "truck"], + (np.empty((0, 4)), np.empty(0), np.empty(0), None), + DoesNotRaise(), + ), # single incorrect instance segmentation result with no enough points ( { "predictions": [ @@ -366,87 +371,60 @@ def test_filter_polygons_by_area( "class": "person", "points": [ {"x": 200.0, "y": 300.0}, - {"x": 250.0, "y": 300.0} - ] + {"x": 250.0, "y": 300.0}, + {"x": 250.0, "y": 350.0}, + {"x": 200.0, "y": 350.0}, + ], } ], "image": {"width": 1000, "height": 1000}, }, ["person", "car", "truck"], ( - np.empty((0, 4)), - np.empty(0), - np.empty(0), - None + np.array([[175.0, 275.0, 225.0, 325.0]]), + np.array([0.9]), + np.array([0]), + TEST_MASK, ), DoesNotRaise(), ), # single incorrect instance segmentation result with no enough points ( - { - "predictions": [ - { - "x": 200.0, - "y": 300.0, - "width": 50.0, - "height": 50.0, - "confidence": 0.9, - "class": "person", - "points": [ - {"x": 200.0, "y": 300.0}, - {"x": 250.0, "y": 300.0}, - {"x": 250.0, "y": 350.0}, - {"x": 200.0, "y": 350.0}, - ] - } - ], - "image": {"width": 1000, "height": 1000}, - }, - ["person", "car", "truck"], - ( - np.array([[175.0, 275.0, 225.0, 325.0]]), - np.array([0.9]), - np.array([0]), - TEST_MASK - ), - DoesNotRaise(), - ), # single incorrect instance segmentation result with no enough points - ( - { - "predictions": [ - { - "x": 200.0, - "y": 300.0, - "width": 50.0, - "height": 50.0, - "confidence": 0.9, - "class": "person", - "points": [ - {"x": 200.0, "y": 300.0}, - {"x": 250.0, "y": 300.0}, - {"x": 250.0, "y": 350.0}, - {"x": 200.0, "y": 350.0}, - ] - }, - { - "x": 500.0, - "y": 500.0, - "width": 100.0, - "height": 100.0, - "confidence": 0.8, - "class": "truck", - "points": [] - } - ], - "image": {"width": 1000, "height": 1000}, - }, - ["person", "car", "truck"], - ( - np.array([[175.0, 275.0, 225.0, 325.0]]), - np.array([0.9]), - np.array([0]), - TEST_MASK - ), - DoesNotRaise(), + { + "predictions": [ + { + "x": 200.0, + "y": 300.0, + "width": 50.0, + "height": 50.0, + "confidence": 0.9, + "class": "person", + "points": [ + {"x": 200.0, "y": 300.0}, + {"x": 250.0, "y": 300.0}, + {"x": 250.0, "y": 350.0}, + {"x": 200.0, "y": 350.0}, + ], + }, + { + "x": 500.0, + "y": 500.0, + "width": 100.0, + "height": 100.0, + "confidence": 0.8, + "class": "truck", + "points": [], + }, + ], + "image": {"width": 1000, "height": 1000}, + }, + ["person", "car", "truck"], + ( + np.array([[175.0, 275.0, 225.0, 325.0]]), + np.array([0.9]), + np.array([0]), + TEST_MASK, + ), + DoesNotRaise(), ), # two instance segmentation results - one correct, one incorrect ], )