Programming lesson
Building a Real-Time PPE Detection System with YOLOv8: A Step-by-Step Tutorial
Learn how to build a real-time Personal Protective Equipment (PPE) detection system using YOLOv8 and Flask. This tutorial covers multi-source video input, model optimization, and web streaming.
Introduction: Why YOLOv8 for PPE Detection?
Personal Protective Equipment (PPE) compliance is critical in construction, manufacturing, and healthcare. With the rise of AI-powered safety systems, YOLOv8 offers a fast and accurate solution for real-time PPE detection. In this tutorial, you'll learn how to build a web-based PPE detection system using YOLOv8 and Flask, inspired by the latest trends in AI and computer vision. Whether you're a student working on a capstone project or a developer exploring industrial AI, this guide will help you understand the core components and operational logic.
System Architecture Overview
The system comprises four main modules: video acquisition, object detection, data management, and web service. It supports multiple video sources: physical cameras, virtual cameras, video files, RTSP streams, and HTTP streams. This flexibility allows deployment from edge devices to cloud servers. The architecture follows enterprise-level design, ensuring robustness and scalability.
Setting Up the Environment
Start by installing dependencies: Flask, OpenCV, and Ultralytics YOLO. Use a virtual environment to avoid conflicts. The system uses environment variables for configuration, loaded via load_dotenv(). Create a screenshots directory for temporary storage. This defensive programming practice prevents crashes if the directory exists.
import os
from dotenv import load_dotenv
from flask import Flask
load_dotenv()
os.makedirs('screenshots', exist_ok=True)
app = Flask(__name__)Multi-Source Camera Configuration
Define a dictionary of camera sources with fallback priorities. This design ensures the system can switch to a demo video if no camera is available, ideal for testing or containerized deployments.
CAMERA_SOURCES = {
'default': 0,
'virtual': 10,
'file': 'test_video.mp4',
'usb': 1,
'rtsp': 'rtsp://username:password@ip:port/stream',
'http': 'http://ip:port/video'
}
camera_attempts = [
('default', CAMERA_SOURCES['default']),
('virtual', CAMERA_SOURCES['virtual']),
('file', CAMERA_SOURCES['file']),
]Camera Initialization with Error Handling
Iterate through sources and attempt to open each. Set buffer size to 1 for low latency, a critical optimization for real-time performance. Retrieve frame dimensions and FPS for later use.
for source_name, source_value in camera_attempts:
try:
if source_name == 'file':
if not os.path.exists(source_value):
print(f"Video file {source_value} not found, skipping...")
continue
camera = cv2.VideoCapture(source_value)
else:
camera = cv2.VideoCapture(source_value)
if camera.isOpened():
camera.set(cv2.CAP_PROP_BUFFERSIZE, 1)
width = int(camera.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(camera.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = camera.get(cv2.CAP_PROP_FPS)
break
except Exception as e:
print(f"Failed to open {source_name}: {e}")Loading the YOLOv8 Model
Load the lightweight YOLOv8 nano model for a balance of speed and accuracy. Use a try-except block to fall back to mock detection if the model file is missing—useful for demos or resource-limited environments.
from ultralytics import YOLO
try:
model = YOLO('yolov8n.pt')
print("YOLO model loaded successfully")
except:
print("Warning: YOLO model not found, using mock detection")
model = NoneVideo Streaming with Generator Pattern
Flask video streaming uses Python generators. The generate_frames() function continuously reads frames, runs detection, and yields JPEG-encoded images. If the camera fails, it generates demo frames to keep the UI alive.
def generate_frames():
global last_screenshot_time
while True:
if camera_available and camera:
success, frame = camera.read()
if not success:
frame = create_demo_frame()
else:
frame = create_demo_frame()
# Run detection
if model:
results = model.predict(frame, conf=0.6, iou=0.8, imgsz=640, half=True, max_det=10, stream_buffer=True, agnostic_nms=True, vid_stride=12)
# Encode and yield
ret, buffer = cv2.imencode('.jpg', frame)
yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + buffer.tobytes() + b'\r\n')Optimizing Detection Parameters
Each parameter in model.predict() fine-tunes performance: conf=0.6 filters low-confidence detections; iou=0.8 controls overlap removal; imgsz=640 balances speed and accuracy; half=True enables half-precision inference for faster GPU processing; max_det=10 limits detections per frame; vid_stride=12 processes every 12th frame, reducing computational load by 92% while maintaining adequate monitoring. This is especially important for real-time PPE compliance on edge devices.
Intelligent Screenshot Triggering
Save screenshots only when a PPE violation is detected (e.g., missing helmet or vest). Use a cooldown timer to avoid flooding storage. The screenshot is saved with a timestamp and metadata in a database for audit trails.
if detection_triggered:
current_time = time.time()
if current_time - last_screenshot_time > 5: # cooldown 5 seconds
cv2.imwrite(f'screenshots/violation_{int(current_time)}.jpg', frame)
last_screenshot_time = current_timeWeb Interface with Flask
Create routes for the video feed and dashboard. The /video_feed endpoint streams the processed frames. Use HTML with semantic tags for accessibility: <h2>, <p>, <pre>, <code>.
@app.route('/video_feed')
def video_feed():
return Response(generate_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/')
def index():
return '''<h2>PPE Detection Dashboard</h2>
<p>Real-time monitoring for safety compliance.</p>
<img src="/video_feed" width="640" height="480">'''Testing and Deployment
Run the Flask app and access it via browser. For production, use a WSGI server like Gunicorn. The system can be deployed on cloud servers or edge devices like NVIDIA Jetson. Consider using Docker for containerization. This YOLOv8 PPE detection tutorial demonstrates how to build a robust, real-time safety monitoring system with minimal hardware requirements.
Conclusion
You've learned how to build a YOLOv8-based PPE detection system with Flask. The multi-source camera support, fallback mechanisms, and optimization techniques make it suitable for real-world industrial applications. As AI continues to transform workplace safety, this project provides a solid foundation for further customization. Happy coding!