RICHERGIRL commited on
Commit
fa8ff57
·
verified ·
1 Parent(s): d504db9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -31
app.py CHANGED
@@ -20,12 +20,15 @@ DEFAULT_MASK_PATHS = [
20
  "mask5.png",
21
  ]
22
 
23
- # Verify default masks exist
 
24
  for mask_path in DEFAULT_MASK_PATHS:
25
  try:
26
- Image.open(mask_path)
 
27
  except FileNotFoundError:
28
  print(f"Warning: Default mask file not found: {mask_path}")
 
29
 
30
  css = """
31
  #col-left { margin: 0 auto; max-width: 430px; }
@@ -33,20 +36,37 @@ css = """
33
  #col-right { margin: 0 auto; max-width: 430px; }
34
  #col-showcase { margin: 0 auto; max-width: 1100px; }
35
  #button { color: blue; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  """
37
 
38
  def remove_mask_background(mask_img):
39
  """Remove all backgrounds (white, black, transparent) from mask image"""
 
 
 
40
  mask_img = mask_img.convert("RGBA")
41
  datas = mask_img.getdata()
42
  new_data = []
43
 
44
  for item in datas:
45
- # Remove white (RGB > 240), black (RGB < 15), and existing transparent pixels
46
  if (item[0] > 240 and item[1] > 240 and item[2] > 240) or \
47
  (item[0] < 15 and item[1] < 15 and item[2] < 15) or \
48
  (item[3] == 0):
49
- new_data.append((255, 255, 255, 0)) # Fully transparent
50
  else:
51
  new_data.append(item)
52
 
@@ -67,10 +87,14 @@ def get_random_compliment():
67
  ]
68
  return random.choice(compliments)
69
 
70
- def apply_mask(person_img, mask_img, seed, randomize_seed):
71
- """Improved mask application using facial landmarks with perfect transparency"""
72
- if person_img is None or mask_img is None:
73
- return None, None, "Empty image"
 
 
 
 
74
 
75
  if randomize_seed:
76
  seed = random.randint(0, MAX_SEED)
@@ -79,8 +103,10 @@ def apply_mask(person_img, mask_img, seed, randomize_seed):
79
  # Convert to numpy array
80
  img_np = np.array(person_img)
81
 
82
- # Process the mask with aggressive background removal
83
  processed_mask = remove_mask_background(mask_img)
 
 
84
 
85
  # Detect facial landmarks
86
  landmarks = fa.get_landmarks(img_np)
@@ -125,23 +151,24 @@ def apply_mask(person_img, mask_img, seed, randomize_seed):
125
  print(f"Error applying mask: {e}")
126
  return person_img, seed, f"Error: {e}"
127
 
128
- def capture_and_process(mask_img, seed, randomize_seed):
129
- """Capture from webcam and apply mask with transparency"""
130
- temp_file = tempfile.NamedTemporaryFile(suffix=".jpg", delete=False)
131
- temp_path = temp_file.name
 
 
 
 
132
 
133
  cap = cv2.VideoCapture(0)
134
  ret, frame = cap.read()
135
-
136
- if ret:
137
- cv2.imwrite(temp_path, frame)
138
- pil_image = Image.open(temp_path)
139
- result_img, final_seed, info = apply_mask(pil_image, mask_img, seed, randomize_seed)
140
- cap.release()
141
- return result_img, final_seed, info
142
- else:
143
- cap.release()
144
  return None, seed, "Failed to capture image"
 
 
 
145
 
146
  # Create interface
147
  with gr.Blocks(css=css) as MaskSuggest:
@@ -158,13 +185,23 @@ with gr.Blocks(css=css) as MaskSuggest:
158
  )
159
 
160
  with gr.Column(elem_id="col-mid"):
161
- gr.Markdown("### Step 2. Upload a mask image")
162
- mask_img_input = gr.Image(label="Mask image (PNG with transparency)", type="pil")
163
- mask_img_example = gr.Examples(
164
- examples=["mask1.jpg", "mask2.png", "mask3.png"],
165
- inputs=mask_img_input,
166
- examples_per_page=12
167
- )
 
 
 
 
 
 
 
 
 
 
168
 
169
  with gr.Column(elem_id="col-right"):
170
  gr.Markdown("### Step 3. Get result")
@@ -173,13 +210,25 @@ with gr.Blocks(css=css) as MaskSuggest:
173
  randomize_seed = gr.Checkbox(value=True, label="Randomize seed", visible=False)
174
  seed_used = gr.Number(label="Seed used", visible=False)
175
  result_info = gr.Textbox(label="Status")
176
- process_button = gr.Button("Run", elem_id="button")
177
 
178
  process_button.click(
179
  fn=apply_mask,
180
- inputs=[person_img_input, mask_img_input, seed, randomize_seed],
181
  outputs=[image_out, seed_used, result_info],
182
  api_name='apply_mask'
183
  )
 
 
 
 
 
 
 
 
 
 
 
 
184
 
185
  MaskSuggest.queue(api_open=False).launch(show_api=False)
 
20
  "mask5.png",
21
  ]
22
 
23
+ # Preload all mask images
24
+ MASK_IMAGES = []
25
  for mask_path in DEFAULT_MASK_PATHS:
26
  try:
27
+ mask_img = Image.open(mask_path)
28
+ MASK_IMAGES.append(mask_img)
29
  except FileNotFoundError:
30
  print(f"Warning: Default mask file not found: {mask_path}")
31
+ MASK_IMAGES.append(None)
32
 
33
  css = """
34
  #col-left { margin: 0 auto; max-width: 430px; }
 
36
  #col-right { margin: 0 auto; max-width: 430px; }
37
  #col-showcase { margin: 0 auto; max-width: 1100px; }
38
  #button { color: blue; }
39
+ .mask-thumbnail {
40
+ cursor: pointer;
41
+ border: 2px solid transparent;
42
+ border-radius: 5px;
43
+ margin: 5px;
44
+ height: 100px;
45
+ object-fit: contain;
46
+ }
47
+ .mask-thumbnail:hover {
48
+ border-color: #4a6cf7;
49
+ }
50
+ .mask-thumbnail.selected {
51
+ border-color: #4a6cf7;
52
+ box-shadow: 0 0 10px rgba(74, 108, 247, 0.5);
53
+ }
54
  """
55
 
56
  def remove_mask_background(mask_img):
57
  """Remove all backgrounds (white, black, transparent) from mask image"""
58
+ if mask_img is None:
59
+ return None
60
+
61
  mask_img = mask_img.convert("RGBA")
62
  datas = mask_img.getdata()
63
  new_data = []
64
 
65
  for item in datas:
 
66
  if (item[0] > 240 and item[1] > 240 and item[2] > 240) or \
67
  (item[0] < 15 and item[1] < 15 and item[2] < 15) or \
68
  (item[3] == 0):
69
+ new_data.append((255, 255, 255, 0))
70
  else:
71
  new_data.append(item)
72
 
 
87
  ]
88
  return random.choice(compliments)
89
 
90
+ def apply_mask(person_img, mask_index, seed, randomize_seed):
91
+ """Apply selected mask to face with perfect transparency"""
92
+ if person_img is None or mask_index is None or mask_index >= len(MASK_IMAGES):
93
+ return None, None, "Empty image or invalid mask"
94
+
95
+ mask_img = MASK_IMAGES[mask_index]
96
+ if mask_img is None:
97
+ return None, None, "Mask not found"
98
 
99
  if randomize_seed:
100
  seed = random.randint(0, MAX_SEED)
 
103
  # Convert to numpy array
104
  img_np = np.array(person_img)
105
 
106
+ # Process the mask with background removal
107
  processed_mask = remove_mask_background(mask_img)
108
+ if processed_mask is None:
109
+ return None, None, "Mask processing failed"
110
 
111
  # Detect facial landmarks
112
  landmarks = fa.get_landmarks(img_np)
 
151
  print(f"Error applying mask: {e}")
152
  return person_img, seed, f"Error: {e}"
153
 
154
+ def capture_and_process(mask_index, seed, randomize_seed):
155
+ """Capture from webcam and apply selected mask"""
156
+ if mask_index is None or mask_index >= len(MASK_IMAGES):
157
+ return None, None, "Invalid mask selection"
158
+
159
+ mask_img = MASK_IMAGES[mask_index]
160
+ if mask_img is None:
161
+ return None, None, "Mask not found"
162
 
163
  cap = cv2.VideoCapture(0)
164
  ret, frame = cap.read()
165
+ cap.release()
166
+
167
+ if not ret:
 
 
 
 
 
 
168
  return None, seed, "Failed to capture image"
169
+
170
+ pil_image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
171
+ return apply_mask(pil_image, mask_index, seed, randomize_seed)
172
 
173
  # Create interface
174
  with gr.Blocks(css=css) as MaskSuggest:
 
185
  )
186
 
187
  with gr.Column(elem_id="col-mid"):
188
+ gr.Markdown("### Step 2. Choose a mask")
189
+
190
+ # Create mask selection thumbnails
191
+ with gr.Row():
192
+ for i, mask_img in enumerate(MASK_IMAGES):
193
+ if mask_img is not None:
194
+ thumbnail = mask_img.resize((100, 100), Image.Resampling.LANCZOS)
195
+ gr.Image(value=thumbnail, label=f"Mask {i+1}",
196
+ interactive=False, show_label=True,
197
+ elem_classes="mask-thumbnail").select(
198
+ lambda x, i=i: i,
199
+ outputs=[gr.Radio(choices=list(range(len(MASK_IMAGES))),
200
+ value=0, visible=False)]
201
+
202
+ # Hidden radio buttons for mask selection
203
+ mask_selection = gr.Radio(choices=list(range(len(MASK_IMAGES))),
204
+ label="Selected Mask", visible=False, value=0)
205
 
206
  with gr.Column(elem_id="col-right"):
207
  gr.Markdown("### Step 3. Get result")
 
210
  randomize_seed = gr.Checkbox(value=True, label="Randomize seed", visible=False)
211
  seed_used = gr.Number(label="Seed used", visible=False)
212
  result_info = gr.Textbox(label="Status")
213
+ process_button = gr.Button("Apply Mask", elem_id="button")
214
 
215
  process_button.click(
216
  fn=apply_mask,
217
+ inputs=[person_img_input, mask_selection, seed, randomize_seed],
218
  outputs=[image_out, seed_used, result_info],
219
  api_name='apply_mask'
220
  )
221
+
222
+ gr.Markdown("### Webcam Version")
223
+ with gr.Row():
224
+ webcam_button = gr.Button("Capture from Webcam")
225
+ webcam_output = gr.Image(label="Webcam Result")
226
+ webcam_status = gr.Textbox(label="Webcam Status")
227
+
228
+ webcam_button.click(
229
+ fn=capture_and_process,
230
+ inputs=[mask_selection, seed, randomize_seed],
231
+ outputs=[webcam_output, seed_used, webcam_status]
232
+ )
233
 
234
  MaskSuggest.queue(api_open=False).launch(show_api=False)