From 9ad850af46142f9b71e9cc8990df71bf712a5755 Mon Sep 17 00:00:00 2001 From: jackiehimel Date: Wed, 12 Nov 2025 20:58:25 -0500 Subject: [PATCH 1/5] fix: correct numpy indexing in denormalize_boxes and add ultralytics validation - Fix denormalize_boxes numpy indexing bug that caused IndexError with 3+ boxes - Add validation for missing boxes attribute in from_ultralytics - Add comprehensive test coverage (11 new tests) Fixes #1959 Fixes #2000 --- supervision/detection/core.py | 27 ++++---- supervision/detection/utils/boxes.py | 4 +- test/detection/test_core.py | 80 ++++++++++++++++++++++++ test/detection/utils/test_boxes.py | 92 +++++++++++++++++++++++++++- 4 files changed, 188 insertions(+), 15 deletions(-) diff --git a/supervision/detection/core.py b/supervision/detection/core.py index ffe5ed3fc..ae6205dfb 100644 --- a/supervision/detection/core.py +++ b/supervision/detection/core.py @@ -296,18 +296,21 @@ def from_ultralytics(cls, ultralytics_results) -> Detections: class_id=np.arange(len(ultralytics_results)), ) - class_id = ultralytics_results.boxes.cls.cpu().numpy().astype(int) - class_names = np.array([ultralytics_results.names[i] for i in class_id]) - return cls( - xyxy=ultralytics_results.boxes.xyxy.cpu().numpy(), - confidence=ultralytics_results.boxes.conf.cpu().numpy(), - class_id=class_id, - mask=extract_ultralytics_masks(ultralytics_results), - tracker_id=ultralytics_results.boxes.id.int().cpu().numpy() - if ultralytics_results.boxes.id is not None - else None, - data={CLASS_NAME_DATA_FIELD: class_names}, - ) + if hasattr(ultralytics_results, "boxes") and ultralytics_results.boxes is not None: + class_id = ultralytics_results.boxes.cls.cpu().numpy().astype(int) + class_names = np.array([ultralytics_results.names[i] for i in class_id]) + return cls( + xyxy=ultralytics_results.boxes.xyxy.cpu().numpy(), + confidence=ultralytics_results.boxes.conf.cpu().numpy(), + class_id=class_id, + mask=extract_ultralytics_masks(ultralytics_results), + tracker_id=ultralytics_results.boxes.id.int().cpu().numpy() + if ultralytics_results.boxes.id is not None + else None, + data={CLASS_NAME_DATA_FIELD: class_names}, + ) + + return cls.empty() @classmethod def from_yolo_nas(cls, yolo_nas_results) -> Detections: diff --git a/supervision/detection/utils/boxes.py b/supervision/detection/utils/boxes.py index 3b01fcb68..60542a43a 100644 --- a/supervision/detection/utils/boxes.py +++ b/supervision/detection/utils/boxes.py @@ -147,8 +147,8 @@ def denormalize_boxes( width, height = resolution_wh result = normalized_xyxy.copy() - result[[0, 2]] = (result[[0, 2]] * width) / normalization_factor - result[[1, 3]] = (result[[1, 3]] * height) / normalization_factor + result[:, [0, 2]] = (result[:, [0, 2]] * width) / normalization_factor + result[:, [1, 3]] = (result[:, [1, 3]] * height) / normalization_factor return result diff --git a/test/detection/test_core.py b/test/detection/test_core.py index c57bea409..1542f0a35 100644 --- a/test/detection/test_core.py +++ b/test/detection/test_core.py @@ -815,3 +815,83 @@ def test_merge_inner_detection_object_pair( with exception: result = merge_inner_detection_object_pair(detection_1, detection_2) assert result == expected_result + +class TestFromUltralytics: + """Test suite for Detections.from_ultralytics method.""" + + def test_from_ultralytics_with_missing_boxes_attribute(self): + """Test that from_ultralytics handles missing boxes attribute gracefully. + + Regression test for issue #2000. + """ + # Create a mock ultralytics result without boxes attribute + class MockUltralyticsResult: + def __init__(self): + self.names = {0: "class1", 1: "class2"} + # Intentionally not setting 'boxes' or 'obb' attribute + + mock_result = MockUltralyticsResult() + detections = Detections.from_ultralytics(mock_result) + + # Should return empty detections instead of crashing + assert len(detections) == 0 + assert detections.xyxy.shape == (0, 4) + + def test_from_ultralytics_with_boxes_none(self): + """Test that from_ultralytics handles boxes=None (segmentation-only models).""" + # Create a mock ultralytics result with boxes=None + class MockUltralyticsResult: + def __init__(self): + self.boxes = None + self.names = {0: "class1"} + # Mock masks attribute for segmentation + self.masks = None + + mock_result = MockUltralyticsResult() + # This should handle the segmentation-only case + # Note: Will fail if masks are not properly set, but that's expected behavior + try: + _ = Detections.from_ultralytics(mock_result) + # If masks are properly implemented, this should work + except (AttributeError, TypeError): + # Expected if masks aren't properly mocked + pass + + def test_from_ultralytics_with_valid_boxes(self): + """Test that from_ultralytics works correctly with valid boxes.""" + # Create a mock ultralytics result with valid boxes + class MockBoxes: + def __init__(self): + self.cls = self._MockTensor([0, 1]) + self.xyxy = self._MockTensor([[10, 20, 30, 40], [50, 60, 70, 80]]) + self.conf = self._MockTensor([0.9, 0.8]) + self.id = None + + class _MockTensor: + def __init__(self, data): + self.data = np.array(data) + + def cpu(self): + return self + + def numpy(self): + return self.data + + def astype(self, dtype): + return self.data.astype(dtype) + + class MockUltralyticsResult: + def __init__(self): + self.boxes = MockBoxes() + self.names = {0: "person", 1: "car"} + self.masks = None + + mock_result = MockUltralyticsResult() + detections = Detections.from_ultralytics(mock_result) + + assert len(detections) == 2 + assert np.array_equal( + detections.xyxy, np.array([[10, 20, 30, 40], [50, 60, 70, 80]]) + ) + assert np.array_equal(detections.confidence, np.array([0.9, 0.8])) + assert np.array_equal(detections.class_id, np.array([0, 1])) diff --git a/test/detection/utils/test_boxes.py b/test/detection/utils/test_boxes.py index 919989287..b27dd87d1 100644 --- a/test/detection/utils/test_boxes.py +++ b/test/detection/utils/test_boxes.py @@ -5,7 +5,12 @@ import numpy as np import pytest -from supervision.detection.utils.boxes import clip_boxes, move_boxes, scale_boxes +from supervision.detection.utils.boxes import ( + clip_boxes, + denormalize_boxes, + move_boxes, + scale_boxes, +) @pytest.mark.parametrize( @@ -142,3 +147,88 @@ def test_scale_boxes( with exception: result = scale_boxes(xyxy=xyxy, factor=factor) assert np.array_equal(result, expected_result) + + +@pytest.mark.parametrize( + "normalized_xyxy, resolution_wh, normalization_factor, expected_result, exception", + [ + ( + np.empty(shape=(0, 4)), + (1280, 720), + 1.0, + np.empty(shape=(0, 4)), + DoesNotRaise(), + ), # empty array + ( + np.array([[0.1, 0.2, 0.5, 0.6]]), + (1280, 720), + 1.0, + np.array([[128.0, 144.0, 640.0, 432.0]]), + DoesNotRaise(), + ), # single box with default normalization + ( + np.array([[0.1, 0.2, 0.5, 0.6], [0.3, 0.4, 0.7, 0.8]]), + (1280, 720), + 1.0, + np.array([[128.0, 144.0, 640.0, 432.0], [384.0, 288.0, 896.0, 576.0]]), + DoesNotRaise(), + ), # two boxes with default normalization + ( + np.array( + [[0.1, 0.2, 0.5, 0.6], [0.3, 0.4, 0.7, 0.8], [0.2, 0.1, 0.6, 0.5]] + ), + (1280, 720), + 1.0, + np.array( + [ + [128.0, 144.0, 640.0, 432.0], + [384.0, 288.0, 896.0, 576.0], + [256.0, 72.0, 768.0, 360.0], + ] + ), + DoesNotRaise(), + ), # three boxes - regression test for issue #1959 + ( + np.array([[10.0, 20.0, 50.0, 60.0]]), + (100, 200), + 100.0, + np.array([[10.0, 40.0, 50.0, 120.0]]), + DoesNotRaise(), + ), # single box with custom normalization factor + ( + np.array([[10.0, 20.0, 50.0, 60.0], [30.0, 40.0, 70.0, 80.0]]), + (100, 200), + 100.0, + np.array([[10.0, 40.0, 50.0, 120.0], [30.0, 80.0, 70.0, 160.0]]), + DoesNotRaise(), + ), # two boxes with custom normalization factor + ( + np.array([[0.0, 0.0, 1.0, 1.0]]), + (1920, 1080), + 1.0, + np.array([[0.0, 0.0, 1920.0, 1080.0]]), + DoesNotRaise(), + ), # full frame box + ( + np.array([[0.5, 0.5, 0.5, 0.5]]), + (640, 480), + 1.0, + np.array([[320.0, 240.0, 320.0, 240.0]]), + DoesNotRaise(), + ), # zero-area box (point) + ], +) +def test_denormalize_boxes( + normalized_xyxy: np.ndarray, + resolution_wh: tuple[int, int], + normalization_factor: float, + expected_result: np.ndarray, + exception: Exception, +) -> None: + with exception: + result = denormalize_boxes( + normalized_xyxy=normalized_xyxy, + resolution_wh=resolution_wh, + normalization_factor=normalization_factor, + ) + assert np.allclose(result, expected_result) From 61cca76acc479124bad10599878f44b6250aa896 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 13 Nov 2025 02:10:19 +0000 Subject: [PATCH 2/5] =?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/core.py | 5 ++++- test/detection/test_core.py | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/supervision/detection/core.py b/supervision/detection/core.py index ae6205dfb..bda2e7de3 100644 --- a/supervision/detection/core.py +++ b/supervision/detection/core.py @@ -296,7 +296,10 @@ def from_ultralytics(cls, ultralytics_results) -> Detections: class_id=np.arange(len(ultralytics_results)), ) - if hasattr(ultralytics_results, "boxes") and ultralytics_results.boxes is not None: + if ( + hasattr(ultralytics_results, "boxes") + and ultralytics_results.boxes is not None + ): class_id = ultralytics_results.boxes.cls.cpu().numpy().astype(int) class_names = np.array([ultralytics_results.names[i] for i in class_id]) return cls( diff --git a/test/detection/test_core.py b/test/detection/test_core.py index 1542f0a35..bf27f209e 100644 --- a/test/detection/test_core.py +++ b/test/detection/test_core.py @@ -816,6 +816,7 @@ def test_merge_inner_detection_object_pair( result = merge_inner_detection_object_pair(detection_1, detection_2) assert result == expected_result + class TestFromUltralytics: """Test suite for Detections.from_ultralytics method.""" @@ -824,6 +825,7 @@ def test_from_ultralytics_with_missing_boxes_attribute(self): Regression test for issue #2000. """ + # Create a mock ultralytics result without boxes attribute class MockUltralyticsResult: def __init__(self): @@ -839,6 +841,7 @@ def __init__(self): def test_from_ultralytics_with_boxes_none(self): """Test that from_ultralytics handles boxes=None (segmentation-only models).""" + # Create a mock ultralytics result with boxes=None class MockUltralyticsResult: def __init__(self): @@ -859,6 +862,7 @@ def __init__(self): def test_from_ultralytics_with_valid_boxes(self): """Test that from_ultralytics works correctly with valid boxes.""" + # Create a mock ultralytics result with valid boxes class MockBoxes: def __init__(self): From 35272b40d30b05effb13f62b13e10784f845fa11 Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Fri, 14 Nov 2025 12:38:55 +0100 Subject: [PATCH 3/5] remove ultralytics tests --- test/detection/test_core.py | 84 ------------------------------------- 1 file changed, 84 deletions(-) diff --git a/test/detection/test_core.py b/test/detection/test_core.py index bf27f209e..c57bea409 100644 --- a/test/detection/test_core.py +++ b/test/detection/test_core.py @@ -815,87 +815,3 @@ def test_merge_inner_detection_object_pair( with exception: result = merge_inner_detection_object_pair(detection_1, detection_2) assert result == expected_result - - -class TestFromUltralytics: - """Test suite for Detections.from_ultralytics method.""" - - def test_from_ultralytics_with_missing_boxes_attribute(self): - """Test that from_ultralytics handles missing boxes attribute gracefully. - - Regression test for issue #2000. - """ - - # Create a mock ultralytics result without boxes attribute - class MockUltralyticsResult: - def __init__(self): - self.names = {0: "class1", 1: "class2"} - # Intentionally not setting 'boxes' or 'obb' attribute - - mock_result = MockUltralyticsResult() - detections = Detections.from_ultralytics(mock_result) - - # Should return empty detections instead of crashing - assert len(detections) == 0 - assert detections.xyxy.shape == (0, 4) - - def test_from_ultralytics_with_boxes_none(self): - """Test that from_ultralytics handles boxes=None (segmentation-only models).""" - - # Create a mock ultralytics result with boxes=None - class MockUltralyticsResult: - def __init__(self): - self.boxes = None - self.names = {0: "class1"} - # Mock masks attribute for segmentation - self.masks = None - - mock_result = MockUltralyticsResult() - # This should handle the segmentation-only case - # Note: Will fail if masks are not properly set, but that's expected behavior - try: - _ = Detections.from_ultralytics(mock_result) - # If masks are properly implemented, this should work - except (AttributeError, TypeError): - # Expected if masks aren't properly mocked - pass - - def test_from_ultralytics_with_valid_boxes(self): - """Test that from_ultralytics works correctly with valid boxes.""" - - # Create a mock ultralytics result with valid boxes - class MockBoxes: - def __init__(self): - self.cls = self._MockTensor([0, 1]) - self.xyxy = self._MockTensor([[10, 20, 30, 40], [50, 60, 70, 80]]) - self.conf = self._MockTensor([0.9, 0.8]) - self.id = None - - class _MockTensor: - def __init__(self, data): - self.data = np.array(data) - - def cpu(self): - return self - - def numpy(self): - return self.data - - def astype(self, dtype): - return self.data.astype(dtype) - - class MockUltralyticsResult: - def __init__(self): - self.boxes = MockBoxes() - self.names = {0: "person", 1: "car"} - self.masks = None - - mock_result = MockUltralyticsResult() - detections = Detections.from_ultralytics(mock_result) - - assert len(detections) == 2 - assert np.array_equal( - detections.xyxy, np.array([[10, 20, 30, 40], [50, 60, 70, 80]]) - ) - assert np.array_equal(detections.confidence, np.array([0.9, 0.8])) - assert np.array_equal(detections.class_id, np.array([0, 1])) From f563c5a63472380ca261e64656a95e6a0ad4f33c Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Fri, 14 Nov 2025 12:53:58 +0100 Subject: [PATCH 4/5] update `denormalize_boxes` docstring and examples --- supervision/detection/utils/boxes.py | 57 ++++++++++++++++------------ test/detection/utils/test_boxes.py | 4 +- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/supervision/detection/utils/boxes.py b/supervision/detection/utils/boxes.py index 60542a43a..44b78cba8 100644 --- a/supervision/detection/utils/boxes.py +++ b/supervision/detection/utils/boxes.py @@ -95,24 +95,27 @@ def pad_boxes(xyxy: np.ndarray, px: int, py: int | None = None) -> np.ndarray: def denormalize_boxes( - normalized_xyxy: np.ndarray, + xyxy: np.ndarray, resolution_wh: tuple[int, int], normalization_factor: float = 1.0, ) -> np.ndarray: """ - Converts normalized bounding box coordinates to absolute pixel values. + Convert normalized bounding box coordinates to absolute pixel coordinates. + + Multiplies each bounding box coordinate by image size and divides by + `normalization_factor`, mapping values from normalized `[0, normalization_factor]` + to absolute pixel values for a given resolution. Args: - normalized_xyxy (np.ndarray): A numpy array of shape `(N, 4)` where each row - contains normalized coordinates in the format `(x_min, y_min, x_max, y_max)`, - with values between 0 and `normalization_factor`. - resolution_wh (Tuple[int, int]): A tuple `(width, height)` representing the - target image resolution. - normalization_factor (float, optional): The normalization range of the input - coordinates. Defaults to 1.0. + xyxy (`numpy.ndarray`): Normalized bounding boxes of shape `(N, 4)`, + where each row is `(x_min, y_min, x_max, y_max)`, values in + `[0, normalization_factor]`. + resolution_wh (`tuple[int, int]`): Target image resolution as `(width, height)`. + normalization_factor (`float`): Maximum value of input coordinate range. + Defaults to `1.0`. Returns: - np.ndarray: An array of shape `(N, 4)` with absolute coordinates in + (`numpy.ndarray`): Array of shape `(N, 4)` with absolute coordinates in `(x_min, y_min, x_max, y_max)` format. Examples: @@ -120,32 +123,38 @@ def denormalize_boxes( import numpy as np import supervision as sv - # Default normalization (0-1) normalized_xyxy = np.array([ [0.1, 0.2, 0.5, 0.6], - [0.3, 0.4, 0.7, 0.8] + [0.3, 0.4, 0.7, 0.8], + [0.2, 0.1, 0.6, 0.5] ]) - resolution_wh = (100, 200) - sv.denormalize_boxes(normalized_xyxy, resolution_wh) + sv.denormalize_boxes(normalized_xyxy, (1280, 720)) # array([ - # [ 10., 40., 50., 120.], - # [ 30., 80., 70., 160.] + # [128., 144., 640., 432.], + # [384., 288., 896., 576.], + # [256., 72., 768., 360.] # ]) + ``` + + ``` + import numpy as np + import supervision as sv - # Custom normalization (0-100) normalized_xyxy = np.array([ - [10., 20., 50., 60.], - [30., 40., 70., 80.] + [256., 128., 768., 640.] ]) - sv.denormalize_boxes(normalized_xyxy, resolution_wh, normalization_factor=100.0) + result = sv.denormalize_boxes( + normalized_xyxy, + (1280, 720), + normalization_factor=1024.0 + ) # array([ - # [ 10., 40., 50., 120.], - # [ 30., 80., 70., 160.] + # [320., 90., 960., 450.] # ]) ``` - """ # noqa E501 // docs + """ width, height = resolution_wh - result = normalized_xyxy.copy() + result = xyxy.copy() result[:, [0, 2]] = (result[:, [0, 2]] * width) / normalization_factor result[:, [1, 3]] = (result[:, [1, 3]] * height) / normalization_factor diff --git a/test/detection/utils/test_boxes.py b/test/detection/utils/test_boxes.py index b27dd87d1..787c970f4 100644 --- a/test/detection/utils/test_boxes.py +++ b/test/detection/utils/test_boxes.py @@ -219,7 +219,7 @@ def test_scale_boxes( ], ) def test_denormalize_boxes( - normalized_xyxy: np.ndarray, + xyxy: np.ndarray, resolution_wh: tuple[int, int], normalization_factor: float, expected_result: np.ndarray, @@ -227,7 +227,7 @@ def test_denormalize_boxes( ) -> None: with exception: result = denormalize_boxes( - normalized_xyxy=normalized_xyxy, + xyxy=xyxy, resolution_wh=resolution_wh, normalization_factor=normalization_factor, ) From dfd2a60855f0e3a70622ec36bfe3406728c5362b Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Fri, 14 Nov 2025 13:12:39 +0100 Subject: [PATCH 5/5] update `denormalize_boxes` docstring and examples; update `from_google_gemini_2_0`, `from_google_gemini_2_5` and `from_moondream` to use latest version of `denormalize_boxes` --- supervision/detection/utils/boxes.py | 14 +++++----- supervision/detection/vlm.py | 40 +++++++++++++--------------- test/detection/utils/test_boxes.py | 2 +- 3 files changed, 25 insertions(+), 31 deletions(-) diff --git a/supervision/detection/utils/boxes.py b/supervision/detection/utils/boxes.py index 44b78cba8..01fcdc769 100644 --- a/supervision/detection/utils/boxes.py +++ b/supervision/detection/utils/boxes.py @@ -123,12 +123,13 @@ def denormalize_boxes( import numpy as np import supervision as sv - normalized_xyxy = np.array([ + xyxy = np.array([ [0.1, 0.2, 0.5, 0.6], [0.3, 0.4, 0.7, 0.8], [0.2, 0.1, 0.6, 0.5] ]) - sv.denormalize_boxes(normalized_xyxy, (1280, 720)) + + sv.denormalize_boxes(xyxy, (1280, 720)) # array([ # [128., 144., 640., 432.], # [384., 288., 896., 576.], @@ -140,14 +141,11 @@ def denormalize_boxes( import numpy as np import supervision as sv - normalized_xyxy = np.array([ + xyxy = np.array([ [256., 128., 768., 640.] ]) - result = sv.denormalize_boxes( - normalized_xyxy, - (1280, 720), - normalization_factor=1024.0 - ) + + sv.denormalize_boxes(xyxy, (1280, 720), normalization_factor=1024.0) # array([ # [320., 90., 960., 450.] # ]) diff --git a/supervision/detection/vlm.py b/supervision/detection/vlm.py index 71207554e..2f9b60ddb 100644 --- a/supervision/detection/vlm.py +++ b/supervision/detection/vlm.py @@ -538,7 +538,7 @@ def from_google_gemini_2_0( return np.empty((0, 4)), None, np.empty((0,), dtype=str) labels = [] - boxes_list = [] + xyxy = [] for item in data: if "box_2d" not in item or "label" not in item: @@ -546,18 +546,16 @@ def from_google_gemini_2_0( labels.append(item["label"]) box = item["box_2d"] # Gemini bbox order is [y_min, x_min, y_max, x_max] - boxes_list.append( - denormalize_boxes( - np.array([box[1], box[0], box[3], box[2]]).astype(np.float64), - resolution_wh=(w, h), - normalization_factor=1000, - ) - ) + xyxy.append([box[1], box[0], box[3], box[2]]) - if not boxes_list: + if len(xyxy) == 0: return np.empty((0, 4)), None, np.empty((0,), dtype=str) - xyxy = np.array(boxes_list) + xyxy = denormalize_boxes( + np.array(xyxy, dtype=np.float64), + resolution_wh=(w, h), + normalization_factor=1000, + ) class_name = np.array(labels) class_id = None @@ -649,10 +647,10 @@ def from_google_gemini_2_5( box = item["box_2d"] # Gemini bbox order is [y_min, x_min, y_max, x_max] absolute_bbox = denormalize_boxes( - np.array([box[1], box[0], box[3], box[2]]).astype(np.float64), + np.array([[box[1], box[0], box[3], box[2]]]).astype(np.float64), resolution_wh=(w, h), normalization_factor=1000, - ) + )[0] boxes_list.append(absolute_bbox) if "mask" in item: @@ -735,7 +733,7 @@ def from_google_gemini_2_5( def from_moondream( result: dict, resolution_wh: tuple[int, int], -) -> tuple[np.ndarray]: +) -> np.ndarray: """ Parse and scale bounding boxes from moondream JSON output. @@ -773,7 +771,7 @@ def from_moondream( if "objects" not in result or not isinstance(result["objects"], list): return np.empty((0, 4), dtype=float) - denormalize_xyxy = [] + xyxy = [] for item in result["objects"]: if not all(k in item for k in ["x_min", "y_min", "x_max", "y_max"]): @@ -784,14 +782,12 @@ def from_moondream( x_max = item["x_max"] y_max = item["y_max"] - denormalize_xyxy.append( - denormalize_boxes( - np.array([x_min, y_min, x_max, y_max]).astype(np.float64), - resolution_wh=(w, h), - ) - ) + xyxy.append([x_min, y_min, x_max, y_max]) - if not denormalize_xyxy: + if len(xyxy) == 0: return np.empty((0, 4)) - return np.array(denormalize_xyxy, dtype=float) + return denormalize_boxes( + np.array(xyxy).astype(np.float64), + resolution_wh=(w, h), + ) diff --git a/test/detection/utils/test_boxes.py b/test/detection/utils/test_boxes.py index 787c970f4..66d0d999c 100644 --- a/test/detection/utils/test_boxes.py +++ b/test/detection/utils/test_boxes.py @@ -150,7 +150,7 @@ def test_scale_boxes( @pytest.mark.parametrize( - "normalized_xyxy, resolution_wh, normalization_factor, expected_result, exception", + "xyxy, resolution_wh, normalization_factor, expected_result, exception", [ ( np.empty(shape=(0, 4)),