Spaces:
Runtime error
Runtime error
| import cv2 | |
| import uuid | |
| import os | |
| import shutil | |
| from fastapi import FastAPI, File, UploadFile | |
| from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse | |
| from ultralytics import YOLO | |
| # --- Initialization --- | |
| app = FastAPI() | |
| # Load the pre-trained YOLOv8 model | |
| # Ensure 'best.pt' is in the same directory as this script | |
| try: | |
| model = YOLO('best.pt') | |
| except Exception as e: | |
| print(f"Error loading model: {e}") | |
| # Exit if the model can't be loaded, as the app is useless without it. | |
| exit() | |
| # A dictionary to store the paths of uploaded videos, using a session ID as the key | |
| video_sessions = {} | |
| # *** FIX: Use the /tmp directory which is writeable on Hugging Face Spaces *** | |
| UPLOAD_DIR = "/tmp/uploads" | |
| os.makedirs(UPLOAD_DIR, exist_ok=True) | |
| # --- Frontend Endpoint --- | |
| async def read_root(): | |
| """Serves the main HTML page.""" | |
| try: | |
| with open("templates/index.html") as f: | |
| return f.read() | |
| except FileNotFoundError: | |
| return "<h1>Error: index.html not found</h1><p>Please make sure the 'templates' folder and 'index.html' file exist.</p>" | |
| # --- Webcam Streaming --- | |
| def generate_webcam_frames(): | |
| """Generates annotated frames from the webcam.""" | |
| # Note: Webcam functionality will not work on Hugging Face Spaces | |
| # as the server does not have a physical camera. | |
| # This endpoint will work locally but fail on the server. | |
| camera = cv2.VideoCapture(0) | |
| if not camera.isOpened(): | |
| print("Error: Could not start webcam.") | |
| return | |
| while True: | |
| success, frame = camera.read() | |
| if not success: | |
| break | |
| else: | |
| # Run YOLOv8 inference on the frame, filtering for helmets (12) and vests (16) | |
| results = model(frame, classes=[12, 16], verbose=False) | |
| annotated_frame = results[0].plot() | |
| # Encode the frame as JPEG | |
| ret, buffer = cv2.imencode('.jpg', annotated_frame) | |
| if not ret: | |
| continue | |
| frame_bytes = buffer.tobytes() | |
| # Yield the frame in the multipart format | |
| yield (b'--frame\r\n' | |
| b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n') | |
| camera.release() | |
| def video_feed_webcam(): | |
| """Streams video from the webcam.""" | |
| return StreamingResponse(generate_webcam_frames(), media_type="multipart/x-mixed-replace; boundary=frame") | |
| # --- Video Upload and Processing --- | |
| async def upload_video(video_file: UploadFile = File(...)): | |
| """Handles video file uploads.""" | |
| session_id = str(uuid.uuid4()) | |
| file_path = os.path.join(UPLOAD_DIR, f"{session_id}_{video_file.filename}") | |
| # Save the uploaded file | |
| with open(file_path, "wb") as buffer: | |
| shutil.copyfileobj(video_file.file, buffer) | |
| # Store the path for the streaming endpoint | |
| video_sessions[session_id] = file_path | |
| return JSONResponse(content={"session_id": session_id}) | |
| def generate_upload_frames(session_id: str): | |
| """Generates annotated frames from an uploaded video.""" | |
| file_path = video_sessions.get(session_id) | |
| if not file_path or not os.path.exists(file_path): | |
| print(f"Error: Video for session {session_id} not found.") | |
| return | |
| video = cv2.VideoCapture(file_path) | |
| while video.isOpened(): | |
| success, frame = video.read() | |
| if not success: | |
| break | |
| else: | |
| # Run YOLOv8 inference | |
| results = model(frame, classes=[12, 16], verbose=False) | |
| annotated_frame = results[0].plot() | |
| # Encode frame | |
| ret, buffer = cv2.imencode('.jpg', annotated_frame) | |
| if not ret: | |
| continue | |
| frame_bytes = buffer.tobytes() | |
| yield (b'--frame\r\n' | |
| b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n') | |
| video.release() | |
| # Clean up: remove the video file and session entry after streaming | |
| if os.path.exists(file_path): | |
| os.remove(file_path) | |
| if session_id in video_sessions: | |
| del video_sessions[session_id] | |
| def video_feed_upload(session_id: str): | |
| """Streams video from an uploaded file based on the session ID.""" | |
| return StreamingResponse(generate_upload_frames(session_id), media_type="multipart/x-mixed-replace; boundary=frame") | |