Assignment Chef icon Assignment Chef
All English tutorials

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.

YOLOv8 PPE detection real-time object detection PPE compliance system Flask video streaming computer vision tutorial AI safety monitoring YOLOv8 optimization parameters multi-source camera input defensive programming Python industrial AI applications edge device deployment real-time inference YOLOv8 nano model PPE detection project Flask web app tutorial student capstone project AI

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 = None

Video 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_time

Web 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!