SondosM commited on
Commit
9e2d6e7
·
verified ·
1 Parent(s): 56a7625

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +34 -13
app.py CHANGED
@@ -4,6 +4,7 @@ import inspect
4
  import sys
5
  import os
6
  import types
 
7
  from unittest.mock import MagicMock
8
 
9
  import numpy as np
@@ -23,7 +24,7 @@ from fastapi.responses import JSONResponse
23
  import uvicorn
24
  from huggingface_hub import hf_hub_download
25
 
26
- # --- Compatibility Patches ---
27
  if not hasattr(inspect, "getargspec"):
28
  inspect.getargspec = inspect.getfullargspec
29
 
@@ -32,7 +33,7 @@ for attr, typ in [("int", int), ("float", float), ("complex", complex),
32
  if not hasattr(np, attr):
33
  setattr(np, attr, typ)
34
 
35
- # --- Pyrender / OpenGL Mock (Headless Fix) ---
36
  pyrender_mock = types.ModuleType("pyrender")
37
  for _attr in ["Scene", "Mesh", "Node", "PerspectiveCamera", "DirectionalLight",
38
  "PointLight", "SpotLight", "OffscreenRenderer", "RenderFlags",
@@ -50,14 +51,35 @@ os.environ["PYOPENGL_PLATFORM"] = "osmesa"
50
  # --- Hugging Face Model Integration ---
51
  REPO_ID = "SondosM/api_GP"
52
 
53
- def get_hf_file(filename):
54
- return hf_hub_download(repo_id=REPO_ID, filename=filename)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
- # Resolve paths from Hugging Face Repo
57
  WILOR_REPO_PATH = "./WiLoR"
 
58
  WILOR_CKPT = get_hf_file("pretrained_models/pretrained_models/wilor_final.ckpt")
59
  WILOR_CFG = get_hf_file("pretrained_models/pretrained_models/model_config.yaml")
60
  DETECTOR_PATH = get_hf_file("pretrained_models/pretrained_models/detector.pt")
 
61
  CLASSIFIER_PATH = get_hf_file("classifier.pkl")
62
 
63
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
@@ -82,12 +104,12 @@ def load_models():
82
  wilor_model.to(DEVICE)
83
  wilor_model.eval()
84
 
85
- print(f"Loading YOLO from: {DETECTOR_PATH}")
86
  yolo_detector = YOLO(DETECTOR_PATH)
87
 
88
- print("Loading Classifier...")
89
  classifier = joblib.load(CLASSIFIER_PATH)
90
- print("Models loaded!")
91
 
92
  @asynccontextmanager
93
  async def lifespan(app: FastAPI):
@@ -141,7 +163,7 @@ def read_image_from_upload(file_bytes: bytes) -> np.ndarray:
141
  arr = np.frombuffer(file_bytes, np.uint8)
142
  img = cv2.imdecode(arr, cv2.IMREAD_COLOR)
143
  if img is None:
144
- raise HTTPException(status_code=400, detail="Invalid image.")
145
  return img
146
 
147
  @app.get("/")
@@ -168,7 +190,7 @@ async def predict(file: UploadFile = File(...)):
168
  crop = img_rgb[y1:y2, x1:x2]
169
 
170
  if crop.size == 0:
171
- raise HTTPException(status_code=422, detail="Empty crop.")
172
 
173
  features = extract_features(crop)
174
  if features is None:
@@ -184,7 +206,7 @@ async def predict(file: UploadFile = File(...)):
184
  proba = classifier.predict_proba(feat_df)[0]
185
 
186
  return JSONResponse({
187
- "prediction": prediction,
188
  "confidence": round(float(proba.max()), 4),
189
  "hand_side": hand_side,
190
  "bbox": [int(x1), int(y1), int(x2), int(y2)],
@@ -224,7 +246,7 @@ async def predict_with_skeleton(file: UploadFile = File(...)):
224
  crop_b64 = base64.b64encode(buf).decode("utf-8")
225
 
226
  return JSONResponse({
227
- "prediction": prediction,
228
  "confidence": round(float(proba.max()), 4),
229
  "hand_side": hand_side,
230
  "bbox": [int(x1), int(y1), int(x2), int(y2)],
@@ -233,5 +255,4 @@ async def predict_with_skeleton(file: UploadFile = File(...)):
233
  })
234
 
235
  if __name__ == "__main__":
236
- # Hugging Face Spaces port is 7860
237
  uvicorn.run("app:app", host="0.0.0.0", port=7860, reload=False)
 
4
  import sys
5
  import os
6
  import types
7
+ import shutil
8
  from unittest.mock import MagicMock
9
 
10
  import numpy as np
 
24
  import uvicorn
25
  from huggingface_hub import hf_hub_download
26
 
27
+ # --- Compatibility Patches for Numpy and Inspect ---
28
  if not hasattr(inspect, "getargspec"):
29
  inspect.getargspec = inspect.getfullargspec
30
 
 
33
  if not hasattr(np, attr):
34
  setattr(np, attr, typ)
35
 
36
+ # --- Pyrender / OpenGL Mock (Headless Environment Fix) ---
37
  pyrender_mock = types.ModuleType("pyrender")
38
  for _attr in ["Scene", "Mesh", "Node", "PerspectiveCamera", "DirectionalLight",
39
  "PointLight", "SpotLight", "OffscreenRenderer", "RenderFlags",
 
51
  # --- Hugging Face Model Integration ---
52
  REPO_ID = "SondosM/api_GP"
53
 
54
+ def get_hf_file(filename, is_mano=False):
55
+ print(f"Downloading {filename} from {REPO_ID}...")
56
+ temp_path = hf_hub_download(repo_id=REPO_ID, filename=filename)
57
+
58
+ if is_mano:
59
+ # Create local folder structure expected by WiLoR
60
+ os.makedirs("./mano_data", exist_ok=True)
61
+ target_path = os.path.join("./mano_data", os.path.basename(filename))
62
+ if not os.path.exists(target_path):
63
+ shutil.copy(temp_path, target_path)
64
+ print(f"Copied {filename} to {target_path}")
65
+ return target_path
66
+
67
+ return temp_path
68
+
69
+ # --- Map paths according to your Repo list ---
70
+ print("Initializing model file paths...")
71
+
72
+ # MANO Files
73
+ get_hf_file("mano_data/mano_data/mano_mean_params.npz", is_mano=True)
74
+ get_hf_file("mano_data/mano_data/MANO_LEFT.pkl", is_mano=True)
75
+ get_hf_file("mano_data/mano_data/MANO_RIGHT.pkl", is_mano=True)
76
 
 
77
  WILOR_REPO_PATH = "./WiLoR"
78
+ # Model weights
79
  WILOR_CKPT = get_hf_file("pretrained_models/pretrained_models/wilor_final.ckpt")
80
  WILOR_CFG = get_hf_file("pretrained_models/pretrained_models/model_config.yaml")
81
  DETECTOR_PATH = get_hf_file("pretrained_models/pretrained_models/detector.pt")
82
+ # Classifier
83
  CLASSIFIER_PATH = get_hf_file("classifier.pkl")
84
 
85
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
 
104
  wilor_model.to(DEVICE)
105
  wilor_model.eval()
106
 
107
+ print(f"Loading YOLO detector...")
108
  yolo_detector = YOLO(DETECTOR_PATH)
109
 
110
+ print("Loading RandomForest classifier...")
111
  classifier = joblib.load(CLASSIFIER_PATH)
112
+ print(" All models loaded successfully!")
113
 
114
  @asynccontextmanager
115
  async def lifespan(app: FastAPI):
 
163
  arr = np.frombuffer(file_bytes, np.uint8)
164
  img = cv2.imdecode(arr, cv2.IMREAD_COLOR)
165
  if img is None:
166
+ raise HTTPException(status_code=400, detail="Invalid image format.")
167
  return img
168
 
169
  @app.get("/")
 
190
  crop = img_rgb[y1:y2, x1:x2]
191
 
192
  if crop.size == 0:
193
+ raise HTTPException(status_code=422, detail="Empty hand crop.")
194
 
195
  features = extract_features(crop)
196
  if features is None:
 
206
  proba = classifier.predict_proba(feat_df)[0]
207
 
208
  return JSONResponse({
209
+ "prediction": str(prediction),
210
  "confidence": round(float(proba.max()), 4),
211
  "hand_side": hand_side,
212
  "bbox": [int(x1), int(y1), int(x2), int(y2)],
 
246
  crop_b64 = base64.b64encode(buf).decode("utf-8")
247
 
248
  return JSONResponse({
249
+ "prediction": str(prediction),
250
  "confidence": round(float(proba.max()), 4),
251
  "hand_side": hand_side,
252
  "bbox": [int(x1), int(y1), int(x2), int(y2)],
 
255
  })
256
 
257
  if __name__ == "__main__":
 
258
  uvicorn.run("app:app", host="0.0.0.0", port=7860, reload=False)