Stroke-ia commited on
Commit
b2d4293
·
verified ·
1 Parent(s): 5d8bdaa

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -136
app.py DELETED
@@ -1,136 +0,0 @@
1
- import os
2
- import cv2
3
- import time
4
- import threading
5
- import numpy as np
6
- from datetime import datetime
7
- from fastapi import FastAPI, UploadFile, File
8
- from fastapi.staticfiles import StaticFiles
9
- from ultralytics import YOLO
10
- from PIL import Image
11
-
12
- # ==============================
13
- # ENV FIX (HF SAFE)
14
- # ==============================
15
- os.environ["YOLO_CONFIG_DIR"] = "/tmp/Ultralytics"
16
- os.environ["MPLCONFIGDIR"] = "/tmp/matplotlib"
17
-
18
- # ==============================
19
- # CONFIG
20
- # ==============================
21
- MODEL_PATH = "best.pt"
22
- OUTPUT_DIR = "/tmp/outputs"
23
- BASE_URL = "https://stroke-ia-detect-avc-image.hf.space"
24
-
25
- os.makedirs(OUTPUT_DIR, exist_ok=True)
26
-
27
- # ==============================
28
- # LOAD MODEL (ONCE)
29
- # ==============================
30
- print("🚀 Loading YOLO model...")
31
- model = YOLO(MODEL_PATH)
32
- print("✅ Model loaded")
33
-
34
- # ==============================
35
- # FASTAPI
36
- # ==============================
37
- app = FastAPI(title="Stroke-IA Facial Detection API")
38
- app.mount("/files", StaticFiles(directory=OUTPUT_DIR), name="files")
39
-
40
- # ==============================
41
- # UTILS
42
- # ==============================
43
- def generate_report(results) -> str:
44
- boxes = results[0].boxes
45
- if boxes is None or len(boxes) == 0:
46
- return "=== RAPPORT AUTOMATIQUE ===\n\nAucune anomalie détectée.\n"
47
-
48
- rapport = "=== RAPPORT AUTOMATIQUE AVC ===\n\n"
49
- rapport += f"Nombre de signes détectés : {len(boxes)}\n\n"
50
-
51
- for i, cls_id in enumerate(boxes.cls.cpu().numpy().astype(int), 1):
52
- rapport += f"- Indice {i} : Classe {cls_id}\n"
53
-
54
- rapport += "\n⚠️ Ce résultat est généré par une IA.\n"
55
- rapport += "⚠️ Ne remplace pas un diagnostic médical.\n"
56
-
57
- return rapport
58
-
59
- # ==============================
60
- # HEALTH CHECK (IMPORTANT)
61
- # ==============================
62
- @app.get("/health")
63
- def health():
64
- return {
65
- "status": "ok",
66
- "model": "loaded",
67
- "time": datetime.utcnow().isoformat()
68
- }
69
-
70
- # ==============================
71
- # PREDICT
72
- # ==============================
73
- @app.post("/predict/")
74
- async def predict(image_file: UploadFile = File(...), conf: float = 0.8):
75
-
76
- # ---------- Save temp image ----------
77
- tmp_path = f"/tmp/{image_file.filename}"
78
- with open(tmp_path, "wb") as f:
79
- f.write(await image_file.read())
80
-
81
- # ---------- Load image ----------
82
- image = Image.open(tmp_path).convert("RGB")
83
- np_img = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
84
-
85
- # ---------- YOLO Prediction ----------
86
- results = model.predict(
87
- source=np_img,
88
- conf=conf,
89
- verbose=False
90
- )
91
-
92
- # ---------- No detection ----------
93
- if results[0].boxes is None or len(results[0].boxes) == 0:
94
- os.remove(tmp_path)
95
- return {
96
- "status": "ok",
97
- "message": "✅ Aucun signe d’AVC détecté sur cette image."
98
- }
99
-
100
- # ---------- Annotate ----------
101
- annotated = results[0].plot(labels=True)
102
-
103
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
104
- img_name = f"stroke_result_{timestamp}.png"
105
- txt_name = f"rapport_{timestamp}.txt"
106
-
107
- img_path = os.path.join(OUTPUT_DIR, img_name)
108
- txt_path = os.path.join(OUTPUT_DIR, txt_name)
109
-
110
- cv2.imwrite(img_path, annotated)
111
-
112
- with open(txt_path, "w", encoding="utf-8") as f:
113
- f.write(generate_report(results))
114
-
115
- os.remove(tmp_path)
116
-
117
- return {
118
- "status": "success",
119
- "annotated_result_url": f"{BASE_URL}/files/{img_name}",
120
- "rapport_url": f"{BASE_URL}/files/{txt_name}",
121
- "message": "⚠️ Signes potentiels détectés – Vérification médicale recommandée"
122
- }
123
-
124
- # ==============================
125
- # AUTO CLEANUP
126
- # ==============================
127
- def cleanup(interval=600):
128
- while True:
129
- time.sleep(interval)
130
- for f in os.listdir(OUTPUT_DIR):
131
- try:
132
- os.remove(os.path.join(OUTPUT_DIR, f))
133
- except:
134
- pass
135
-
136
- threading.Thread(target=cleanup, daemon=True).start()