From 3490c3e670381e7e61c2509f418c9e72b60dd890 Mon Sep 17 00:00:00 2001 From: James Gallagher Date: Fri, 3 Nov 2023 15:59:53 +0000 Subject: [PATCH 1/7] add azure data loader --- supervision/detection/core.py | 62 +++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/supervision/detection/core.py b/supervision/detection/core.py index 77bfca9d..adce6aa6 100644 --- a/supervision/detection/core.py +++ b/supervision/detection/core.py @@ -483,6 +483,68 @@ class Detections: xyxy = xywh_to_xyxy(boxes_xywh=xywh) return cls(xyxy=xyxy, mask=mask) + @classmethod + def from_azure_analyze_image(cls, azure_result: dict) -> Detections: + """ + Creates a Detections instance from Azure Image Analysis 4.0 + (https://learn.microsoft.com/en-us/azure/ai-services/computer-vision/concept-object-detection-40) + + Args: + azure_result (dict): The output Results instance from Azure Image Analysis + + Returns: + Detections: A new Detections object. + + Example: + ```python + >>> import supervision as sv + >>> import requests + >>> image = open(input, "rb").read() + + >>> endpoint = "https://.cognitiveservices.azure.com/" + + >>> self.headers = { + ... "Content-Type": "application/octet-stream", + ... "Ocp-Apim-Subscription-Key": self.subscription_key, + ... } + + >>> response = requests.post(endpoint, headers=self.headers, data=image).json() + + >>> detections = sv.Detections.from_azure_analyze_image(response) + """ + + xyxys, confidences, class_ids = [], [], {} + + for detection in azure_result["objectsResult"]["values"]: + bbox = detection["boundingBox"] + + tags = detection["tags"] + + x0 = bbox["x"] + y0 = bbox["y"] + x1 = x0 + bbox["w"] + y1 = y0 + bbox["h"] + + for tag in tags: + xyxys.append([x0, y0, x1, y1]) + confidences.append(tag["confidence"]) + + class_name = tag["name"] + + if class_name not in class_ids: + class_ids[class_name] = len(class_ids) + + class_ids.append(class_ids[class_name]) + + if len(xyxys) == 0: + return Detections.empty() + + return cls( + xyxy=np.array(xyxys), + class_id=np.array(class_ids), + confidence=np.array(confidences), + ) + @classmethod def from_paddledet(cls, paddledet_result) -> Detections: """ From c438b16e7487a13068777ca9c4cf1c60204c924f Mon Sep 17 00:00:00 2001 From: James Gallagher Date: Fri, 3 Nov 2023 16:11:16 +0000 Subject: [PATCH 2/7] update example --- supervision/detection/core.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/supervision/detection/core.py b/supervision/detection/core.py index adce6aa6..e9b51efe 100644 --- a/supervision/detection/core.py +++ b/supervision/detection/core.py @@ -502,13 +502,17 @@ class Detections: >>> image = open(input, "rb").read() >>> endpoint = "https://.cognitiveservices.azure.com/" + >>> subscription_key = "..." - >>> self.headers = { + >>> headers = { ... "Content-Type": "application/octet-stream", - ... "Ocp-Apim-Subscription-Key": self.subscription_key, + ... "Ocp-Apim-Subscription-Key": subscription_key ... } - >>> response = requests.post(endpoint, headers=self.headers, data=image).json() + >>> response = requests.post(endpoint, + ... headers=self.headers, + ... data=image + ... ).json() >>> detections = sv.Detections.from_azure_analyze_image(response) """ From b4b332a0e2ad3c5a3e4c5d5de6f483447947a7f1 Mon Sep 17 00:00:00 2001 From: James Gallagher Date: Mon, 27 Nov 2023 14:14:56 +0000 Subject: [PATCH 3/7] fix dict data type --- supervision/detection/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/supervision/detection/core.py b/supervision/detection/core.py index e9b51efe..9f7e8234 100644 --- a/supervision/detection/core.py +++ b/supervision/detection/core.py @@ -517,7 +517,7 @@ class Detections: >>> detections = sv.Detections.from_azure_analyze_image(response) """ - xyxys, confidences, class_ids = [], [], {} + xyxys, confidences, class_ids = [], [], [] for detection in azure_result["objectsResult"]["values"]: bbox = detection["boundingBox"] From fa8f31931c93a62b94a074fca738d3cf5f6a308e Mon Sep 17 00:00:00 2001 From: James Gallagher Date: Mon, 27 Nov 2023 14:16:52 +0000 Subject: [PATCH 4/7] fix dict data type --- supervision/detection/core.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/supervision/detection/core.py b/supervision/detection/core.py index 9f7e8234..57342f7b 100644 --- a/supervision/detection/core.py +++ b/supervision/detection/core.py @@ -519,6 +519,8 @@ class Detections: xyxys, confidences, class_ids = [], [], [] + class_map = {} + for detection in azure_result["objectsResult"]["values"]: bbox = detection["boundingBox"] @@ -535,10 +537,10 @@ class Detections: class_name = tag["name"] - if class_name not in class_ids: - class_ids[class_name] = len(class_ids) + if class_name not in class_map: + class_map[class_name] = len(class_ids) - class_ids.append(class_ids[class_name]) + class_ids.append(class_map[class_name]) if len(xyxys) == 0: return Detections.empty() From a31f9649475054906ebdd125b845f00c23fe2f42 Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Tue, 5 Dec 2023 13:46:15 +0100 Subject: [PATCH 5/7] Revise Detections.from_azure_analyze_image method for class mapping flexibility --- supervision/detection/core.py | 48 ++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/supervision/detection/core.py b/supervision/detection/core.py index 879e3c5a..75fd0a9c 100644 --- a/supervision/detection/core.py +++ b/supervision/detection/core.py @@ -1,7 +1,7 @@ from __future__ import annotations from dataclasses import astuple, dataclass -from typing import Any, Iterator, List, Optional, Tuple, Union +from typing import Any, Iterator, List, Optional, Tuple, Union, Dict import numpy as np @@ -461,7 +461,7 @@ class Detections: >>> from segment_anything import ( ... sam_model_registry, ... SamAutomaticMaskGenerator - ... ) + ... ) >>> sam_model_reg = sam_model_registry[MODEL_TYPE] >>> sam = sam_model_reg(checkpoint=CHECKPOINT_PATH).to(device=DEVICE) @@ -485,21 +485,29 @@ class Detections: return cls(xyxy=xyxy, mask=mask) @classmethod - def from_azure_analyze_image(cls, azure_result: dict) -> Detections: + def from_azure_analyze_image( + cls, + azure_result: dict, + class_map: Optional[Dict[int, str]] = None + ) -> Detections: """ Creates a Detections instance from Azure Image Analysis 4.0 (https://learn.microsoft.com/en-us/azure/ai-services/computer-vision/concept-object-detection-40) Args: - azure_result (dict): The output Results instance from Azure Image Analysis + azure_result (dict): The result from Azure Image Analysis. It should + contain detected objects and their bounding box coordinates. + class_map (Optional[Dict[int, str]]): A mapping ofclass IDs (int) to class + names (str). If None, a new mapping is created dynamically. Returns: Detections: A new Detections object. Example: ```python - >>> import supervision as sv >>> import requests + >>> import supervision as sv + >>> image = open(input, "rb").read() >>> endpoint = "https://.cognitiveservices.azure.com/" @@ -517,10 +525,17 @@ class Detections: >>> detections = sv.Detections.from_azure_analyze_image(response) """ + xyxy, confidences, class_ids = [], [], [] - xyxys, confidences, class_ids = [], [], [] + is_dynamic_mapping = class_map is None + if is_dynamic_mapping: + class_map = {} - class_map = {} + class_map = { + value: key + for key, value + in class_map.items() + } for detection in azure_result["objectsResult"]["values"]: bbox = detection["boundingBox"] @@ -533,21 +548,24 @@ class Detections: y1 = y0 + bbox["h"] for tag in tags: - xyxys.append([x0, y0, x1, y1]) - confidences.append(tag["confidence"]) - + confidence = tag["confidence"] class_name = tag["name"] + class_id = class_map.get(class_name, None) - if class_name not in class_map: - class_map[class_name] = len(class_ids) + if is_dynamic_mapping and class_id is None: + class_id = len(class_map) + class_map[class_name] = class_id - class_ids.append(class_map[class_name]) + if class_id is not None: + xyxy.append([x0, y0, x1, y1]) + confidences.append(confidence) + class_ids.append(class_id) - if len(xyxys) == 0: + if len(xyxy) == 0: return Detections.empty() return cls( - xyxy=np.array(xyxys), + xyxy=np.array(xyxy), class_id=np.array(class_ids), confidence=np.array(confidences), ) From 38b87d6098dcf2305cf5b50889f5a2e4226234cf Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Dec 2023 12:46:33 +0000 Subject: [PATCH 6/7] =?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 | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/supervision/detection/core.py b/supervision/detection/core.py index 75fd0a9c..7e3c1409 100644 --- a/supervision/detection/core.py +++ b/supervision/detection/core.py @@ -1,7 +1,7 @@ from __future__ import annotations from dataclasses import astuple, dataclass -from typing import Any, Iterator, List, Optional, Tuple, Union, Dict +from typing import Any, Dict, Iterator, List, Optional, Tuple, Union import numpy as np @@ -486,9 +486,7 @@ class Detections: @classmethod def from_azure_analyze_image( - cls, - azure_result: dict, - class_map: Optional[Dict[int, str]] = None + cls, azure_result: dict, class_map: Optional[Dict[int, str]] = None ) -> Detections: """ Creates a Detections instance from Azure Image Analysis 4.0 @@ -531,11 +529,7 @@ class Detections: if is_dynamic_mapping: class_map = {} - class_map = { - value: key - for key, value - in class_map.items() - } + class_map = {value: key for key, value in class_map.items()} for detection in azure_result["objectsResult"]["values"]: bbox = detection["boundingBox"] From cb5e9c0df07e15a06899429eb834c94f7db67a2d Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Tue, 5 Dec 2023 13:57:27 +0100 Subject: [PATCH 7/7] Added error handling in Detections.from_azure_analyze_image method --- supervision/detection/core.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/supervision/detection/core.py b/supervision/detection/core.py index 75fd0a9c..8d97bc03 100644 --- a/supervision/detection/core.py +++ b/supervision/detection/core.py @@ -525,6 +525,11 @@ class Detections: >>> detections = sv.Detections.from_azure_analyze_image(response) """ + if "error" in azure_result: + raise ValueError( + f'Azure API returned an error {azure_result["error"]["message"]}' + ) + xyxy, confidences, class_ids = [], [], [] is_dynamic_mapping = class_map is None