Seniordev22 commited on
Commit
12a8a6d
·
verified ·
1 Parent(s): c0d286a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +30 -16
app.py CHANGED
@@ -160,31 +160,45 @@ def get_beard_mask_fast(pil_image: Image.Image, exclude_mask: np.ndarray):
160
  if int(cls) == 0: # beard class
161
  m = results[0].masks.data[i].cpu().numpy()
162
  m = cv2.resize(m, (orig_w, orig_h), interpolation=cv2.INTER_LINEAR)
163
- mask = np.maximum(mask, (m > 0.35).astype(np.float32))
164
 
165
  # Remove protected areas
166
  mask = np.maximum(mask - exclude_mask, 0)
167
 
168
- if mask.sum() > 30:
169
- # ====================== IMPROVED ROUNDING + NO EXTRA SPACE ======================
170
 
171
- # Step 1: Light erosion to remove extra pixels
172
- kernel_erode = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
173
- mask = cv2.erode(mask, kernel_erode, iterations=1)
174
 
175
- # Step 2: Strong close with big elliptical kernel Best rounding
176
- kernel_close = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11, 11))
177
- mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel_close, iterations=2)
178
 
179
- # Step 3: Light open to clean noise
180
  kernel_open = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
181
  mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel_open, iterations=1)
182
 
183
- # Step 4: Soft blur for natural edges
184
- mask = cv2.GaussianBlur(mask, (7, 7), 1.8)
 
 
 
 
 
 
 
 
185
 
186
- # Step 5: Tight threshold → No extra space
187
- mask = (mask > 0.25).astype(np.float32)
 
 
 
 
 
 
188
 
189
  return mask
190
 
@@ -259,8 +273,8 @@ def process_face_whitening(input_image: Image.Image):
259
  hair_mask, exclude_mask, mustache_mask = get_hair_and_exclude_masks(img_resized)
260
  beard_mask = get_beard_mask_fast(img_resized, exclude_mask)
261
 
262
- # Combine beard + mustache with slight reduction on mustache
263
- beard_mask = np.maximum(beard_mask, mustache_mask * 0.90)
264
 
265
  final_resized = apply_strong_grey_hair(img_resized, hair_mask, beard_mask)
266
  final_img = final_resized.resize((ow, oh), Image.LANCZOS)
 
160
  if int(cls) == 0: # beard class
161
  m = results[0].masks.data[i].cpu().numpy()
162
  m = cv2.resize(m, (orig_w, orig_h), interpolation=cv2.INTER_LINEAR)
163
+ mask = np.maximum(mask, (m > 0.32).astype(np.float32)) # slightly lower threshold
164
 
165
  # Remove protected areas
166
  mask = np.maximum(mask - exclude_mask, 0)
167
 
168
+ if mask.sum() > 25: # lowered a bit
169
+ # ====================== HIGHLY IMPROVED ROUNDING ======================
170
 
171
+ # 1. Aggressive erosion to kill extra space
172
+ kernel_erode = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7))
173
+ mask = cv2.erode(mask, kernel_erode, iterations=2)
174
 
175
+ # 2. Strong close with very big kernel for perfect round corners
176
+ kernel_close = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (13, 13))
177
+ mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel_close, iterations=3)
178
 
179
+ # 3. Clean noise
180
  kernel_open = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
181
  mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel_open, iterations=1)
182
 
183
+ # 4. Contour based smoothing (Best for round & tight beard shape)
184
+ contours, _ = cv2.findContours((mask > 0.1).astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
185
+ if contours:
186
+ smooth_mask = np.zeros_like(mask, dtype=np.float32)
187
+ for cnt in contours:
188
+ if cv2.contourArea(cnt) > 50: # ignore very small noise
189
+ epsilon = 0.008 * cv2.arcLength(cnt, True) # lower = more round
190
+ approx = cv2.approxPolyDP(cnt, epsilon, True)
191
+ cv2.drawContours(smooth_mask, [approx], -1, 1.0, thickness=cv2.FILLED)
192
+ mask = smooth_mask
193
 
194
+ # 5. Final soft blur
195
+ mask = cv2.GaussianBlur(mask, (9, 9), 2.0)
196
+
197
+ # 6. Very tight final threshold (no extra space)
198
+ mask = (mask > 0.28).astype(np.float32)
199
+
200
+ # 7. Final light erosion for extra safety
201
+ mask = cv2.erode(mask, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)), iterations=1)
202
 
203
  return mask
204
 
 
273
  hair_mask, exclude_mask, mustache_mask = get_hair_and_exclude_masks(img_resized)
274
  beard_mask = get_beard_mask_fast(img_resized, exclude_mask)
275
 
276
+ # Combine with mustache
277
+ beard_mask = np.maximum(beard_mask, mustache_mask * 0.88)
278
 
279
  final_resized = apply_strong_grey_hair(img_resized, hair_mask, beard_mask)
280
  final_img = final_resized.resize((ow, oh), Image.LANCZOS)