anujakkulkarni commited on
Commit
0184e25
·
verified ·
1 Parent(s): f2567d1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -0
app.py CHANGED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, UploadFile, File, HTTPException
2
+ from fastapi.responses import JSONResponse
3
+ from ultralytics import YOLO
4
+ import cv2
5
+ import numpy as np
6
+ from shapely.geometry import box as shapely_box, Polygon
7
+ from shapely.ops import unary_union
8
+ import mediapipe as mp
9
+ from collections import defaultdict
10
+
11
+ app = FastAPI(title="Face Skin Percentage API")
12
+
13
+ # -------------------- LOAD MODELS --------------------
14
+ skin_model_path = "pores.pt" # Your YOLO model path
15
+ skin_model = YOLO(skin_model_path)
16
+ mp_face_mesh = mp.solutions.face_mesh.FaceMesh(static_image_mode=True)
17
+
18
+ # -------------------- HOME ROUTE --------------------
19
+ @app.get("/")
20
+ def home():
21
+ return {"message": "✅ Skin API is running",
22
+ "usage": "POST an image (form-data key 'file') to /analyze"}
23
+
24
+ # -------------------- ANALYZE ROUTE --------------------
25
+ @app.post("/analyze")
26
+ async def analyze(file: UploadFile = File(...)):
27
+ if not file:
28
+ raise HTTPException(status_code=400, detail="No file uploaded")
29
+
30
+ # Read image bytes and convert to OpenCV image
31
+ contents = await file.read()
32
+ np_arr = np.frombuffer(contents, np.uint8)
33
+ img = cv2.imdecode(np_arr, cv2.IMREAD_COLOR)
34
+ if img is None:
35
+ raise HTTPException(status_code=400, detail="Invalid image file")
36
+
37
+ img_h, img_w = img.shape[:2]
38
+
39
+ # -------------------- STEP 1: Detect face --------------------
40
+ rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
41
+ result = mp_face_mesh.process(rgb_img)
42
+
43
+ face_area = 0
44
+ face_polygon = None
45
+ if result.multi_face_landmarks:
46
+ for facial_landmarks in result.multi_face_landmarks:
47
+ points = [[int(lm.x * img_w), int(lm.y * img_h)] for lm in facial_landmarks.landmark]
48
+ hull = cv2.convexHull(np.array(points, dtype=np.int32))
49
+ face_area = cv2.contourArea(hull)
50
+ face_polygon = Polygon(hull.reshape(-1, 2))
51
+ break # only first face
52
+ else:
53
+ return JSONResponse({"success": False, "message": "No face detected", "percentages": {}})
54
+
55
+ # -------------------- STEP 2: Run YOLO skin detection --------------------
56
+ skin_results = skin_model(img)
57
+ boxes_xy = skin_results[0].boxes.xyxy.cpu().numpy()
58
+ boxes_cls = skin_results[0].boxes.cls.cpu().numpy().astype(int)
59
+
60
+ class_polygons = defaultdict(list)
61
+ for xy, cls_id in zip(boxes_xy, boxes_cls):
62
+ x1, y1, x2, y2 = xy.astype(int)
63
+ det_poly = shapely_box(x1, y1, x2, y2)
64
+ if face_polygon.intersects(det_poly):
65
+ intersection = det_poly.intersection(face_polygon)
66
+ if intersection.area > 0:
67
+ class_polygons[cls_id].append(intersection)
68
+
69
+ # -------------------- STEP 3: Calculate percentages --------------------
70
+ skin_percentages = {}
71
+ for cls_id, class_name in skin_model.names.items():
72
+ polys = class_polygons.get(cls_id, [])
73
+ if polys:
74
+ union_poly = unary_union(polys)
75
+ percentage = (union_poly.area / face_area) * 100 if face_area > 0 else 0.0
76
+ else:
77
+ percentage = 0.0
78
+ skin_percentages[class_name] = round(percentage, 2)
79
+
80
+ return {"success": True, "percentages": skin_percentages}