import cv2
import numpy as np
from stretch4_body.subsystem.cameras import *
from stretch4_body.subsystem.cameras.detectors.detector_ai_models import AIModelWrapper
# RTMLIB imports
from rtmlib import YOLOX
from rtmlib.tools.base import RTMLIB_SETTINGS
# Configure rtmlib to utilize the Intel GPU or NPU via OpenVINO Execution Provider
RTMLIB_SETTINGS['onnxruntime']['npu'] = ('OpenVINOExecutionProvider', {'device_type': 'NPU'})
RTMLIB_SETTINGS['onnxruntime']['gpu'] = ('OpenVINOExecutionProvider', {'device_type': 'GPU'})
class YOLOXWrapper(AIModelWrapper):
def __init__(self):
self.coco_classes = [
"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",
"fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
"elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
"skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",
"tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
"sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
"potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard",
"cell phone", "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase",
"scissors", "teddy bear", "hair drier", "toothbrush", "monitor", "can", "bottle", "tennis ball", "ball", "tape", "mug", "remote control", "desk"
]
self.model = self.init_model()
def name(self) -> str:
return "YOLOX Object Detection"
def init_model(self):
device = 'gpu' # npu, cpu, gpu
backend = 'onnxruntime' # We use onnxruntime to route to the OpenVINO NPU Provider
# Provide a URL to a COCO yolox model. rtmlib will cache it automatically.
url = 'https://github.com/Megvii-BaseDetection/YOLOX/releases/download/0.1.1rc0/yolox_tiny.onnx'
return YOLOX(url, mode='multiclass',model_input_size=(416, 416), backend=backend, device=device)
def run_model(self, img: np.ndarray):
return self.model(img)
def visualize_results(self, img: np.ndarray, result_from_run_model) -> np.ndarray:
bboxes, cls_inds = result_from_run_model
h, w = img.shape[:2]
img_area = h * w
for bbox, cls_id in zip(bboxes, cls_inds):
x1, y1, x2, y2 = map(int, bbox[:4])
area = (x2 - x1) * (y2 - y1)
# Color based on relative size (Green for small, Red for large)
ratio = min(1.0, max(0.0, np.sqrt(area / img_area)))
hue = int((1.0 - ratio) * 120)
hsv = np.uint8([[[hue, 255, 255]]])
color = tuple(map(int, cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)[0][0]))
cv2.rectangle(img, (x1, y1), (x2, y2), color, 3)
label = self.coco_classes[int(cls_id)] if int(cls_id) < len(self.coco_classes) else str(cls_id)
label = f"{label.capitalize()}"
# Render a solid background for the text
font_scale = 0.8
thickness = 2
(t_w, t_h), baseline = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, font_scale, thickness)
y_label_bg = max(y1, t_h + 10)
cv2.rectangle(img, (x1, y_label_bg - t_h - 10), (x1 + t_w + 10, y_label_bg), color, -1)
# Draw white text over the solid background (anti-aliased)
cv2.putText(img, label, (x1 + 5, y_label_bg - 5), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (255, 255, 255), thickness, cv2.LINE_AA)
return img
# Instantiate the custom model wrapper
yolox_model = YOLOXWrapper()
# Start the left camera stream passing the AI model to the pipeline
# for image_frame in stream_center_camera(ai_models_to_use=[yolox_model]):
# if image_frame is None:
# continue
# results = image_frame.ai_model_results[0]
# annotated_image = yolox_model.visualize_results(image_frame.image.copy(), results)
# cv2.namedWindow(yolox_model.name(), cv2.WINDOW_NORMAL)
# cv2.imshow(yolox_model.name(), annotated_image)
# if cv2.waitKey(1) == ord('q'):
# break
for synced_frame in stream_gripper_camera(ai_models_to_use=[yolox_model]):
if synced_frame is None:
continue
image_frame =synced_frame.left
results = image_frame.ai_model_results[0]
annotated_image = yolox_model.visualize_results(image_frame.image.copy(), results)
cv2.namedWindow(yolox_model.name(), cv2.WINDOW_NORMAL)
cv2.imshow(yolox_model.name(), annotated_image)
if cv2.waitKey(1) == ord('q'):
break