Spaces:
Build error
Build error
Delete overlay.py
Browse files- overlay.py +0 -45
overlay.py
DELETED
|
@@ -1,45 +0,0 @@
|
|
| 1 |
-
import cv2
|
| 2 |
-
import numpy as np
|
| 3 |
-
|
| 4 |
-
def _read_png_rgba(path):
|
| 5 |
-
png = cv2.imread(path, cv2.IMREAD_UNCHANGED)
|
| 6 |
-
if png is None or png.shape[2] != 4:
|
| 7 |
-
raise ValueError("Hairstyle PNG must be RGBA with transparency.")
|
| 8 |
-
return png
|
| 9 |
-
|
| 10 |
-
def auto_align(png_rgba, mask, landmarks=None):
|
| 11 |
-
"""Scale & position the hairstyle PNG to roughly cover the mask area."""
|
| 12 |
-
mh, mw = mask.shape[:2]
|
| 13 |
-
# target box from mask
|
| 14 |
-
ys, xs = np.where(mask > 0)
|
| 15 |
-
if len(xs) == 0 or len(ys) == 0:
|
| 16 |
-
return cv2.resize(png_rgba, (mw, mh))
|
| 17 |
-
x0, x1 = xs.min(), xs.max()
|
| 18 |
-
y0, y1 = ys.min(), ys.max()
|
| 19 |
-
tw, th = int((x1 - x0) * 1.1), int((y1 - y0) * 0.7) # slightly wider; less tall
|
| 20 |
-
tw = max(1, min(tw, mw))
|
| 21 |
-
th = max(1, min(th, mh))
|
| 22 |
-
aligned = cv2.resize(png_rgba, (tw, th))
|
| 23 |
-
canvas = np.zeros((mh, mw, 4), dtype=np.uint8)
|
| 24 |
-
|
| 25 |
-
# top-align near upper mask region (approx forehead)
|
| 26 |
-
y = max(0, y0 - int(0.25 * th))
|
| 27 |
-
x = max(0, x0 - int(0.05 * tw))
|
| 28 |
-
|
| 29 |
-
y2 = min(mh, y + th); x2 = min(mw, x + tw)
|
| 30 |
-
crop_h, crop_w = y2 - y, x2 - x
|
| 31 |
-
canvas[y:y2, x:x2] = aligned[:crop_h, :crop_w]
|
| 32 |
-
return canvas
|
| 33 |
-
|
| 34 |
-
def _alpha_blend(base_bgr, overlay_rgba):
|
| 35 |
-
bgr = base_bgr.copy()
|
| 36 |
-
alpha = overlay_rgba[:, :, 3:4] / 255.0
|
| 37 |
-
rgb = overlay_rgba[:, :, :3]
|
| 38 |
-
bgr = (alpha * rgb + (1 - alpha) * bgr).astype(np.uint8)
|
| 39 |
-
return bgr
|
| 40 |
-
|
| 41 |
-
def apply_hairstyle(img_bgr, style_path, mask, landmarks=None):
|
| 42 |
-
png = _read_png_rgba(style_path)
|
| 43 |
-
aligned = auto_align(png, mask, landmarks)
|
| 44 |
-
out = _alpha_blend(img_bgr, aligned)
|
| 45 |
-
return out
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|