Seniordev22 commited on
Commit
6e09aed
·
verified ·
1 Parent(s): 1ee3050

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +22 -28
app.py CHANGED
@@ -146,7 +146,7 @@ def get_hair_and_exclude_masks(pil_image: Image.Image):
146
  exclude = cv2.GaussianBlur(exclude, (5, 5), 1.2)
147
  exclude = cv2.resize(exclude, (orig_w, orig_h), interpolation=cv2.INTER_LINEAR)
148
 
149
- # Lip mask (protection)
150
  lip_mask = np.zeros((128, 128), dtype=np.float32)
151
  lip_mask = np.maximum(lip_mask, (probs[10].numpy() > 0.42).astype(np.float32))
152
  lip_mask = np.maximum(lip_mask, (probs[11].numpy() > 0.42).astype(np.float32))
@@ -214,7 +214,7 @@ def get_beard_mask_fast(pil_image: Image.Image, exclude_mask: np.ndarray, lip_ma
214
  mask[lip_mask > 0] = 0
215
  return mask
216
 
217
- # ====================== FIXED COLOR TRANSFER (NO RED TINT + BEARD SAME AS HAIR) ======================
218
  @timed("Color Transfer")
219
  def apply_strong_grey_hair(image: Image.Image, hair_mask: np.ndarray, beard_mask: np.ndarray):
220
  comb = np.maximum(hair_mask, beard_mask)
@@ -222,47 +222,41 @@ def apply_strong_grey_hair(image: Image.Image, hair_mask: np.ndarray, beard_mask
222
  comb = cv2.GaussianBlur(comb, (5,5), 1.5)
223
 
224
  img = np.array(image).astype(np.float32) / 255.0
225
-
226
- # LAB for better color control
227
- lab = cv2.cvtColor((img * 255).astype(np.uint8), cv2.COLOR_RGB2LAB).astype(np.float32)
228
  hsv = cv2.cvtColor((img * 255).astype(np.uint8), cv2.COLOR_RGB2HSV).astype(np.float32)
229
 
230
- # Hair Grey Base
231
  hsv_hair = hsv.copy()
232
- hsv_hair[..., 1] = hsv_hair[..., 1] * (1 - 0.85 * hair_mask) # strong desaturation
233
  original_v = hsv[..., 2]
 
234
  hsv_hair[..., 2] = np.clip(
235
- original_v + (85 * hair_mask) - (original_v * 0.30 * hair_mask),
236
- 105, 205
237
  )
238
- hair_grey_rgb = cv2.cvtColor(hsv_hair.astype(np.uint8), cv2.COLOR_HSV2RGB).astype(np.float32) / 255.0
239
- hair_grey_lab = cv2.cvtColor((hair_grey_rgb * 255).astype(np.uint8), cv2.COLOR_RGB2LAB).astype(np.float32)
240
 
241
- # Apply to Beard + Mustache (Exactly same as hair)
242
- beard_mask_3ch = np.stack([beard_mask, beard_mask, beard_mask], axis=2)
243
- final_lab = lab.copy()
244
- final_lab = final_lab * (1 - beard_mask_3ch) + hair_grey_lab * beard_mask_3ch
245
 
246
- # Remove Red Tint forcefully (a-channel = red-green)
247
- beard_area = beard_mask > 0.12
248
- if np.any(beard_area):
249
- final_lab[beard_area, 1] = final_lab[beard_area, 1] * 0.20 # strong red neutralization
250
 
251
- # Apply Hair on top
252
  hair_mask_3ch = np.stack([hair_mask, hair_mask, hair_mask], axis=2)
253
- final_lab = final_lab * (1 - hair_mask_3ch) + hair_grey_lab * hair_mask_3ch
254
 
255
- # Convert back to RGB
256
- final = cv2.cvtColor(final_lab.astype(np.uint8), cv2.COLOR_LAB2RGB).astype(np.float32) / 255.0
257
-
258
- # Final protection + cool tint
259
  comb_3ch = np.stack([comb, comb, comb], axis=2)
260
  final = final * comb_3ch + img * (1 - comb_3ch)
261
- final = final + (np.array([8, 6, 4], dtype=np.float32)/255.0 * comb[..., None] * 0.15)
 
 
262
 
263
  final = np.clip(final * 255, 0, 255).astype(np.uint8)
264
  result = Image.fromarray(final)
265
- result = result.filter(ImageFilter.UnsharpMask(radius=0.8, percent=80, threshold=1))
266
 
267
  return result
268
 
@@ -281,7 +275,7 @@ def process_face_whitening(input_image: Image.Image):
281
  hair_mask, exclude_mask, mustache_mask, lip_mask = get_hair_and_exclude_masks(img_resized)
282
  beard_mask = get_beard_mask_fast(img_resized, exclude_mask, lip_mask)
283
 
284
- # Strong blending
285
  beard_mask = np.maximum(beard_mask, mustache_mask * 0.98)
286
 
287
  # Extra boost for thin mustache
 
146
  exclude = cv2.GaussianBlur(exclude, (5, 5), 1.2)
147
  exclude = cv2.resize(exclude, (orig_w, orig_h), interpolation=cv2.INTER_LINEAR)
148
 
149
+ # Lip mask
150
  lip_mask = np.zeros((128, 128), dtype=np.float32)
151
  lip_mask = np.maximum(lip_mask, (probs[10].numpy() > 0.42).astype(np.float32))
152
  lip_mask = np.maximum(lip_mask, (probs[11].numpy() > 0.42).astype(np.float32))
 
214
  mask[lip_mask > 0] = 0
215
  return mask
216
 
217
+ # ====================== COLOR TRANSFER - BEARD SAME AS HAIR (FIXED) ======================
218
  @timed("Color Transfer")
219
  def apply_strong_grey_hair(image: Image.Image, hair_mask: np.ndarray, beard_mask: np.ndarray):
220
  comb = np.maximum(hair_mask, beard_mask)
 
222
  comb = cv2.GaussianBlur(comb, (5,5), 1.5)
223
 
224
  img = np.array(image).astype(np.float32) / 255.0
 
 
 
225
  hsv = cv2.cvtColor((img * 255).astype(np.uint8), cv2.COLOR_RGB2HSV).astype(np.float32)
226
 
227
+ # === Hair Grey (Base) ===
228
  hsv_hair = hsv.copy()
229
+ hsv_hair[..., 1] = hsv_hair[..., 1] * (1 - 0.78 * hair_mask)
230
  original_v = hsv[..., 2]
231
+ boost_amount = 89 * hair_mask
232
  hsv_hair[..., 2] = np.clip(
233
+ original_v + boost_amount - (original_v * 0.35 * hair_mask),
234
+ 110, 210
235
  )
236
+ hair_grey = cv2.cvtColor(hsv_hair.astype(np.uint8), cv2.COLOR_HSV2RGB).astype(np.float32) / 255.0
 
237
 
238
+ # === Create a fully grey image for beard (FIX) ===
239
+ gray = cv2.cvtColor((img * 255).astype(np.uint8), cv2.COLOR_RGB2GRAY)
240
+ gray = np.stack([gray, gray, gray], axis=2).astype(np.float32) / 255.0
 
241
 
242
+ # === Beard + Mustache get the grey image (no more red!) ===
243
+ beard_mask_3ch = np.stack([beard_mask, beard_mask, beard_mask], axis=2)
244
+ final = gray * beard_mask_3ch + img * (1 - beard_mask_3ch)
 
245
 
246
+ # === Hair area gets the hair_grey (preserves texture) ===
247
  hair_mask_3ch = np.stack([hair_mask, hair_mask, hair_mask], axis=2)
248
+ final = hair_grey * hair_mask_3ch + final * (1 - hair_mask_3ch)
249
 
250
+ # === Final protection (avoid artifacts outside hair+beard) ===
 
 
 
251
  comb_3ch = np.stack([comb, comb, comb], axis=2)
252
  final = final * comb_3ch + img * (1 - comb_3ch)
253
+
254
+ # === Light cool tint for natural look ===
255
+ final = final + (np.array([9, 7, 5], dtype=np.float32) / 255.0 * comb[..., None] * 0.18)
256
 
257
  final = np.clip(final * 255, 0, 255).astype(np.uint8)
258
  result = Image.fromarray(final)
259
+ result = result.filter(ImageFilter.UnsharpMask(radius=0.8, percent=75, threshold=1))
260
 
261
  return result
262
 
 
275
  hair_mask, exclude_mask, mustache_mask, lip_mask = get_hair_and_exclude_masks(img_resized)
276
  beard_mask = get_beard_mask_fast(img_resized, exclude_mask, lip_mask)
277
 
278
+ # Strong blending for beard + mustache
279
  beard_mask = np.maximum(beard_mask, mustache_mask * 0.98)
280
 
281
  # Extra boost for thin mustache