Files changed (1) hide show
  1. app.py +42 -20
app.py CHANGED
@@ -1,8 +1,11 @@
1
  import gradio as gr
2
  from PIL import Image
3
  import os
 
 
 
4
 
5
- # Load all hairstyle images from folder
6
  def load_hairstyles():
7
  folder = "hairstyles"
8
  if not os.path.exists(folder):
@@ -13,36 +16,54 @@ def load_hairstyles():
13
  ]
14
 
15
  hairstyles = load_hairstyles()
 
16
 
17
- # Automatically apply hairstyle to uploaded image
18
  def apply_hairstyle(user_img, style_index):
19
  if user_img is None or not hairstyles:
20
  return None
21
 
22
- user_img = user_img.convert("RGBA")
23
- base_w, base_h = user_img.size
24
- hairstyle = hairstyles[style_index]
 
25
 
26
- # Resize hairstyle to match width of head image
27
- scale_factor = 0.9 # Adjust if needed
28
- new_width = int(base_w * scale_factor)
29
- new_height = int(hairstyle.height * (new_width / hairstyle.width))
30
- resized_hairstyle = hairstyle.resize((new_width, new_height))
31
 
32
- # Automatically center it near the top
33
- paste_x = (base_w - new_width) // 2
34
- paste_y = int(base_h * 0.05) # Adjust this offset if needed
35
 
36
- composite = Image.new("RGBA", user_img.size)
37
- composite.paste(resized_hairstyle, (paste_x, paste_y), resized_hairstyle)
 
 
 
 
 
38
 
39
- final = Image.alpha_composite(user_img, composite)
40
- return final.convert("RGB")
41
 
42
- # Gradio Interface (no sliders shown to user)
43
- with gr.Blocks() as demo:
44
- gr.Markdown("## πŸ’‡ Salon Virtual Hairstyle Try-On (Auto Fit – No Adjustment Needed)")
 
 
 
 
 
 
 
 
 
 
 
 
45
 
 
 
 
46
  with gr.Row():
47
  with gr.Column():
48
  image_input = gr.Image(type="pil", label="πŸ“· Upload Your Image")
@@ -58,3 +79,4 @@ with gr.Blocks() as demo:
58
  )
59
 
60
  demo.launch()
 
 
1
  import gradio as gr
2
  from PIL import Image
3
  import os
4
+ import cv2
5
+ import numpy as np
6
+ import mediapipe as mp
7
 
8
+ # Load hairstyles from 'hairstyles' folder
9
  def load_hairstyles():
10
  folder = "hairstyles"
11
  if not os.path.exists(folder):
 
16
  ]
17
 
18
  hairstyles = load_hairstyles()
19
+ mp_face_detection = mp.solutions.face_detection
20
 
21
+ # Apply hairstyle using face detection to auto-align on head
22
  def apply_hairstyle(user_img, style_index):
23
  if user_img is None or not hairstyles:
24
  return None
25
 
26
+ # Convert to CV2 image for detection
27
+ img_cv2 = np.array(user_img.convert("RGB"))
28
+ img_cv2 = cv2.cvtColor(img_cv2, cv2.COLOR_RGB2BGR)
29
+ h_img, w_img = img_cv2.shape[:2]
30
 
31
+ with mp_face_detection.FaceDetection(model_selection=1, min_detection_confidence=0.5) as face_detection:
32
+ results = face_detection.process(cv2.cvtColor(img_cv2, cv2.COLOR_BGR2RGB))
 
 
 
33
 
34
+ if not results.detections:
35
+ return user_img # No face detected, return original
 
36
 
37
+ # Use first face
38
+ detection = results.detections[0]
39
+ bbox = detection.location_data.relative_bounding_box
40
+ x = int(bbox.xmin * w_img)
41
+ y = int(bbox.ymin * h_img)
42
+ w = int(bbox.width * w_img)
43
+ h = int(bbox.height * h_img)
44
 
45
+ # Estimate head top
46
+ top_y = max(y - int(h * 0.6), 0)
47
 
48
+ # Load and resize hairstyle
49
+ hairstyle = hairstyles[style_index]
50
+ new_width = int(w * 1.1) # Slightly wider than face
51
+ new_height = int(hairstyle.height * (new_width / hairstyle.width))
52
+ resized_hair = hairstyle.resize((new_width, new_height))
53
+
54
+ # Create output image
55
+ user_img = user_img.convert("RGBA")
56
+ composite = Image.new("RGBA", user_img.size)
57
+ paste_x = x - int((new_width - w) / 2)
58
+ paste_y = top_y
59
+ composite.paste(resized_hair, (paste_x, paste_y), resized_hair)
60
+
61
+ final = Image.alpha_composite(user_img, composite)
62
+ return final.convert("RGB")
63
 
64
+ # Gradio Interface
65
+ with gr.Blocks() as demo:
66
+ gr.Markdown("## πŸ’‡ Salon Virtual Hairstyle Try-On (Face-Aligned, No Adjustment Needed)")
67
  with gr.Row():
68
  with gr.Column():
69
  image_input = gr.Image(type="pil", label="πŸ“· Upload Your Image")
 
79
  )
80
 
81
  demo.launch()
82
+