Abhilash7 commited on
Commit
c7498ef
·
verified ·
1 Parent(s): 97d716e

Create segmentation.py

Browse files
Files changed (1) hide show
  1. segmentation.py +69 -0
segmentation.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+ try:
4
+ import mediapipe as mp
5
+ _HAS_MP = True
6
+ except Exception:
7
+ _HAS_MP = False
8
+
9
+ def segment_image(img_np):
10
+ """
11
+ Returns a binary mask (uint8 0/255) for hair/head region using MediaPipe if available,
12
+ otherwise falls back to naive ellipse.
13
+ """
14
+ if not _HAS_MP:
15
+ # Fallback to naive ellipse
16
+ h, w = img_np.shape[:2]
17
+ mask = np.zeros((h, w), dtype=np.uint8)
18
+ center = (w // 2, int(h * 0.38))
19
+ axes = (int(w * 0.28), int(h * 0.33))
20
+ cv2.ellipse(mask, center, axes, 0, 0, 360, 255, -1)
21
+ return mask
22
+
23
+ # Use MediaPipe FaceMesh for better head segmentation
24
+ mp_face = mp.solutions.face_mesh
25
+ with mp_face.FaceMesh(static_image_mode=True, max_num_faces=1) as face_mesh:
26
+ results = face_mesh.process(cv2.cvtColor(img_np, cv2.COLOR_BGR2RGB))
27
+ if not results.multi_face_landmarks:
28
+ return np.zeros(img_np.shape[:2], dtype=np.uint8) # Empty mask if no face
29
+
30
+ landmarks = results.multi_face_landmarks[0]
31
+ h, w = img_np.shape[:2]
32
+ mask = np.zeros((h, w), dtype=np.uint8)
33
+
34
+ # Define head contour points (approximate hair region using face landmarks)
35
+ head_points = [
36
+ 10, # Top forehead
37
+ 109, 67, 103, 54, 21, 162, 127, 234, 93, 132, 215, # Left side
38
+ 338, 297, 332, 284, 251, 389, 356, 454, 323, 361, 288, # Right side
39
+ 152 # Chin
40
+ ]
41
+ points = np.array([(int(landmarks.landmark[i].x * w), int(landmarks.landmark[i].y * h)) for i in head_points])
42
+
43
+ # Expand slightly for hair
44
+ hull = cv2.convexHull(points)
45
+ cv2.fillConvexPoly(mask, hull, 255)
46
+
47
+ # Dilate to cover more hair area
48
+ kernel = np.ones((15, 15), np.uint8)
49
+ mask = cv2.dilate(mask, kernel, iterations=2)
50
+
51
+ return mask
52
+
53
+ def estimate_landmarks(img_np):
54
+ """
55
+ Return dict with key landmarks for alignment (e.g., forehead anchor).
56
+ """
57
+ if not _HAS_MP:
58
+ return None
59
+ mp_face = mp.solutions.face_mesh
60
+ with mp_face.FaceMesh(static_image_mode=True, max_num_faces=1) as face_mesh:
61
+ results = face_mesh.process(cv2.cvtColor(img_np, cv2.COLOR_BGR2RGB))
62
+ if not results.multi_face_landmarks:
63
+ return None
64
+ lm = results.multi_face_landmarks[0].landmark
65
+ # Forehead anchor (average of top landmarks)
66
+ xs = [p.x for p in lm[:10]] # Normalized [0,1]
67
+ ys = [p.y for p in lm[:10]]
68
+ h, w = img_np.shape[:2]
69
+ return {"forehead_anchor": (int(np.mean(xs) * w), int(np.mean(ys) * h))}