Spaces:
Runtime error
Runtime error
| import asyncio | |
| import websockets | |
| import cv2 | |
| import base64 | |
| import json | |
| import numpy as np | |
| from ultralytics import YOLO | |
| import threading | |
| from datetime import datetime | |
| class WebSocketDetector: | |
| def __init__(self): | |
| self.model = YOLO('yolov8n.pt') | |
| self.connected_clients = set() | |
| self.streaming = False | |
| async def register(self, websocket): | |
| """Register new client""" | |
| self.connected_clients.add(websocket) | |
| print(f"Client connected. Total clients: {len(self.connected_clients)}") | |
| async def unregister(self, websocket): | |
| """Unregister client""" | |
| self.connected_clients.remove(websocket) | |
| print(f"Client disconnected. Total clients: {len(self.connected_clients)}") | |
| async def send_frame(self, websocket, frame, detections): | |
| """Send frame and detection data to client""" | |
| # Encode frame to JPEG | |
| _, buffer = cv2.imencode('.jpg', frame) | |
| frame_base64 = base64.b64encode(buffer).decode('utf-8') | |
| # Create message | |
| message = { | |
| 'type': 'frame', | |
| 'timestamp': datetime.now().isoformat(), | |
| 'image': frame_base64, | |
| 'detections': detections, | |
| 'total_objects': len(detections) | |
| } | |
| await websocket.send(json.dumps(message)) | |
| async def handle_client(self, websocket, path): | |
| """Handle individual client connection""" | |
| await self.register(websocket) | |
| try: | |
| async for message in websocket: | |
| data = json.loads(message) | |
| if data.get('command') == 'start': | |
| self.streaming = True | |
| elif data.get('command') == 'stop': | |
| self.streaming = False | |
| elif data.get('command') == 'status': | |
| await websocket.send(json.dumps({ | |
| 'type': 'status', | |
| 'streaming': self.streaming, | |
| 'clients': len(self.connected_clients) | |
| })) | |
| except websockets.exceptions.ConnectionClosed: | |
| pass | |
| finally: | |
| await self.unregister(websocket) | |
| def detect_frame(self, frame): | |
| """Run detection on frame""" | |
| results = self.model(frame, verbose=False) | |
| # Extract detections | |
| detections = [] | |
| if results[0].boxes is not None: | |
| for box in results[0].boxes: | |
| detections.append({ | |
| 'class': self.model.names[int(box.cls)], | |
| 'confidence': float(box.conf), | |
| 'bbox': box.xyxy.tolist()[0] | |
| }) | |
| annotated = results[0].plot() | |
| return annotated, detections | |
| async def broadcast_frames(self): | |
| """Broadcast frames to all connected clients""" | |
| cap = cv2.VideoCapture(0) | |
| while True: | |
| if self.streaming and self.connected_clients: | |
| ret, frame = cap.read() | |
| if ret: | |
| annotated, detections = self.detect_frame(frame) | |
| # Send to all connected clients | |
| await asyncio.gather( | |
| *[self.send_frame(client, annotated, detections) | |
| for client in self.connected_clients] | |
| ) | |
| await asyncio.sleep(0.033) # ~30 FPS | |
| cap.release() | |
| async def main(): | |
| detector = WebSocketDetector() | |
| # Start broadcasting task | |
| broadcast_task = asyncio.create_task(detector.broadcast_frames()) | |
| # Start WebSocket server | |
| async with websockets.serve(detector.handle_client, "localhost", 8765): | |
| print("WebSocket server started on ws://localhost:8765") | |
| await asyncio.Future() # Run forever | |
| if __name__ == "__main__": | |
| asyncio.run(main()) |