# AICAM Drone YOLO ONNX – Training & Deployment Guide

## Overview

This guide describes the **correct, current workflow** for training, exporting, and deploying a YOLOv8 ONNX drone detection model used by the AICAM / Rasp project.

This document supersedes earlier OpenCV-DNN–centric guidance.  
The **authoritative runtime path is ONNX Runtime (CPU) + Picamera2**.

---

## Scope and Design Assumptions

- Single-purpose detector: **drone**
- Single-class YOLOv8 model
- Raspberry Pi runtime:
  - Picamera2
  - ONNX Runtime CPUExecutionProvider
  - System Python (no venv for preview)
- No Caffe SSD, no OpenCV DNN ONNX inference

---

## Environment Notes

### Training / Export
- Virtual environments are recommended
- GPU acceleration is optional (PC recommended)

### Raspberry Pi Runtime
- Prefer **system Python**
- Python venvs may break:
  - Qt preview
  - Picamera2 simplejpeg ABI
- Headless operation is fully supported

---

## Dataset Structure

```
data/
└── synth_drone_yolo/
    ├── images/
    │   ├── train/
    │   └── val/
    ├── labels/
    │   ├── train/
    │   └── val/
    └── data.yaml
```

Class list:
```
0: drone
```

---

## Adding More Photos (Images + Labels)

You can improve detection accuracy by adding more real-world photos.

### Step 1: Add Images
Copy new images into:

```
data/synth_drone_yolo/images/train/
```

Supported formats:
- `.jpg`
- `.jpeg`
- `.png`

### Step 2: Create Label Files
For each image, create a matching `.txt` file:

Example:
```
images/train/frame_00123.jpg
labels/train/frame_00123.txt
```

YOLO label format:
```
<class_id> <x_center> <y_center> <width> <height>
```

All values are normalized (0–1).

For this project:
```
class_id = 0
```

Example:
```
0 0.512 0.438 0.083 0.061
```

### Step 3: Hard Negatives (Strongly Recommended)

Add images containing **no drones**:
- birds
- planes
- clouds
- glare
- moving trees

Use:
- an empty `.txt` label file (recommended)

Hard negatives significantly reduce false positives.

---

## Training

Use Ultralytics YOLOv8 training as normal.

Ensure:
- `nc: 1`
- class list contains only `drone`

---

## Export to ONNX (Critical)

Export with **static shapes** and **no NMS**:

```bash
yolo export   model=runs/detect/train/weights/best.pt   format=onnx   imgsz=640   dynamic=False   nms=False   opset=12
```

Notes:
- If runtime output appears incorrect, try `opset=13` or `17`
- Input/output shapes must be fixed

---

## Verify ONNX with ONNX Runtime (Recommended)

```bash
python3 - <<'PY'
import onnxruntime as ort

model = "models/drone_yolov8n.onnx"
sess = ort.InferenceSession(model, providers=["CPUExecutionProvider"])

print("Inputs:")
for i in sess.get_inputs():
    print(i.name, i.shape)

print("Outputs:")
for o in sess.get_outputs():
    print(o.name, o.shape)
PY
```

Expected:
- Input: `[1, 3, 640, 640]`
- Output: `[1, 5, 8400]`

---

## Runtime Execution (Raspberry Pi)

### Recommended Command

```bash
python3 AICAM_Drone_YOLO_Only.py   --yolo-model /home/user/models/best.onnx   --conf 0.35   --min-area-px 2000   --confirm-hits 4   --confirm-window-s 1.5
```

---

## Storage Behavior (Important)

Storage defaults are defined in `build_arg_parser()`.

### Default Paths

- Primary mount:
  ```
  /media/user/disk
  ```
- Fallback:
  ```
  /home/user/.aicam
  ```
- Base subdirectory:
  ```
  aicam_drone
  ```

### Selection Rule

1. Use `<mount>/<base-subdir>` if writable
2. Otherwise fallback to `<fallback>/<base-subdir>`

Resulting structure:
```
<base>/
├── clips/
├── logs/
└── tmp/
```

---

## Preview and Python Virtual Environments

### Why Preview Fails in venvs

Preview uses `cv2.imshow()` → Qt/X11.  
venvs do not reliably inherit GUI libraries on Raspberry Pi.

### Correct Usage

#### Headless / venv-safe
```bash
python3 AICAM_Drone_YOLO_Only.py   --yolo-model models/best.onnx   --annotate-clips secondary
```

#### Live Preview (system Python)
```bash
deactivate
python3 AICAM_Drone_YOLO_Only.py   --yolo-model models/best.onnx   --preview   --annotate-preview
```

---

## Common Warnings

ONNX Runtime GPU discovery warnings are normal and safe to ignore on Raspberry Pi.

---

## Operational Notes

- `TRIGGER` events imply **drone detection**
- `reason: clip_len` indicates max clip duration reached
- Avoid running with `sudo` to prevent permission issues

---

## Summary

- ONNX Runtime is the authoritative inference path
- Static YOLOv8 ONNX models only
- Add photos by extending images + labels
- Storage is automatic and logged
- Preview is optional and GUI-dependent

---

## Python Virtual Environment (venv) Setup — REQUIRED

> This project **must be run inside a Python virtual environment** for model testing and training to ensure isolation, reproducibility, and to prevent system Python contamination.
>  
> **Exception:** Runtime-only Raspberry Pi deployments may continue to use system Python as noted elsewhere in this guide.

### 1. Install required system packages
```bash
sudo apt update
sudo apt install -y python3 python3-venv python3-pip build-essential
```

Verify Python:
```bash
python3 --version
```

### 2. Navigate to the TrainAI Drone YOLO project directory
```bash
cd ~/TrainAI-Drone-YOLO
```

### 3. Create the Python virtual environment
```bash
python3 -m venv .venv
```

### 4. Activate the virtual environment
```bash
source .venv/bin/activate
```

Verify activation:
```bash
which python
```

Expected:
```text
.../TrainAI-Drone-YOLO/.venv/bin/python
```

### 5. Upgrade pip tooling (inside venv only)
```bash
pip install --upgrade pip setuptools wheel
```

### 6. Install project dependencies
```bash
pip install -r requirements.txt
```

### 7. Confirm environment readiness
```bash
python -c "import torch; print(torch.__version__)"
python -c "import ultralytics; print('Ultralytics OK')"
```

### 8. Continue with training, export, and testing
All subsequent Python commands in this guide **must be executed with the venv active** when performing training or model tests.

### 9. Deactivate the virtual environment
```bash
deactivate
```

---
