Skip to content

Commit c5c478a

Browse files
committed
feat: add YOLO 2026 OpenVINO detection skill (Docker-based)
- Docker deployment using official openvino/ubuntu22_runtime image - Supports Intel NCS2 (MYRIAD), Intel GPU (iGPU/Arc), and CPU - AUTO device selector lets OpenVINO pick best available - FP16/INT8/FP32 precision options - YOLO26n with Ultralytics OpenVINO backend - JSONL stdin/stdout protocol (same as yolo-detection-2026) - Colab script for model export (runs on any platform)
1 parent 9137400 commit c5c478a

File tree

11 files changed

+936
-0
lines changed

11 files changed

+936
-0
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# ─── OpenVINO Detection — Runtime Image ───────────────────────────────────────
2+
# Uses official Intel OpenVINO runtime image (includes GPU drivers).
3+
# Built locally on user's machine.
4+
#
5+
# Build: docker build -t aegis-openvino-detect .
6+
# Run: docker run -i --rm --device /dev/dri --device /dev/bus/usb \
7+
# -v /tmp/aegis_detection:/tmp/aegis_detection \
8+
# aegis-openvino-detect
9+
10+
FROM openvino/ubuntu22_runtime:latest
11+
12+
USER root
13+
14+
# ─── System dependencies ─────────────────────────────────────────────────────
15+
RUN apt-get update && apt-get install -y --no-install-recommends \
16+
python3-pip \
17+
usbutils \
18+
libusb-1.0-0 \
19+
&& rm -rf /var/lib/apt/lists/*
20+
21+
# ─── Python dependencies ─────────────────────────────────────────────────────
22+
COPY requirements.txt /app/requirements.txt
23+
RUN pip3 install --no-cache-dir -r /app/requirements.txt
24+
25+
# ─── Application code ────────────────────────────────────────────────────────
26+
COPY scripts/ /app/scripts/
27+
COPY models/ /app/models/
28+
29+
WORKDIR /app
30+
31+
# ─── Shared volume for frame exchange ────────────────────────────────────────
32+
VOLUME ["/tmp/aegis_detection"]
33+
34+
ENV PYTHONUNBUFFERED=1
35+
36+
# ─── Entry point ─────────────────────────────────────────────────────────────
37+
ENTRYPOINT ["python3", "scripts/detect.py"]
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
---
2+
name: yolo-detection-2026-openvino
3+
description: "OpenVINO — real-time object detection via Docker (NCS2, Intel GPU, CPU)"
4+
version: 1.0.0
5+
icon: assets/icon.png
6+
entry: scripts/detect.py
7+
deploy: deploy.sh
8+
runtime: docker
9+
10+
requirements:
11+
docker: ">=20.10"
12+
platforms: ["linux", "macos", "windows"]
13+
14+
parameters:
15+
- name: auto_start
16+
label: "Auto Start"
17+
type: boolean
18+
default: false
19+
group: Lifecycle
20+
21+
- name: confidence
22+
label: "Confidence Threshold"
23+
type: number
24+
min: 0.1
25+
max: 1.0
26+
default: 0.5
27+
group: Model
28+
29+
- name: classes
30+
label: "Detect Classes"
31+
type: string
32+
default: "person,car,dog,cat"
33+
group: Model
34+
35+
- name: fps
36+
label: "Processing FPS"
37+
type: select
38+
options: [0.2, 0.5, 1, 3, 5, 15]
39+
default: 5
40+
group: Performance
41+
42+
- name: input_size
43+
label: "Input Resolution"
44+
type: select
45+
options: [320, 640]
46+
default: 640
47+
group: Performance
48+
49+
- name: device
50+
label: "Inference Device"
51+
type: select
52+
options: ["AUTO", "CPU", "GPU", "MYRIAD"]
53+
default: "AUTO"
54+
description: "AUTO lets OpenVINO pick the fastest available device"
55+
group: Performance
56+
57+
- name: precision
58+
label: "Model Precision"
59+
type: select
60+
options: ["FP16", "INT8", "FP32"]
61+
default: "FP16"
62+
group: Performance
63+
64+
capabilities:
65+
live_detection:
66+
script: scripts/detect.py
67+
description: "Real-time object detection via OpenVINO"
68+
69+
category: detection
70+
mutex: detection
71+
---
72+
73+
# OpenVINO Object Detection
74+
75+
Real-time object detection using Intel OpenVINO runtime. Runs inside Docker for cross-platform support. Supports Intel NCS2 USB stick, Intel integrated GPU, Intel Arc discrete GPU, and any x86_64 CPU.
76+
77+
## Requirements
78+
79+
- **Docker Desktop 4.35+** (all platforms)
80+
- **Optional hardware**: Intel NCS2 USB, Intel iGPU, Intel Arc GPU
81+
- Falls back to CPU if no accelerator present
82+
83+
## How It Works
84+
85+
```
86+
┌─────────────────────────────────────────────────────┐
87+
│ Host (Aegis-AI) │
88+
│ frame.jpg → /tmp/aegis_detection/ │
89+
│ stdin ──→ ┌──────────────────────────────┐ │
90+
│ │ Docker Container │ │
91+
│ │ detect.py │ │
92+
│ │ ├─ loads OpenVINO IR model │ │
93+
│ │ ├─ reads frame from volume │ │
94+
│ │ └─ runs inference on device │ │
95+
│ stdout ←── │ → JSONL detections │ │
96+
│ └──────────────────────────────┘ │
97+
│ USB ──→ /dev/bus/usb (NCS2) │
98+
│ DRI ──→ /dev/dri (Intel GPU) │
99+
└─────────────────────────────────────────────────────┘
100+
```
101+
102+
## Supported Devices
103+
104+
| Device | Flag | Precision | ~Speed |
105+
|--------|------|-----------|--------|
106+
| Intel NCS2 | `MYRIAD` | FP16 | ~15ms |
107+
| Intel iGPU | `GPU` | FP16/INT8 | ~8ms |
108+
| Intel Arc | `GPU` | FP16/INT8 | ~4ms |
109+
| Any CPU | `CPU` | FP32/INT8 | ~25ms |
110+
| Auto | `AUTO` | Best | Auto |
111+
112+
## Protocol
113+
114+
Same JSONL as `yolo-detection-2026`:
115+
116+
```jsonl
117+
{"event": "ready", "model": "yolo26n_openvino", "device": "GPU", "format": "openvino_ir", "classes": 80}
118+
{"event": "detections", "frame_id": 42, "camera_id": "front_door", "objects": [{"class": "person", "confidence": 0.85, "bbox": [100, 50, 300, 400]}]}
119+
{"event": "perf_stats", "total_frames": 50, "timings_ms": {"inference": {"avg": 8.1, "p50": 7.9, "p95": 10.2}}}
120+
```
121+
122+
## Installation
123+
124+
```bash
125+
./deploy.sh
126+
```
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# OpenVINO Detection Skill — Configuration Schema
2+
# Parsed by Aegis skill-registry-service.cjs → parseConfigYaml()
3+
4+
params:
5+
- key: auto_start
6+
label: Auto Start
7+
type: boolean
8+
default: false
9+
description: "Start this skill automatically when Aegis launches"
10+
11+
- key: confidence
12+
label: Confidence Threshold
13+
type: number
14+
default: 0.5
15+
description: "Minimum detection confidence (0.1–1.0)"
16+
17+
- key: fps
18+
label: Frame Rate
19+
type: select
20+
default: 5
21+
description: "Detection processing rate"
22+
options:
23+
- { value: 0.2, label: "Ultra Low (0.2 FPS)" }
24+
- { value: 0.5, label: "Low (0.5 FPS)" }
25+
- { value: 1, label: "Normal (1 FPS)" }
26+
- { value: 3, label: "Active (3 FPS)" }
27+
- { value: 5, label: "High (5 FPS)" }
28+
- { value: 15, label: "Real-time (15 FPS)" }
29+
30+
- key: classes
31+
label: Detection Classes
32+
type: string
33+
default: "person,car,dog,cat"
34+
description: "Comma-separated COCO class names to detect"
35+
36+
- key: input_size
37+
label: Input Resolution
38+
type: select
39+
default: 640
40+
description: "Image size for inference — OpenVINO handles 640 well on most hardware"
41+
options:
42+
- { value: 320, label: "320×320 (fastest)" }
43+
- { value: 640, label: "640×640 (recommended)" }
44+
45+
- key: device
46+
label: Inference Device
47+
type: select
48+
default: AUTO
49+
description: "OpenVINO device — AUTO picks best available"
50+
options:
51+
- { value: AUTO, label: "Auto-detect (best available)" }
52+
- { value: CPU, label: "CPU" }
53+
- { value: GPU, label: "Intel GPU (iGPU / Arc)" }
54+
- { value: MYRIAD, label: "Intel NCS2 (Myriad X)" }
55+
56+
- key: precision
57+
label: Model Precision
58+
type: select
59+
default: FP16
60+
description: "FP16 is fastest on GPU/NCS2; INT8 is fastest on CPU; FP32 is most accurate"
61+
options:
62+
- { value: FP16, label: "FP16 (recommended for GPU/NCS2)" }
63+
- { value: INT8, label: "INT8 (fastest on CPU)" }
64+
- { value: FP32, label: "FP32 (most accurate)" }
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
@echo off
2+
REM deploy.bat — Docker-based bootstrapper for OpenVINO Detection Skill (Windows)
3+
4+
setlocal enabledelayedexpansion
5+
6+
set "SKILL_DIR=%~dp0"
7+
set "IMAGE_NAME=aegis-openvino-detect"
8+
set "IMAGE_TAG=latest"
9+
set "LOG_PREFIX=[openvino-deploy]"
10+
11+
REM ─── Check Docker ────────────────────────────────────────────────────────
12+
where docker >nul 2>&1
13+
if %errorlevel% neq 0 (
14+
echo %LOG_PREFIX% ERROR: Docker not found. 1>&2
15+
echo {"event": "error", "stage": "docker", "message": "Docker not found"}
16+
exit /b 1
17+
)
18+
19+
docker info >nul 2>&1
20+
if %errorlevel% neq 0 (
21+
echo %LOG_PREFIX% ERROR: Docker daemon not running. 1>&2
22+
echo {"event": "error", "stage": "docker", "message": "Docker daemon not running"}
23+
exit /b 1
24+
)
25+
26+
echo {"event": "progress", "stage": "docker", "message": "Docker ready"}
27+
28+
REM ─── Build Docker image ──────────────────────────────────────────────────
29+
echo %LOG_PREFIX% Building Docker image... 1>&2
30+
echo {"event": "progress", "stage": "build", "message": "Building Docker image..."}
31+
32+
docker build -t %IMAGE_NAME%:%IMAGE_TAG% "%SKILL_DIR%"
33+
if %errorlevel% neq 0 (
34+
echo {"event": "error", "stage": "build", "message": "Docker image build failed"}
35+
exit /b 1
36+
)
37+
38+
echo {"event": "progress", "stage": "build", "message": "Docker image ready"}
39+
40+
REM ─── Probe devices ──────────────────────────────────────────────────────
41+
docker run --rm --privileged %IMAGE_NAME%:%IMAGE_TAG% python3 scripts/device_probe.py >nul 2>&1
42+
43+
REM ─── Set run command ─────────────────────────────────────────────────────
44+
set "RUN_CMD=docker run -i --rm --privileged -v /tmp/aegis_detection:/tmp/aegis_detection --env AEGIS_SKILL_ID --env AEGIS_SKILL_PARAMS --env PYTHONUNBUFFERED=1 %IMAGE_NAME%:%IMAGE_TAG%"
45+
46+
echo {"event": "complete", "status": "success", "run_command": "%RUN_CMD%", "message": "OpenVINO skill installed"}
47+
exit /b 0
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#!/usr/bin/env bash
2+
# deploy.sh — Docker-based bootstrapper for OpenVINO Detection Skill
3+
#
4+
# Builds the Docker image locally and verifies device availability.
5+
# Called by Aegis skill-runtime-manager during installation.
6+
7+
set -euo pipefail
8+
9+
SKILL_DIR="$(cd "$(dirname "$0")" && pwd)"
10+
IMAGE_NAME="aegis-openvino-detect"
11+
IMAGE_TAG="latest"
12+
LOG_PREFIX="[openvino-deploy]"
13+
14+
log() { echo "$LOG_PREFIX $*" >&2; }
15+
emit() { echo "$1"; }
16+
17+
# ─── Step 1: Check Docker ────────────────────────────────────────────────────
18+
19+
DOCKER_CMD=""
20+
for cmd in docker podman; do
21+
if command -v "$cmd" &>/dev/null; then
22+
DOCKER_CMD="$cmd"
23+
break
24+
fi
25+
done
26+
27+
if [ -z "$DOCKER_CMD" ]; then
28+
log "ERROR: Docker (or Podman) not found."
29+
emit '{"event": "error", "stage": "docker", "message": "Docker not found. Install Docker Desktop 4.35+"}'
30+
exit 1
31+
fi
32+
33+
if ! "$DOCKER_CMD" info &>/dev/null; then
34+
log "ERROR: Docker daemon is not running."
35+
emit '{"event": "error", "stage": "docker", "message": "Docker daemon not running"}'
36+
exit 1
37+
fi
38+
39+
DOCKER_VER=$("$DOCKER_CMD" version --format '{{.Server.Version}}' 2>/dev/null || echo "unknown")
40+
log "Using $DOCKER_CMD (version: $DOCKER_VER)"
41+
emit "{\"event\": \"progress\", \"stage\": \"docker\", \"message\": \"Docker ready ($DOCKER_VER)\"}"
42+
43+
# ─── Step 2: Detect platform for device access ──────────────────────────────
44+
45+
PLATFORM="$(uname -s)"
46+
DEVICE_FLAGS=""
47+
48+
case "$PLATFORM" in
49+
Linux)
50+
# Pass Intel GPU and USB devices
51+
[ -d /dev/dri ] && DEVICE_FLAGS="--device /dev/dri"
52+
[ -d /dev/bus/usb ] && DEVICE_FLAGS="$DEVICE_FLAGS --device /dev/bus/usb"
53+
[ -z "$DEVICE_FLAGS" ] && DEVICE_FLAGS="--privileged"
54+
log "Platform: Linux — devices: $DEVICE_FLAGS"
55+
;;
56+
Darwin)
57+
log "Platform: macOS — Docker Desktop USB/IP for NCS2, CPU fallback available"
58+
DEVICE_FLAGS="--privileged"
59+
;;
60+
MINGW*|MSYS*|CYGWIN*)
61+
log "Platform: Windows — Docker Desktop USB/IP"
62+
DEVICE_FLAGS="--privileged"
63+
;;
64+
*)
65+
DEVICE_FLAGS="--privileged"
66+
;;
67+
esac
68+
69+
emit "{\"event\": \"progress\", \"stage\": \"platform\", \"message\": \"Platform: $PLATFORM\"}"
70+
71+
# ─── Step 3: Build Docker image ─────────────────────────────────────────────
72+
73+
log "Building Docker image: $IMAGE_NAME:$IMAGE_TAG ..."
74+
emit '{"event": "progress", "stage": "build", "message": "Building Docker image..."}'
75+
76+
if "$DOCKER_CMD" build -t "$IMAGE_NAME:$IMAGE_TAG" "$SKILL_DIR" 2>&1 | while read -r line; do
77+
log "$line"
78+
done; then
79+
log "Docker image built successfully"
80+
emit '{"event": "progress", "stage": "build", "message": "Docker image ready"}'
81+
else
82+
log "ERROR: Docker build failed"
83+
emit '{"event": "error", "stage": "build", "message": "Docker image build failed"}'
84+
exit 1
85+
fi
86+
87+
# ─── Step 4: Probe devices ──────────────────────────────────────────────────
88+
89+
log "Probing OpenVINO devices..."
90+
emit '{"event": "progress", "stage": "probe", "message": "Checking OpenVINO devices..."}'
91+
92+
PROBE_OUTPUT=$("$DOCKER_CMD" run --rm $DEVICE_FLAGS \
93+
"$IMAGE_NAME:$IMAGE_TAG" python3 scripts/device_probe.py 2>/dev/null) || true
94+
95+
if echo "$PROBE_OUTPUT" | grep -q '"accelerator_found": true'; then
96+
log "Hardware accelerator detected (GPU/NCS2)"
97+
emit '{"event": "progress", "stage": "probe", "message": "Hardware accelerator detected"}'
98+
else
99+
log "No accelerator — CPU mode available"
100+
emit '{"event": "progress", "stage": "probe", "message": "CPU mode (no GPU/NCS2 detected)"}'
101+
fi
102+
103+
# ─── Step 5: Build run command ───────────────────────────────────────────────
104+
105+
RUN_CMD="$DOCKER_CMD run -i --rm $DEVICE_FLAGS"
106+
RUN_CMD="$RUN_CMD -v /tmp/aegis_detection:/tmp/aegis_detection"
107+
RUN_CMD="$RUN_CMD --env AEGIS_SKILL_ID --env AEGIS_SKILL_PARAMS --env PYTHONUNBUFFERED=1"
108+
RUN_CMD="$RUN_CMD $IMAGE_NAME:$IMAGE_TAG"
109+
110+
log "Runtime command: $RUN_CMD"
111+
112+
emit "{\"event\": \"complete\", \"status\": \"success\", \"run_command\": \"$RUN_CMD\", \"message\": \"OpenVINO skill installed\"}"
113+
log "Done!"
114+
exit 0

0 commit comments

Comments
 (0)