Detect helmets, vests, and masks in real-time — log every violation, stream live feeds to a web dashboard, and alert your team instantly.
Features · Quick Start · API Reference · Architecture · Contributing
Construction sites are among the most hazardous work environments. Manual supervision of PPE compliance is unreliable and resource-intensive. This project automates safety monitoring using YOLOv8 and exposes a production-ready FastAPI backend — supporting multiple camera feeds, a persistent violation log, a live web dashboard, and pluggable alert channels.
| Feature | Description |
|---|---|
| 🪖 Helmet Detection | Identifies whether workers are wearing hard hats |
| 🦺 Vest Detection | Detects high-visibility safety vests |
| 😷 Mask Detection | Monitors mask compliance on site |
| 🧍 Person Detection | Tracks worker presence in the frame |
| 📊 Live Counts Overlay | Real-time detection counts on the video feed |
| Feature | Description |
|---|---|
| 🌐 REST API | FastAPI backend with full CRUD, streaming, and export endpoints |
| 📷 Multi-Camera | Webcam, RTSP streams, and video files — unlimited concurrent feeds |
| 🗄️ Violation Log | Every violation saved to SQLite (dev) or PostgreSQL (prod) with frame snapshot |
| 📡 Live Dashboard | Bootstrap 5 web UI with MJPEG stream and real-time WebSocket counts |
| 📧 Email Alerts | Async SMTP alerts with violation frame attached |
| 🔗 Webhook Alerts | HTTP POST to any endpoint (Slack, Teams, custom) |
| 🐳 Docker | Production-ready Docker + docker-compose with PostgreSQL |
| ✅ Tests & CI | pytest unit + integration tests, GitHub Actions CI pipeline |
# 1. Clone the repo
git clone https://github.com/Ansarimajid/Construction-PPE-Detection.git
cd Construction-PPE-Detection
# 2. Install dependencies
pip install -r requirements/base.txt
# 3. Configure environment
cp .env.example .env
# Edit .env with your email credentials (optional)
# 4. Start the server
uvicorn app.main:app --reloadOpen http://localhost:8000 for the web dashboard, or http://localhost:8000/docs for the interactive API.
cp .env.example .env
# Edit .env with your settings
docker compose upThe full stack starts — FastAPI app + PostgreSQL + persistent violation frame storage. Open http://localhost:8000.
docker compose -f docker-compose.yml -f docker-compose.dev.yml upThe original single-file script still works as before:
conda env create -f yolo_env.yml && conda activate yolo
# or: pip install -r requirements/base.txt
python webcam.pyCopy .env.example to .env and fill in your values:
# Application
APP_ENV=dev
LOG_LEVEL=INFO
# Database (SQLite for dev, PostgreSQL for prod)
DATABASE_URL=sqlite+aiosqlite:///./ppe_detection.db
# Model
MODEL_PATH=Model/ppe.pt
DETECTION_CONFIDENCE=0.5
# Alert timing (seconds)
ALERT_COOLDOWN_SECONDS=10
# Email (Gmail — requires App Password)
SENDER_EMAIL=your_email@gmail.com
RECEIVER_EMAIL=receiver@example.com
EMAIL_PASSWORD=your_app_password
# Optional: generic HTTP webhook
WEBHOOK_URL=https://hooks.example.com/alertsGmail users: Generate an App Password — your regular password won't work with SMTP.
Never commit
.env— it's already in.gitignore.
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/health |
System health + active camera count |
GET |
/api/v1/metrics |
Per-camera detection counts |
GET |
/api/v1/cameras |
List all cameras |
POST |
/api/v1/cameras |
Add a camera |
POST |
/api/v1/cameras/{id}/start |
Start processing a camera |
POST |
/api/v1/cameras/{id}/stop |
Stop processing a camera |
GET |
/api/v1/violations |
Query violations (filter by camera, date, type) |
GET |
/api/v1/violations/export |
Download violations as CSV |
GET |
/api/v1/stream/{camera_id} |
MJPEG live video stream |
WS |
/api/v1/ws/{camera_id} |
WebSocket: live detection counts (JSON) |
Full interactive docs available at /docs (Swagger UI) and /redoc.
# Add camera
curl -X POST http://localhost:8000/api/v1/cameras \
-H "Content-Type: application/json" \
-d '{"name": "Site Entrance", "source_type": "webcam", "source_uri": "0"}'
# Start it (use the id returned above)
curl -X POST http://localhost:8000/api/v1/cameras/1/start
# Stream in browser
open http://localhost:8000/api/v1/stream/1curl -X POST http://localhost:8000/api/v1/cameras \
-H "Content-Type: application/json" \
-d '{"name": "Gate Camera", "source_type": "rtsp", "source_uri": "rtsp://192.168.1.100/stream"}'┌─────────────────────────────────────────────────────────────┐
│ FastAPI Application │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌────────────────┐ │
│ │ CameraManager│ │ PPEDetector │ │ViolationChecker│ │
│ │ (async tasks)│──▶│ (YOLOv8) │──▶│ (per-camera │ │
│ │ per camera │ │ inference │ │ state + rules)│ │
│ └──────────────┘ └──────────────┘ └───────┬────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ AlertDispatcher │ │
│ │ ┌────────────┐ │ │
│ │ │EmailHandler│ │ │
│ │ │WebhookHandl│ │ │
│ │ │DB Handler │ │ │
│ │ └────────────┘ │ │
│ └─────────────────┘ │
│ │
│ REST API (/api/v1/*) MJPEG stream WebSocket counts │
│ SQLite / PostgreSQL violation_frames/ (filesystem) │
└─────────────────────────────────────────────────────────────┘
- Webcam —
source_type: "webcam",source_uri: "0"(device index) - RTSP —
source_type: "rtsp",source_uri: "rtsp://..." - Video file —
source_type: "file",source_uri: "/path/to/video.mp4"
All handlers run concurrently per violation. A failure in one (e.g. SMTP timeout) never blocks the others.
Construction-PPE-Detection/
├── app/
│ ├── main.py # FastAPI app factory + lifespan
│ ├── core/
│ │ ├── config.py # Pydantic settings (all env vars)
│ │ ├── detector.py # YOLOv8 wrapper
│ │ ├── violation_checker.py # Business rules, per-camera state
│ │ └── frame_annotator.py # Bounding box / overlay drawing
│ ├── camera/ # Webcam, RTSP, file sources + manager
│ ├── alerts/ # Email, webhook, database handlers
│ ├── api/routes/ # REST endpoints
│ ├── db/ # SQLAlchemy models + session
│ ├── schemas/ # Pydantic request/response models
│ └── static/ # Web dashboard (HTML/JS/CSS)
├── tests/
│ ├── unit/ # Violation checker, dispatcher, config
│ └── integration/ # API endpoint tests
├── docker/
│ ├── Dockerfile # Production image (python:3.11-slim)
│ └── Dockerfile.dev # Dev image with hot-reload
├── requirements/
│ ├── base.txt # Runtime dependencies
│ ├── dev.txt # + pytest, ruff
│ └── prod.txt # + gunicorn, asyncpg
├── docker-compose.yml # App + PostgreSQL (production)
├── docker-compose.dev.yml # SQLite + hot-reload (development)
├── pyproject.toml # Ruff config + project metadata
├── .env.example # Config template (commit this, not .env)
├── webcam.py # Legacy standalone script
└── Model/ppe.pt # YOLOv8 weights
pip install -r requirements/dev.txt
pytest tests/ -vTests use an in-memory SQLite database and mock the YOLO model — no webcam or GPU required.
The model detects 10 classes:
| Class | Color |
|---|---|
| Hardhat | Blue |
| Mask | Green |
| NO-Hardhat | Red |
| NO-Mask | Cyan |
| NO-Safety Vest | Magenta |
| Person | Yellow |
| Safety Cone | Purple |
| Safety Vest | Olive |
| Machinery | Teal |
| Vehicle | Gray |
Contributions are welcome! Here's how to get started:
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Install dev deps:
pip install -r requirements/dev.txt - Run tests before pushing:
pytest tests/ -v - Commit your changes:
git commit -m 'Add some feature' - Open a Pull Request
See CONTRIBUTING.md for detailed guidelines.
- Python 3.9+
- See
requirements/base.txtfor the full dependency list - Docker + Docker Compose (for containerised deployment)
- A Gmail App Password (for email alerts) — how to generate one
This project is licensed under the MIT License — see the LICENSE file for details.
- Ultralytics YOLOv8 for the detection backbone
- FastAPI for the async web framework
- The open-source computer vision community for datasets and insights
If this project helped you, consider giving it a star — it helps others find it!
