Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -6,7 +6,7 @@ from shapely.geometry import box as shapely_box, Polygon
|
|
| 6 |
from shapely.ops import unary_union
|
| 7 |
import mediapipe as mp
|
| 8 |
from collections import defaultdict
|
| 9 |
-
from concurrent.futures import ThreadPoolExecutor, as_completed
|
| 10 |
|
| 11 |
# -------------------- CONFIG --------------------
|
| 12 |
model_paths = {
|
|
@@ -160,54 +160,60 @@ def analyze():
|
|
| 160 |
|
| 161 |
img_h, img_w = img.shape[:2]
|
| 162 |
|
| 163 |
-
# --------------------
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
for lm in landmarks.landmark
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
|
| 212 |
except Exception as e:
|
| 213 |
return jsonify({"success": False, "analysis": [], "error": str(e)}), 500
|
|
|
|
| 6 |
from shapely.ops import unary_union
|
| 7 |
import mediapipe as mp
|
| 8 |
from collections import defaultdict
|
| 9 |
+
from concurrent.futures import ThreadPoolExecutor, as_completed, TimeoutError
|
| 10 |
|
| 11 |
# -------------------- CONFIG --------------------
|
| 12 |
model_paths = {
|
|
|
|
| 160 |
|
| 161 |
img_h, img_w = img.shape[:2]
|
| 162 |
|
| 163 |
+
# -------------------- TIME-LIMITED ANALYSIS --------------------
|
| 164 |
+
def full_analysis():
|
| 165 |
+
# FACE DETECTION
|
| 166 |
+
rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
| 167 |
+
result = face_mesh.process(rgb_img)
|
| 168 |
+
|
| 169 |
+
face_polygon = None
|
| 170 |
+
face_area = 0
|
| 171 |
+
if result.multi_face_landmarks:
|
| 172 |
+
for landmarks in result.multi_face_landmarks:
|
| 173 |
+
points = np.array([[int(lm.x * img_w), int(lm.y * img_h)] for lm in landmarks.landmark])
|
| 174 |
+
hull = cv2.convexHull(points)
|
| 175 |
+
face_area = cv2.contourArea(hull)
|
| 176 |
+
face_polygon = Polygon(hull.reshape(-1, 2))
|
| 177 |
+
break
|
| 178 |
+
else:
|
| 179 |
+
raise ValueError("No face detected.")
|
| 180 |
+
|
| 181 |
+
# RUN MODELS
|
| 182 |
+
combined_percentages = {}
|
| 183 |
+
with ThreadPoolExecutor() as executor:
|
| 184 |
+
futures = {
|
| 185 |
+
executor.submit(run_model, model_name, model, img, face_polygon, face_area): model_name
|
| 186 |
+
for model_name, model in models.items()
|
| 187 |
+
}
|
| 188 |
+
for future in as_completed(futures):
|
| 189 |
+
skin_percentages = future.result()
|
| 190 |
+
combined_percentages.update(skin_percentages)
|
| 191 |
+
|
| 192 |
+
final_percentages = normalize_and_merge(combined_percentages)
|
| 193 |
+
|
| 194 |
+
# MERGE WRINKLES + FOREHEAD
|
| 195 |
+
wrinkle_value = final_percentages.get("wrinkles", 0.0) + final_percentages.get("forehead", 0.0)
|
| 196 |
+
final_percentages["wrinkles"] = round(wrinkle_value, 2)
|
| 197 |
+
if "forehead" in final_percentages:
|
| 198 |
+
final_percentages.pop("forehead")
|
| 199 |
+
|
| 200 |
+
# SKIN TYPE
|
| 201 |
+
skin_type_result = detect_skin_type_from_image(img)
|
| 202 |
+
|
| 203 |
+
# FORMAT RESPONSE
|
| 204 |
+
analysis_list = [f"{cls_name.upper()}: {value}%" for cls_name, value in final_percentages.items()]
|
| 205 |
+
analysis_list.append(f"SKIN TYPE: {skin_type_result}")
|
| 206 |
+
|
| 207 |
+
return {"success": True, "analysis": ["\n".join(analysis_list)]}
|
| 208 |
+
|
| 209 |
+
# -------------------- RUN WITH 60 SEC TIMEOUT --------------------
|
| 210 |
+
with ThreadPoolExecutor(max_workers=1) as executor:
|
| 211 |
+
future = executor.submit(full_analysis)
|
| 212 |
+
try:
|
| 213 |
+
result = future.result(timeout=60) # 60-second limit
|
| 214 |
+
return jsonify(result)
|
| 215 |
+
except TimeoutError:
|
| 216 |
+
return jsonify({"success": False, "analysis": [], "error": "Processing timeout (60 sec)."}), 504
|
| 217 |
|
| 218 |
except Exception as e:
|
| 219 |
return jsonify({"success": False, "analysis": [], "error": str(e)}), 500
|