Spaces:
Running
Running
| from flask import Flask, Response, jsonify, request | |
| from flask_cors import CORS | |
| import cv2 | |
| import json | |
| import time | |
| import os | |
| import base64 | |
| import numpy as np | |
| from datetime import datetime | |
| from ppe_detection import load_model, process_frame | |
| app = Flask(__name__) | |
| CORS(app) # Allow cross-origin requests from Vercel frontend | |
| # Global variables | |
| model = None | |
| detection_active = False | |
| detection_results = [] | |
| violation_count = 0 | |
| helmet_count = 0 | |
| vest_count = 0 | |
| glove_count = 0 | |
| def init_model(): | |
| """Load the YOLOv8 model globally""" | |
| global model | |
| if model is None: | |
| print("Loading YOLOv8 model...") | |
| model = load_model() | |
| if model is None: | |
| print("Failed to load model!") | |
| def update_counters(detections): | |
| """Update global counters based on detection results""" | |
| global violation_count, helmet_count, vest_count, glove_count | |
| current_violation_count = 0 | |
| current_helmet_count = 0 | |
| current_vest_count = 0 | |
| current_glove_count = 0 | |
| for detection in detections: | |
| type_name = detection.get("type", "") | |
| if type_name.startswith("NO-") and detection.get("detected", False): | |
| current_violation_count += 1 | |
| elif (type_name == "Hardhat" or type_name == "helmet") and detection.get("detected", False): | |
| current_helmet_count += 1 | |
| elif (type_name == "Safety Vest" or type_name == "vest") and detection.get("detected", False): | |
| current_vest_count += 1 | |
| elif (type_name == "Gloves" or type_name == "hand gloves") and detection.get("detected", False): | |
| current_glove_count += 1 | |
| # Update global counters | |
| violation_count = current_violation_count | |
| helmet_count = current_helmet_count | |
| vest_count = current_vest_count | |
| glove_count = current_glove_count | |
| def index(): | |
| """Home page route""" | |
| return "PPE Detection Cloud API Server is running!" | |
| def start_detection(): | |
| """Start PPE detection""" | |
| global detection_active | |
| # Initialize the model on first start | |
| init_model() | |
| detection_active = True | |
| return jsonify({"success": True, "message": "Detection started"}) | |
| def stop_detection(): | |
| """Stop PPE detection""" | |
| global detection_active | |
| detection_active = False | |
| return jsonify({"success": True, "message": "Detection stopped"}) | |
| def get_status(): | |
| """Get detection status and counters""" | |
| global detection_active, violation_count, helmet_count, vest_count, glove_count | |
| return jsonify({ | |
| "active": detection_active, | |
| "violations": violation_count, | |
| "helmets": helmet_count, | |
| "vests": vest_count, | |
| "gloves": glove_count | |
| }) | |
| def get_results(): | |
| """Get recent detection results""" | |
| global detection_results | |
| return jsonify({"results": detection_results}) | |
| def process_socket_frame(): | |
| """Process incoming base64 video frames from the frontend""" | |
| if request.method == "OPTIONS": | |
| return jsonify({"success": True}) | |
| global model, detection_active, detection_results | |
| if not detection_active: | |
| return jsonify({"success": False, "message": "Detection is not active"}) | |
| if model is None: | |
| init_model() | |
| if model is None: | |
| return jsonify({"success": False, "message": "Model failed to load"}) | |
| try: | |
| data = request.json | |
| frame_data = data.get("frame", "") | |
| # Remove base64 prefix if present | |
| if "," in frame_data: | |
| frame_data = frame_data.split(",")[1] | |
| # Decode base64 to OpenCV image | |
| img_bytes = base64.b64decode(frame_data) | |
| np_arr = np.frombuffer(img_bytes, np.uint8) | |
| frame = cv2.imdecode(np_arr, cv2.IMREAD_COLOR) | |
| if frame is None: | |
| return jsonify({"success": False, "message": "Failed to decode frame"}) | |
| # Run YOLO inference | |
| _, detections = process_frame(frame, model, 0) | |
| timestamp = datetime.now().strftime("%H:%M:%S") | |
| # Update counters | |
| update_counters(detections) | |
| # Update results log | |
| result_entry = { | |
| "timestamp": timestamp, | |
| "detections": detections | |
| } | |
| detection_results.append(result_entry) | |
| # Keep only the last 50 results | |
| if len(detection_results) > 50: | |
| detection_results = detection_results[-50:] | |
| return jsonify({ | |
| "success": True, | |
| "processed": True, | |
| "timestamp": timestamp, | |
| "message": "Frame processed successfully", | |
| "detections": detections | |
| }) | |
| except Exception as e: | |
| print(f"Error processing frame: {e}") | |
| return jsonify({"success": False, "message": str(e)}) | |
| if __name__ == "__main__": | |
| print("Starting Cloud PPE Detection API Server...") | |
| # Render binds to the PORT environment variable | |
| port = int(os.environ.get("PORT", 5000)) | |
| app.run(host="0.0.0.0", port=port, debug=False, threaded=True) |