Spaces:
Running
Running
| import cv2 | |
| import numpy as np | |
| from scipy.ndimage import binary_dilation, binary_erosion | |
| def dilate_mask(mask: np.ndarray, iterations: int = 5) -> np.ndarray: | |
| """Morphologically dilate a binary mask.""" | |
| kernel = np.ones((5, 5), np.uint8) | |
| return cv2.dilate(mask, kernel, iterations=iterations) | |
| def erode_mask(mask: np.ndarray, iterations: int = 3) -> np.ndarray: | |
| """Morphologically erode a binary mask.""" | |
| kernel = np.ones((5, 5), np.uint8) | |
| return cv2.erode(mask, kernel, iterations=iterations) | |
| def feather_mask(mask: np.ndarray, sigma: float = 15.0) -> np.ndarray: | |
| """ | |
| Apply Gaussian feathering to a binary mask. | |
| Returns float32 mask in [0, 1]. | |
| """ | |
| f = mask.astype(np.float32) / 255.0 if mask.max() > 1 else mask.astype(np.float32) | |
| feathered = cv2.GaussianBlur(f, (0, 0), sigmaX=sigma, sigmaY=sigma) | |
| return feathered | |
| def merge_masks(masks: list, weights: list | None = None) -> np.ndarray: | |
| """ | |
| Merge multiple masks by weighted average. | |
| All masks should be same shape, uint8 or float32 in [0,255] or [0,1]. | |
| """ | |
| if not masks: | |
| raise ValueError("No masks provided") | |
| if weights is None: | |
| weights = [1.0] * len(masks) | |
| result = np.zeros_like(masks[0], dtype=np.float32) | |
| total_w = sum(weights) | |
| for m, w in zip(masks, weights): | |
| f = m.astype(np.float32) / 255.0 if m.max() > 1 else m.astype(np.float32) | |
| result += f * (w / total_w) | |
| return np.clip(result, 0, 1) | |
| def get_boundary_mask(mask: np.ndarray, dilation: int = 5, erosion: int = 3) -> np.ndarray: | |
| """Extract the boundary region of a binary mask.""" | |
| dilated = dilate_mask(mask, dilation) | |
| eroded = erode_mask(mask, erosion) | |
| return cv2.subtract(dilated, eroded) | |
| def create_face_ellipse_mask(h: int, w: int, | |
| cx: int, cy: int, | |
| rx: int, ry: int) -> np.ndarray: | |
| """Create an elliptical face mask.""" | |
| mask = np.zeros((h, w), dtype=np.uint8) | |
| cv2.ellipse(mask, (cx, cy), (rx, ry), 0, 0, 360, 255, -1) | |
| return mask | |