yossss2 commited on
Commit
b24f8ab
·
verified ·
1 Parent(s): 38e8ae3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +15 -18
app.py CHANGED
@@ -6,11 +6,9 @@ Nouveau endpoint /extract-features-frames :
6
  → Identique au pipeline d'entraînement Kaggle
7
  """
8
 
9
- from fastapi import FastAPI, UploadFile, File, HTTPException
10
  from fastapi.middleware.cors import CORSMiddleware
11
  from fastapi.responses import JSONResponse
12
- from pydantic import BaseModel
13
- from typing import List
14
  import numpy as np
15
  import cv2
16
  import torch
@@ -62,11 +60,6 @@ app.add_middleware(
62
  )
63
 
64
 
65
- # ── Modèle de requête pour les frames ────────────────────────
66
- class FramesRequest(BaseModel):
67
- frames: List[str] # liste de 16 strings base64 JPEG (224×224)
68
-
69
-
70
  # ── Helper : base64 → numpy (H, W, 3) uint8 ──────────────────
71
  def b64_to_frame(b64str: str) -> np.ndarray:
72
  img_bytes = base64.b64decode(b64str)
@@ -122,25 +115,29 @@ def health():
122
 
123
 
124
  @app.post("/extract-features-frames")
125
- async def extract_features_frames(req: FramesRequest):
126
  """
127
- Reçoit : { "frames": ["<base64_jpeg>", ...] } (16 frames 224×224)
128
  Retourne: { "features": [[...], ...], "shape": [8, 768] }
129
-
130
- Les frames doivent être croppées sur la bouche côté browser
131
- (MediaPipe FaceMesh) — exactement comme le dataset d'entraînement.
132
  """
133
  if vmae_model is None:
134
  raise HTTPException(status_code=503, detail="VideoMAE non chargé")
135
 
136
- n = len(req.frames)
 
 
 
 
 
 
137
  if n == 0:
138
  raise HTTPException(status_code=422, detail="Aucune frame reçue")
139
 
140
- # Padding ou troncature à 16 frames
141
- frames_b64 = req.frames[:NUM_FRAMES]
142
  while len(frames_b64) < NUM_FRAMES:
143
- frames_b64.append(frames_b64[-1]) # répète la dernière frame
144
 
145
  try:
146
  frames_np = [b64_to_frame(f) for f in frames_b64]
@@ -155,7 +152,7 @@ async def extract_features_frames(req: FramesRequest):
155
 
156
  return JSONResponse({
157
  "features": features.tolist(),
158
- "shape": list(features.shape), # [8, 768]
159
  "model_id": VMAE_MODEL_ID,
160
  "frames_received": n,
161
  })
 
6
  → Identique au pipeline d'entraînement Kaggle
7
  """
8
 
9
+ from fastapi import FastAPI, UploadFile, File, HTTPException, Form
10
  from fastapi.middleware.cors import CORSMiddleware
11
  from fastapi.responses import JSONResponse
 
 
12
  import numpy as np
13
  import cv2
14
  import torch
 
60
  )
61
 
62
 
 
 
 
 
 
63
  # ── Helper : base64 → numpy (H, W, 3) uint8 ──────────────────
64
  def b64_to_frame(b64str: str) -> np.ndarray:
65
  img_bytes = base64.b64decode(b64str)
 
115
 
116
 
117
  @app.post("/extract-features-frames")
118
+ async def extract_features_frames(frames_json: str = Form(...)):
119
  """
120
+ Reçoit : FormData { frames_json: "['<base64>', ...]" }
121
  Retourne: { "features": [[...], ...], "shape": [8, 768] }
122
+ Utilise FormData (multipart) pour éviter le preflight CORS de HuggingFace.
 
 
123
  """
124
  if vmae_model is None:
125
  raise HTTPException(status_code=503, detail="VideoMAE non chargé")
126
 
127
+ try:
128
+ import json as _json
129
+ frames_list = _json.loads(frames_json)
130
+ except Exception:
131
+ raise HTTPException(status_code=422, detail="frames_json invalide")
132
+
133
+ n = len(frames_list)
134
  if n == 0:
135
  raise HTTPException(status_code=422, detail="Aucune frame reçue")
136
 
137
+ # Padding ou troncature à NUM_FRAMES
138
+ frames_b64 = frames_list[:NUM_FRAMES]
139
  while len(frames_b64) < NUM_FRAMES:
140
+ frames_b64.append(frames_b64[-1])
141
 
142
  try:
143
  frames_np = [b64_to_frame(f) for f in frames_b64]
 
152
 
153
  return JSONResponse({
154
  "features": features.tolist(),
155
+ "shape": list(features.shape),
156
  "model_id": VMAE_MODEL_ID,
157
  "frames_received": n,
158
  })