RojaKatta commited on
Commit
92fd95d
·
verified ·
1 Parent(s): 6983604

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -68
app.py CHANGED
@@ -1,70 +1,54 @@
1
- import os, json, tempfile
2
- import cv2, numpy as np, gradio as gr
3
  from PIL import Image
4
-
5
- # ---------------------- Paths (hair/ first) ----------------------
6
- BASE_DIR = os.path.dirname(os.path.abspath(__file__))
7
- CANDIDATES = [
8
- os.path.join(BASE_DIR, "hair"), # <- your folder
9
- os.path.join(BASE_DIR, "assets", "hairstyles"),
10
- os.path.join(BASE_DIR, "assets", "Hairstyles"),
11
- os.path.join(BASE_DIR, "hairstyles"),
12
- ]
13
- HAIR_DIR = None
14
- for p in CANDIDATES:
15
- if os.path.isdir(p):
16
- HAIR_DIR = p
17
- break
18
- if HAIR_DIR is None: # create canonical path if nothing exists yet
19
- HAIR_DIR = os.path.join(BASE_DIR, "hair")
20
- os.makedirs(HAIR_DIR, exist_ok=True)
21
-
22
- META_PATH = os.path.join(HAIR_DIR, "meta.json") # optional per-style anchors
23
-
24
- # ---------------------- MediaPipe ----------------------
25
- try:
26
- import mediapipe as mp
27
- except Exception as e:
28
- raise RuntimeError(f"Mediapipe import failed. Check requirements.txt pins. Details: {e}")
29
-
30
- mp_face_mesh = mp.solutions.face_mesh
31
- mp_selfie_seg = mp.solutions.selfie_segmentation
32
- LM = {"left_eye_outer": 33, "right_eye_outer": 263, "mid_forehead": 10}
33
-
34
- # ---------------------- Helpers ----------------------
35
  def load_hairstyles():
36
- try:
37
- files = [f for f in os.listdir(HAIR_DIR) if f.lower().endswith(".png")]
38
- except FileNotFoundError:
39
- files = []
40
- files.sort()
41
- return files
42
-
43
- HAIR_FILES = load_hairstyles()
44
-
45
- def load_meta():
46
- if os.path.exists(META_PATH):
47
- try:
48
- with open(META_PATH, "r") as f:
49
- m = json.load(f)
50
- return m if isinstance(m, dict) else {}
51
- except Exception:
52
- return {}
53
- return {}
54
- META = load_meta()
55
-
56
- def detect_face_keypoints(img_bgr):
57
- h, w = img_bgr.shape[:2]
58
- with mp_face_mesh.FaceMesh(
59
- static_image_mode=True, max_num_faces=1, refine_landmarks=True,
60
- min_detection_confidence=0.6
61
- ) as fm:
62
- res = fm.process(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
63
- if not res.multi_face_landmarks:
64
- return None
65
- lm = res.multi_face_landmarks[0].landmark
66
- def xy(i): return np.array([lm[i].x*w, lm[i].y*h], dtype=np.float32)
67
- return np.stack([xy(LM["left_eye_outer"]), xy(LM["right_eye_outer"]), xy(LM["mid_forehead"])])
68
-
69
- def person_mask(img_bgr):
70
- with mp_selfie_seg.SelfieSegmentation(model_selection=1) as seg:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
 
2
  from PIL import Image
3
+ import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  def load_hairstyles():
5
+ folder = "hairstyles"
6
+ if not os.path.exists(folder):
7
+ return []
8
+ return [
9
+ Image.open(os.path.join(folder, f)).convert("RGBA")
10
+ for f in sorted(os.listdir(folder)) if f.endswith(".png")
11
+ ]
12
+ hairstyles = load_hairstyles()
13
+ def apply_hairstyle(user_img, style_index, x_offset, y_offset, scale):
14
+ if user_img is None or not hairstyles:
15
+ return None
16
+ user_img = user_img.convert("RGBA")
17
+ base_w, base_h = user_img.size
18
+
19
+ hairstyle = hairstyles[style_index]
20
+
21
+ # Resize the hairstyle based on scale
22
+ new_size = (int(base_w * scale), int(hairstyle.height * (base_w * scale / hairstyle.width)))
23
+ hairstyle = hairstyle.resize(new_size)
24
+
25
+ # Create a blank transparent image to position the hairstyle
26
+ composite = Image.new("RGBA", user_img.size)
27
+ paste_x = int((base_w - new_size[0]) / 2 + x_offset)
28
+ paste_y = int(y_offset)
29
+ composite.paste(hairstyle, (paste_x, paste_y), hairstyle)
30
+
31
+ # Overlay it
32
+ result = Image.alpha_composite(user_img, composite)
33
+ return result.convert("RGB")
34
+
35
+ with gr.Blocks() as demo:
36
+ gr.Markdown("## 💇 Salon Virtual Hairstyle Try-On (Adjustable)")
37
+ with gr.Row():
38
+ with gr.Column():
39
+ image_input = gr.Image(type="pil", label="📷 Upload an Image")
40
+ style_slider = gr.Slider(0, max(len(hairstyles)-1, 0), step=1, label="🎨 Select Hairstyle")
41
+ x_offset = gr.Slider(-200, 200, value=0, step=1, label="⬅️➡️ Move Left / Right")
42
+ y_offset = gr.Slider(-200, 200, value=0, step=1, label="⬆️⬇️ Move Up / Down")
43
+ scale = gr.Slider(0.3, 2.0, value=1.0, step=0.05, label="📏 Scale Hairstyle")
44
+ apply_btn = gr.Button("✨ Apply Hairstyle")
45
+ with gr.Column():
46
+ result_output = gr.Image(label="🔍 Result Preview")
47
+
48
+ apply_btn.click(
49
+ fn=apply_hairstyle,
50
+ inputs=[image_input, style_slider, x_offset, y_offset, scale],
51
+ outputs=result_output
52
+ )
53
+
54
+ demo.launch()