Spaces:
Paused
Paused
Download main.py from JSWOOK/gazeTracker: direct link, hf CLI and curl.
- Browser
- Download file 2.07 kB
-
https://huggingface.co/spaces/JSWOOK/gazeTracker/resolve/main/main.py
- Command line
-
hf download hf://spaces/JSWOOK/gazeTracker/main.py
-
curl -L -o main.py https://huggingface.co/spaces/JSWOOK/gazeTracker/resolve/main/main.py
2.07 kB
| import asyncio | |
| import json | |
| from pathlib import Path | |
| import cv2 | |
| import numpy as np | |
| import torch | |
| from fastapi import FastAPI, WebSocket, WebSocketDisconnect | |
| app = FastAPI(title="Reading Trace L2CS") | |
| pipeline = None | |
| def get_pipeline(): | |
| global pipeline | |
| if pipeline is None: | |
| from l2cs import Pipeline | |
| pipeline = Pipeline( | |
| weights=Path("models/L2CSNet_gaze360.pkl"), | |
| arch="ResNet50", | |
| device=torch.device("cuda" if torch.cuda.is_available() else "cpu"), | |
| ) | |
| return pipeline | |
| def health(): | |
| get_pipeline() | |
| return {"status": "ok", "device": "cuda" if torch.cuda.is_available() else "cpu"} | |
| def infer(data: bytes): | |
| frame = cv2.imdecode(np.frombuffer(data, np.uint8), cv2.IMREAD_COLOR) | |
| if frame is None: | |
| return {"error": "invalid frame"} | |
| height, width = frame.shape[:2] | |
| try: | |
| result = get_pipeline().step(frame) | |
| except ValueError: | |
| return {"faces": 0} | |
| yaw = np.asarray(result.yaw).reshape(-1) | |
| pitch = np.asarray(result.pitch).reshape(-1) | |
| if not yaw.size: | |
| return {"faces": 0} | |
| boxes = np.asarray(getattr(result, "bboxes", [])) | |
| index, fx, fy = 0, .5, .5 | |
| if boxes.ndim == 2 and boxes.shape[0] == yaw.size and boxes.shape[1] >= 4: | |
| areas = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1]) | |
| index = int(np.argmax(areas)) | |
| x0, y0, x1, y1 = boxes[index, :4] | |
| fx, fy = float((x0 + x1) / 2 / width), float((y0 + y1) / 2 / height) | |
| return {"yaw": float(yaw[index]), "pitch": float(pitch[index]), "fx": fx, "fy": fy, "faces": int(yaw.size)} | |
| async def websocket_gaze(socket: WebSocket): | |
| await socket.accept() | |
| try: | |
| while True: | |
| data = await socket.receive_bytes() | |
| if len(data) > 2_000_000: | |
| await socket.close(code=1009) | |
| return | |
| result = await asyncio.to_thread(infer, data) | |
| await socket.send_text(json.dumps(result)) | |
| except WebSocketDisconnect: | |
| pass | |