A real-time object detection desktop application built with YOLOv8 and PyQt6. Detects objects from a live webcam feed, logs every detection to PostgreSQL, and lets you teach it new objects by capturing training images and fine-tuning the model — without restarting the app.
- Live detection — runs YOLOv8 inference on every webcam frame with bounding-box overlays
- Detection history — queryable log of all detections stored in PostgreSQL
- Custom object training — capture frames, fine-tune YOLOv8, and hot-swap the new model in one workflow
- Buffered DB writes — detections are batched and flushed at a configurable interval to avoid hammering the database at 30 FPS
- Docker support — ships with a
docker-compose.ymlfor the app + PostgreSQL, with X11 forwarding for the Qt window
| Layer | Technology |
|---|---|
| UI | PyQt6 |
| Detection | YOLOv8 (ultralytics) |
| Camera | OpenCV |
| Database | PostgreSQL 16 + SQLAlchemy + Alembic |
| Container | Docker / docker-compose |
obj_detection/
├── main.py # Entry point — starts the Qt application
├── config.py # Settings loaded from environment / .env
├── camera/
│ └── camera_thread.py # Background QThread: reads webcam frames, emits RGB signals
├── detection/
│ ├── detector.py # DetectorService — wraps YOLO.predict(), supports hot-reload
│ ├── annotator.py # AnnotationRenderer — draws boxes/labels onto frames
│ └── logger.py # DetectionLoggerService — buffers detections, flushes to DB
├── database/
│ ├── models.py # SQLAlchemy ORM models (4 tables)
│ ├── crud.py # All database read/write operations
│ ├── connection.py # SessionLocal factory
│ └── migrations/ # Alembic migration scripts
├── gui/
│ ├── main_window.py # MainWindow — wires all services and widgets together
│ ├── camera_widget.py # "Live Detection" tab
│ ├── history_widget.py # "History" tab
│ └── add_object_widget.py # "Add Object" tab — capture + training UI
├── training/
│ ├── trainer.py # TrainingThread — runs YOLOv8 fine-tuning in background
│ └── dataset_builder.py # Exports captured images from DB into YOLO dataset format
├── scripts/
│ └── seed_coco_classes.py # Seeds the 80 COCO class names into the database
├── models/ # YOLO weight files (auto-downloaded on first run)
├── Dockerfile
├── docker-compose.yml
└── DOCKER_README.md
| Table | Purpose |
|---|---|
object_classes |
Class names; source is coco or custom |
detection_sessions |
One record per app run; tracks model used and start/end time |
detections |
Per-detection rows with confidence, normalised bounding box, and optional JPEG thumbnail |
training_images |
JPEG frames captured for custom training, tagged with train/val split |
- Python 3.12+
- PostgreSQL 16 (or use Docker)
- A webcam
# 1. Create and activate a virtual environment
python -m venv .venv
source .venv/bin/activate
# 2. Install dependencies
pip install -r requirements.txt
# 3. Configure environment
cp .env.example .env # then edit DATABASE_URL at minimum
# Required: DATABASE_URL=postgresql+psycopg2://user:pass@localhost:5432/objdet_db
# 4. Run database migrations
alembic upgrade head
# 5. Seed the 80 COCO class names
python scripts/seed_coco_classes.py
# 6. Launch
python main.py# Grant X11 access (Linux — needed once per session)
xhost +local:docker
# Start PostgreSQL + the app
docker compose up --buildThe app window will appear on your host display via X11 forwarding. See DOCKER_README.md for details on webcam passthrough and display configuration.
All settings are read from environment variables (or a .env file):
| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
(required) | SQLAlchemy connection string |
MODEL_PATH |
models/yolov8n.pt |
Path to YOLO weights file |
CAMERA_INDEX |
0 |
OpenCV camera index |
DETECTION_CONFIDENCE |
0.5 |
Minimum confidence threshold (0–1) |
LOG_INTERVAL_SECONDS |
1 |
How often buffered detections are flushed to the DB |
yolov8n.pt is downloaded automatically by ultralytics on first run if the file is not present.
- Open the Add Object tab.
- Enter a label name (e.g.
rubber duck) and an optional description. - Click Capture Frame while the target object is visible — aim for at least 20 frames from different angles. The first 80% are used for training, the rest for validation.
- Click Train Model. Fine-tuning runs for 50 epochs in a background thread (progress is shown inline).
- When training completes the new weights are hot-swapped into the live detector automatically — no restart needed.
pytest tests/