Skip to content

Commit 20e21a3

Browse files
committed
refactor: image manipulation
1 parent b3bf6c1 commit 20e21a3

File tree

19 files changed

+92
-144
lines changed

19 files changed

+92
-144
lines changed

src/arduino/app_bricks/camera_code_detection/__init__.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#
33
# SPDX-License-Identifier: MPL-2.0
44

5-
from .detection import Detection, CameraCodeDetection
6-
from .utils import draw_bounding_boxes, draw_bounding_box
5+
from .detection import CameraCodeDetection, Detection
76

8-
__all__ = ["CameraCodeDetection", "Detection", "draw_bounding_boxes", "draw_bounding_box"]
7+
__all__ = ["CameraCodeDetection", "Detection"]

src/arduino/app_bricks/camera_code_detection/detection.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import numpy as np
1212
from PIL.Image import Image
1313

14-
from arduino.app_peripherals.usb_camera import USBCamera
14+
from arduino.app_peripherals.camera import Camera
1515
from arduino.app_utils import brick, Logger
1616

1717
logger = Logger("CameraCodeDetection")
@@ -55,7 +55,7 @@ class CameraCodeDetection:
5555

5656
def __init__(
5757
self,
58-
camera: USBCamera = None,
58+
camera: Camera = None,
5959
detect_qr: bool = True,
6060
detect_barcode: bool = True,
6161
):
@@ -76,7 +76,7 @@ def __init__(
7676

7777
self.already_seen_codes = set()
7878

79-
self._camera = camera if camera else USBCamera()
79+
self._camera = camera if camera else Camera()
8080

8181
def start(self):
8282
"""Start the detector and begin scanning for codes."""
@@ -147,7 +147,7 @@ def on_error(self, callback: Callable[[Exception], None] | None):
147147
def loop(self):
148148
"""Main loop to capture frames and detect codes."""
149149
try:
150-
frame = self._camera.capture_bytes()
150+
frame = self._camera.capture()
151151
if frame is None:
152152
return
153153
except Exception as e:

src/arduino/app_bricks/object_detection/README.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,24 @@ The Object Detection Brick allows you to:
2323
```python
2424
import os
2525
from arduino.app_bricks.object_detection import ObjectDetection
26+
from arduino.app_utils.image import draw_bounding_boxes
2627

2728
object_detection = ObjectDetection()
2829

29-
# Image frame can be as bytes or PIL image
30-
frame = os.read("path/to/your/image.jpg")
30+
# Image can be provided as bytes or PIL.Image
31+
img = os.read("path/to/your/image.jpg")
3132

32-
out = object_detection.detect(frame)
33-
# is it possible to customize image type, confidence level and box overlap
34-
# out = object_detection.detect(frame, image_type = "png", confidence = 0.35, overlap = 0.5)
33+
out = object_detection.detect(img)
34+
# You can also provide a confidence level
35+
# out = object_detection.detect(frame, confidence = 0.35)
3536
if out and "detection" in out:
3637
for i, obj_det in enumerate(out["detection"]):
37-
# For every object detected, get its details
38+
# For every object detected, print its details
3839
detected_object = obj_det.get("class_name", None)
39-
bounding_box = obj_det.get("bounding_box_xyxy", None)
4040
confidence = obj_det.get("confidence", None)
41+
bounding_box = obj_det.get("bounding_box_xyxy", None)
4142

42-
# draw the bounding box and key points on the image
43-
out_image = object_detection.draw_bounding_boxes(frame, out)
43+
# Draw the bounding boxes
44+
out_image = draw_bounding_boxes(img, out)
4445
```
4546

src/arduino/app_bricks/object_detection/__init__.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
#
33
# SPDX-License-Identifier: MPL-2.0
44

5-
from PIL import Image
6-
from arduino.app_utils import brick, Logger, draw_bounding_boxes
5+
from arduino.app_utils import brick, Logger
76
from arduino.app_internal.core import EdgeImpulseRunnerFacade
87

98
logger = Logger("ObjectDetection")
@@ -54,19 +53,6 @@ def detect(self, image_bytes, image_type: str = "jpg", confidence: float = None)
5453
ret = super().infer_from_image(image_bytes, image_type)
5554
return self._extract_detection(ret, confidence)
5655

57-
def draw_bounding_boxes(self, image: Image.Image | bytes, detections: dict) -> Image.Image | None:
58-
"""Draw bounding boxes on an image enclosing detected objects using PIL.
59-
60-
Args:
61-
image: The input image to annotate. Can be a PIL Image object or raw image bytes.
62-
detections: Detection results containing object labels and bounding boxes.
63-
64-
Returns:
65-
Image with bounding boxes and key points drawn.
66-
None if no detection or invalid image.
67-
"""
68-
return draw_bounding_boxes(image, detections)
69-
7056
def _extract_detection(self, item, confidence: float = None):
7157
if not item:
7258
return None

src/arduino/app_bricks/object_detection/examples/object_detection_example.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,24 @@
33
# SPDX-License-Identifier: MPL-2.0
44

55
# EXAMPLE_NAME = "Object Detection"
6+
import os
67
from arduino.app_bricks.object_detection import ObjectDetection
8+
from arduino.app_utils.image import draw_bounding_boxes
79

810
object_detection = ObjectDetection()
911

10-
# Image frame can be as bytes or PIL image
11-
with open("image.png", "rb") as f:
12-
frame = f.read()
12+
# Image can be provided as bytes or PIL.Image
13+
img = os.read("path/to/your/image.jpg")
1314

14-
out = object_detection.detect(frame)
15-
# is it possible to customize image type, confidence level and box overlap
16-
# out = object_detection.detect(frame, image_type = "png", confidence = 0.35, overlap = 0.5)
15+
out = object_detection.detect(img)
16+
# You can also provide a confidence level
17+
# out = object_detection.detect(frame, confidence = 0.35)
1718
if out and "detection" in out:
1819
for i, obj_det in enumerate(out["detection"]):
19-
# For every object detected, get its details
20+
# For every object detected, print its details
2021
detected_object = obj_det.get("class_name", None)
21-
bounding_box = obj_det.get("bounding_box_xyxy", None)
2222
confidence = obj_det.get("confidence", None)
23+
bounding_box = obj_det.get("bounding_box_xyxy", None)
2324

24-
# draw the bounding box and key points on the image
25-
out_image = object_detection.draw_bounding_boxes(frame, out)
25+
# Draw the bounding boxes
26+
out_image = draw_bounding_boxes(img, out)

src/arduino/app_bricks/video_imageclassification/brick_compose.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ services:
1313
volumes:
1414
- "${CUSTOM_MODEL_PATH:-/home/arduino/.arduino-bricks/ei-models/}:${CUSTOM_MODEL_PATH:-/home/arduino/.arduino-bricks/ei-models/}"
1515
- "/run/udev:/run/udev"
16-
command: ["--model-file", "${EI_CLASSIFICATION_MODEL:-/models/ootb/ei/mobilenet-v2-224px.eim}", "--dont-print-predictions", "--mode", "streaming", "--preview-original-resolution", "--camera", "${VIDEO_DEVICE:-/dev/video1}"]
16+
command: ["--model-file", "${EI_CLASSIFICATION_MODEL:-/models/ootb/ei/mobilenet-v2-224px.eim}", "--dont-print-predictions", "--mode", "streaming", "--preview-original-resolution", "--gst-launch-args", "tcpserversrc host=0.0.0.0 port=5000 ! jpegdec ! videoconvert ! video/x-raw ! jpegenc"]
1717
healthcheck:
1818
test: [ "CMD-SHELL", "wget -q --spider http://ei-video-classification-runner:4912 || exit 1" ]
1919
interval: 2s

src/arduino/app_bricks/video_objectdetection/brick_compose.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ services:
1313
volumes:
1414
- "${CUSTOM_MODEL_PATH:-/home/arduino/.arduino-bricks/ei-models/}:${CUSTOM_MODEL_PATH:-/home/arduino/.arduino-bricks/ei-models/}"
1515
- "/run/udev:/run/udev"
16-
command: ["--model-file", "${EI_OBJ_DETECTION_MODEL:-/models/ootb/ei/yolo-x-nano.eim}", "--dont-print-predictions", "--mode", "streaming", "--force-target", "--preview-original-resolution", "--camera", "${VIDEO_DEVICE:-/dev/video1}"]
16+
command: ["--model-file", "${EI_OBJ_DETECTION_MODEL:-/models/ootb/ei/yolo-x-nano.eim}", "--dont-print-predictions", "--mode", "streaming", "--preview-original-resolution", "--gst-launch-args", "tcpserversrc host=0.0.0.0 port=5000 ! jpegdec ! videoconvert ! video/x-raw ! jpegenc"]
1717
healthcheck:
1818
test: [ "CMD-SHELL", "wget -q --spider http://ei-video-obj-detection-runner:4912 || exit 1" ]
1919
interval: 2s

src/arduino/app_bricks/visual_anomaly_detection/examples/object_detection_example.py

Lines changed: 0 additions & 25 deletions
This file was deleted.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# SPDX-FileCopyrightText: Copyright (C) 2025 ARDUINO SA <http://www.arduino.cc>
2+
#
3+
# SPDX-License-Identifier: MPL-2.0
4+
5+
# EXAMPLE_NAME = "Visual Anomaly Detection"
6+
import os
7+
from arduino.app_bricks.visual_anomaly_detection import VisualAnomalyDetection
8+
from arduino.app_utils.image import draw_anomaly_markers
9+
10+
anomaly_detection = VisualAnomalyDetection()
11+
12+
# Image can be provided as bytes or PIL.Image
13+
img = os.read("path/to/your/image.jpg")
14+
15+
out = anomaly_detection.detect(img)
16+
if out and "detection" in out:
17+
for i, anomaly in enumerate(out["detection"]):
18+
# For every anomaly detected, print its details
19+
detected_anomaly = anomaly.get("class_name", None)
20+
score = anomaly.get("score", None)
21+
bounding_box = anomaly.get("bounding_box_xyxy", None)
22+
23+
# Draw the bounding boxes
24+
out_image = draw_anomaly_markers(img, out)

src/arduino/app_peripherals/camera/examples/websocket_camera_proxy.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
1010
This example demonstrates how to use a WebSocketCamera as a proxy/relay.
1111
It receives frames from clients on one WebSocket server (127.0.0.1:8080) and
12-
forwards them as raw JPEG binary data to a TCP server (127.0.0.1:5001) at 30fps.
12+
forwards them as raw JPEG binary data to a TCP server (127.0.0.1:5000) at 30fps.
1313
1414
Usage:
1515
python websocket_camera_proxy.py [--input-port PORT] [--output-host HOST] [--output-port PORT]
@@ -22,7 +22,6 @@
2222
import sys
2323
import time
2424

25-
# Add the parent directory to the path to import from arduino package
2625
import os
2726

2827
from arduino.app_peripherals.camera import Camera
@@ -173,17 +172,17 @@ async def main():
173172
global running, camera
174173

175174
parser = argparse.ArgumentParser(description="WebSocket Camera Proxy")
176-
parser.add_argument("--input-port", type=int, default=8080,
175+
parser.add_argument("--input-port", type=int, default=8080,
177176
help="WebSocketCamera input port (default: 8080)")
178-
parser.add_argument("--output-host", default="127.0.0.1",
179-
help="Output TCP server host (default: 127.0.0.1)")
180-
parser.add_argument("--output-port", type=int, default=5001,
181-
help="Output TCP server port (default: 5001)")
182-
parser.add_argument("--fps", type=int, default=30,
177+
parser.add_argument("--output-host", default="0.0.0.0",
178+
help="Output TCP server host (default: 0.0.0.0)")
179+
parser.add_argument("--output-port", type=int, default=5000,
180+
help="Output TCP server port (default: 5000)")
181+
parser.add_argument("--fps", type=int, default=30,
183182
help="Target FPS for forwarding (default: 30)")
184-
parser.add_argument("--quality", type=int, default=80,
183+
parser.add_argument("--quality", type=int, default=80,
185184
help="JPEG quality 1-100 (default: 80)")
186-
parser.add_argument("--verbose", "-v", action="store_true",
185+
parser.add_argument("--verbose", "-v", action="store_true",
187186
help="Enable verbose logging")
188187

189188
args = parser.parse_args()
@@ -204,7 +203,8 @@ async def main():
204203
logger.info(f"Output: TCP server at {args.output_host}:{args.output_port}")
205204
logger.info(f"Target FPS: {args.fps}")
206205

207-
camera = Camera("ws://0.0.0.0:5001")
206+
from arduino.app_utils.image.image_editor import compressed_to_jpeg
207+
camera = Camera("ws://0.0.0.0:5000", transformer=compressed_to_jpeg(80))
208208

209209
try:
210210
# Start camera input and output connection tasks

0 commit comments

Comments
 (0)