Image Segmentation
Transformers
PyTorch
English
garment-mask-generation
image-inpainting
fashion
garment-mask
densepose
human-parsing
Instructions to use Ekliipce/wearit-garment-mask with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Ekliipce/wearit-garment-mask with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-segmentation", model="Ekliipce/wearit-garment-mask")# Load model directly from transformers import GarmentMaskPipeline model = GarmentMaskPipeline.from_pretrained("Ekliipce/wearit-garment-mask", device_map="auto") - Notebooks
- Google Colab
- Kaggle
| import numpy as np | |
| import cv2 | |
| from PIL import Image | |
| from typing import Union | |
| from mappings import ( | |
| DENSE_INDEX_MAP, | |
| ATR_MAPPING, | |
| LIP_MAPPING, | |
| MASK_CLOTH_PARTS, | |
| MASK_DENSE_PARTS, | |
| PROTECT_BODY_PARTS, | |
| PROTECT_CLOTH_PARTS | |
| ) | |
| def get_person_height(mask): | |
| mask = (mask > 127).astype(np.uint8) | |
| nonzero_pixels = np.any(mask, axis=1) | |
| if not np.any(nonzero_pixels): | |
| return 50 | |
| ymin, ymax = np.where(nonzero_pixels)[0][[0, -1]] | |
| person_height = max(50, ymax - ymin) | |
| return person_height | |
| def calculate_kernels(person_height): | |
| dilate_size = max(1, person_height // 30) | |
| dilate_size = dilate_size if dilate_size % 2 == 1 else dilate_size + 1 | |
| dilate_kernel = np.ones((dilate_size, dilate_size), np.uint8) | |
| kernel_size = max(5, person_height // 15) | |
| kernel_size = kernel_size if kernel_size % 2 == 1 else kernel_size + 1 | |
| return dilate_kernel, kernel_size | |
| def part_mask_of(part: Union[str, list], parse: np.ndarray, mapping: dict): | |
| if isinstance(part, str): | |
| part = [part] | |
| mask = np.zeros_like(parse, dtype=np.uint8) | |
| for p in part: | |
| if p not in mapping: | |
| continue | |
| val = mapping[p] | |
| if isinstance(val, list): | |
| for i in val: | |
| mask[parse == i] = 1 | |
| else: | |
| mask[parse == val] = 1 | |
| return mask | |
| def hull_mask(mask_area: np.ndarray): | |
| mask_area = (mask_area * 255).astype(np.uint8) | |
| _, binary = cv2.threshold(mask_area, 127, 255, cv2.THRESH_BINARY) | |
| contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
| hull_mask_result = np.zeros_like(binary) | |
| for cnt in contours: | |
| hull = cv2.convexHull(cnt) | |
| cv2.fillPoly(hull_mask_result, [hull], 255) | |
| return (hull_mask_result > 127).astype(np.uint8) | |
| def compute_strong_protect_area(densepose_mask, schp_lip_mask, schp_atr_mask, dilate_kernel): | |
| hands_protect_area = part_mask_of(['hands', 'feet', 'face'], densepose_mask, DENSE_INDEX_MAP) | |
| hands_protect_area = cv2.dilate(hands_protect_area, dilate_kernel, iterations=1) | |
| arms_legs_schp = ( | |
| part_mask_of(['Left-arm', 'Right-arm', 'Left-leg', 'Right-leg'], schp_atr_mask, ATR_MAPPING) | | |
| part_mask_of(['Left-arm', 'Right-arm', 'Left-leg', 'Right-leg'], schp_lip_mask, LIP_MAPPING) | |
| ) | |
| hands_protect_area = hands_protect_area & arms_legs_schp | |
| face_protect_area = part_mask_of('Face', schp_lip_mask, LIP_MAPPING) | |
| return (hands_protect_area | face_protect_area).astype(np.uint8) | |
| def compute_weak_protect_area(schp_lip_mask, schp_atr_mask, strong_protect_area, part): | |
| body_protect_area = ( | |
| part_mask_of(PROTECT_BODY_PARTS[part], schp_lip_mask, LIP_MAPPING) | | |
| part_mask_of(PROTECT_BODY_PARTS[part], schp_atr_mask, ATR_MAPPING) | |
| ) | |
| hair_protect_area = ( | |
| part_mask_of(['Hair'], schp_lip_mask, LIP_MAPPING) | | |
| part_mask_of(['Hair'], schp_atr_mask, ATR_MAPPING) | |
| ) | |
| cloth_protect_area = part_mask_of(PROTECT_CLOTH_PARTS[part]['ATR'], schp_atr_mask, ATR_MAPPING) | |
| accessory_parts = ['Hat', 'Glove', 'Sunglasses', 'Bag', 'Left-shoe', 'Right-shoe', 'Scarf', 'Socks'] | |
| accessory_protect_area = ( | |
| part_mask_of(accessory_parts, schp_lip_mask, LIP_MAPPING) | | |
| part_mask_of(accessory_parts, schp_atr_mask, ATR_MAPPING) | |
| ) | |
| weak_area = (body_protect_area | cloth_protect_area | hair_protect_area | | |
| strong_protect_area | accessory_protect_area) | |
| return weak_area.astype(np.uint8) | |
| def compute_mask_area(densepose_mask, schp_lip_mask, schp_atr_mask, | |
| weak_protect_area, strong_protect_area, | |
| dilate_kernel, part): | |
| strong_mask_area = ( | |
| part_mask_of(MASK_CLOTH_PARTS[part], schp_lip_mask, LIP_MAPPING) | | |
| part_mask_of(MASK_CLOTH_PARTS[part], schp_atr_mask, ATR_MAPPING) | |
| ) | |
| background_area = ( | |
| part_mask_of(['Background'], schp_lip_mask, LIP_MAPPING) & | |
| part_mask_of(['Background'], schp_atr_mask, ATR_MAPPING) | |
| ) | |
| mask_dense_area = part_mask_of(MASK_DENSE_PARTS[part], densepose_mask, DENSE_INDEX_MAP) | |
| mask_dense_area = cv2.resize(mask_dense_area.astype(np.uint8), None, fx=0.25, fy=0.25, interpolation=cv2.INTER_NEAREST) | |
| mask_dense_area = cv2.dilate(mask_dense_area, dilate_kernel, iterations=2) | |
| mask_dense_area = cv2.resize(mask_dense_area.astype(np.uint8), None, fx=4, fy=4, interpolation=cv2.INTER_NEAREST) | |
| target_shape = densepose_mask.shape | |
| def resize_mask(mask, target_shape): | |
| return cv2.resize(mask.astype(np.uint8), (target_shape[1], target_shape[0]), interpolation=cv2.INTER_NEAREST) | |
| weak_protect_area = resize_mask(weak_protect_area, target_shape) | |
| background_area = resize_mask(background_area, target_shape) | |
| mask_dense_area = resize_mask(mask_dense_area, target_shape) | |
| base_area = np.ones_like(densepose_mask, dtype=np.uint8) | |
| mask_area = (base_area & (~weak_protect_area) & (~background_area)) | mask_dense_area | |
| mask_area = hull_mask(mask_area) | |
| mask_area = (mask_area & (~weak_protect_area)).astype(np.uint8) | |
| return mask_area, background_area | |
| def safe_dilate(mask, kernel, iterations, protect_mask): | |
| dilated_mask = mask.copy() | |
| for _ in range(iterations): | |
| temp_dilated = cv2.dilate(dilated_mask, kernel, iterations=1) | |
| temp_dilated[protect_mask > 0] = 0 | |
| dilated_mask = temp_dilated | |
| return dilated_mask | |
| def finalize_mask(mask_area, kernal_size, strong_mask_area, strong_protect_area, dilate_kernel): | |
| mask_area = (mask_area * 255).astype(np.uint8) | |
| mask_area = cv2.GaussianBlur(mask_area, (kernal_size, kernal_size), 0) | |
| mask_area = np.where(mask_area < 25, 0, 1).astype(np.uint8) | |
| mask_area = (mask_area | strong_mask_area) & (~strong_protect_area) | |
| mask_area = safe_dilate(mask_area, dilate_kernel, iterations=1, protect_mask=strong_protect_area) | |
| return Image.fromarray((mask_area * 255).astype(np.uint8)) | |
| def keep_largest_connected_component(mask_np): | |
| mask_uint8 = (mask_np > 128).astype(np.uint8) | |
| num_labels, labels, stats, _ = cv2.connectedComponentsWithStats(mask_uint8, connectivity=8) | |
| if num_labels <= 1: | |
| return mask_uint8 * 255 | |
| largest_label = 1 + np.argmax(stats[1:, cv2.CC_STAT_AREA]) | |
| cleaned_mask = np.zeros_like(mask_uint8) | |
| cleaned_mask[labels == largest_label] = 1 | |
| return cleaned_mask * 255 |