| from typing import Dict, List, Tuple, Union |
|
|
| import cv2 |
| import numpy as np |
|
|
| from inference.core.entities.requests.inference import ( |
| InstanceSegmentationInferenceRequest, |
| KeypointsDetectionInferenceRequest, |
| ObjectDetectionInferenceRequest, |
| ) |
| from inference.core.entities.responses.inference import ( |
| InstanceSegmentationPrediction, |
| Keypoint, |
| KeypointsPrediction, |
| ObjectDetectionInferenceResponse, |
| ObjectDetectionPrediction, |
| Point, |
| ) |
| from inference.core.utils.image_utils import load_image_rgb, np_image_to_base64 |
|
|
|
|
| def draw_detection_predictions( |
| inference_request: Union[ |
| ObjectDetectionInferenceRequest, |
| InstanceSegmentationInferenceRequest, |
| KeypointsDetectionInferenceRequest, |
| ], |
| inference_response: Union[ |
| ObjectDetectionInferenceResponse, |
| InstanceSegmentationPrediction, |
| KeypointsPrediction, |
| ], |
| colors: Dict[str, str], |
| ) -> bytes: |
| image = load_image_rgb(inference_request.image) |
| for box in inference_response.predictions: |
| color = tuple( |
| int(colors.get(box.class_name, "#4892EA")[i : i + 2], 16) for i in (1, 3, 5) |
| ) |
| image = draw_bbox( |
| image=image, |
| box=box, |
| color=color, |
| thickness=inference_request.visualization_stroke_width, |
| ) |
| if hasattr(box, "points"): |
| image = draw_instance_segmentation_points( |
| image=image, |
| points=box.points, |
| color=color, |
| thickness=inference_request.visualization_stroke_width, |
| ) |
| if hasattr(box, "keypoints"): |
| draw_keypoints( |
| image=image, |
| keypoints=box.keypoints, |
| color=color, |
| thickness=inference_request.visualization_stroke_width, |
| ) |
| if inference_request.visualization_labels: |
| image = draw_labels( |
| image=image, |
| box=box, |
| color=color, |
| ) |
| return np_image_to_base64(image=image) |
|
|
|
|
| def draw_bbox( |
| image: np.ndarray, |
| box: ObjectDetectionPrediction, |
| color: Tuple[int, ...], |
| thickness: int, |
| ) -> np.ndarray: |
| left_top, right_bottom = bbox_to_points(box=box) |
| return cv2.rectangle( |
| image, |
| left_top, |
| right_bottom, |
| color=color, |
| thickness=thickness, |
| ) |
|
|
|
|
| def draw_instance_segmentation_points( |
| image: np.ndarray, |
| points: List[Point], |
| color: Tuple[int, ...], |
| thickness: int, |
| ) -> np.ndarray: |
| points_array = np.array([(int(p.x), int(p.y)) for p in points], np.int32) |
| if len(points) > 2: |
| image = cv2.polylines( |
| image, |
| [points_array], |
| isClosed=True, |
| color=color, |
| thickness=thickness, |
| ) |
| return image |
|
|
|
|
| def draw_keypoints( |
| image: np.ndarray, |
| keypoints: List[Keypoint], |
| color: Tuple[int, ...], |
| thickness: int, |
| ) -> None: |
| for keypoint in keypoints: |
| center_coordinates = (round(keypoint.x), round(keypoint.y)) |
| image = cv2.circle( |
| image, |
| center_coordinates, |
| thickness, |
| color, |
| -1, |
| ) |
|
|
|
|
| def draw_labels( |
| image: np.ndarray, |
| box: Union[ObjectDetectionPrediction, InstanceSegmentationPrediction], |
| color: Tuple[int, ...], |
| ) -> np.ndarray: |
| (x1, y1), _ = bbox_to_points(box=box) |
| text = f"{box.class_name} {box.confidence:.2f}" |
| (text_width, text_height), _ = cv2.getTextSize( |
| text, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1 |
| ) |
| button_size = (text_width + 20, text_height + 20) |
| button_img = np.full( |
| (button_size[1], button_size[0], 3), color[::-1], dtype=np.uint8 |
| ) |
| cv2.putText( |
| button_img, |
| text, |
| (10, 10 + text_height), |
| cv2.FONT_HERSHEY_SIMPLEX, |
| 0.5, |
| (255, 255, 255), |
| 1, |
| ) |
| end_x = min(x1 + button_size[0], image.shape[1]) |
| end_y = min(y1 + button_size[1], image.shape[0]) |
| image[y1:end_y, x1:end_x] = button_img[: end_y - y1, : end_x - x1] |
| return image |
|
|
|
|
| def bbox_to_points( |
| box: Union[ObjectDetectionPrediction, InstanceSegmentationPrediction], |
| ) -> Tuple[Tuple[int, int], Tuple[int, int]]: |
| x1 = int(box.x - box.width / 2) |
| x2 = int(box.x + box.width / 2) |
| y1 = int(box.y - box.height / 2) |
| y2 = int(box.y + box.height / 2) |
| return (x1, y1), (x2, y2) |
|
|