import cv2 import numpy as np from PIL import Image def colormap(rgb=True): color_list = np.array( [ 0.000, 0.000, 0.000, 1.000, 1.000, 1.000, 1.000, 0.498, 0.313, 0.392, 0.581, 0.929, 0.000, 0.447, 0.741, 0.850, 0.325, 0.098, 0.929, 0.694, 0.125, 0.494, 0.184, 0.556, 0.466, 0.674, 0.188, 0.301, 0.745, 0.933, 0.635, 0.078, 0.184, 0.300, 0.300, 0.300, 0.600, 0.600, 0.600, 1.000, 0.000, 0.000, 1.000, 0.500, 0.000, 0.749, 0.749, 0.000, 0.000, 1.000, 0.000, 0.000, 0.000, 1.000, 0.667, 0.000, 1.000, 0.333, 0.333, 0.000, 0.333, 0.667, 0.000, 0.333, 1.000, 0.000, 0.667, 0.333, 0.000, 0.667, 0.667, 0.000, 0.667, 1.000, 0.000, 1.000, 0.333, 0.000, 1.000, 0.667, 0.000, 1.000, 1.000, 0.000, 0.000, 0.333, 0.500, 0.000, 0.667, 0.500, 0.000, 1.000, 0.500, 0.333, 0.000, 0.500, 0.333, 0.333, 0.500, 0.333, 0.667, 0.500, 0.333, 1.000, 0.500, 0.667, 0.000, 0.500, 0.667, 0.333, 0.500, 0.667, 0.667, 0.500, 0.667, 1.000, 0.500, 1.000, 0.000, 0.500, 1.000, 0.333, 0.500, 1.000, 0.667, 0.500, 1.000, 1.000, 0.500, 0.000, 0.333, 1.000, 0.000, 0.667, 1.000, 0.000, 1.000, 1.000, 0.333, 0.000, 1.000, 0.333, 0.333, 1.000, 0.333, 0.667, 1.000, 0.333, 1.000, 1.000, 0.667, 0.000, 1.000, 0.667, 0.333, 1.000, 0.667, 0.667, 1.000, 0.667, 1.000, 1.000, 1.000, 0.000, 1.000, 1.000, 0.333, 1.000, 1.000, 0.667, 1.000, 0.167, 0.000, 0.000, 0.333, 0.000, 0.000, 0.500, 0.000, 0.000, 0.667, 0.000, 0.000, 0.833, 0.000, 0.000, 1.000, 0.000, 0.000, 0.000, 0.167, 0.000, 0.000, 0.333, 0.000, 0.000, 0.500, 0.000, 0.000, 0.667, 0.000, 0.000, 0.833, 0.000, 0.000, 1.000, 0.000, 0.000, 0.000, 0.167, 0.000, 0.000, 0.333, 0.000, 0.000, 0.500, 0.000, 0.000, 0.667, 0.000, 0.000, 0.833, 0.000, 0.000, 1.000, 0.143, 0.143, 0.143, 0.286, 0.286, 0.286, 0.429, 0.429, 0.429, 0.571, 0.571, 0.571, 0.714, 0.714, 0.714, 0.857, 0.857, 0.857, ] ).astype(np.float32) color_list = color_list.reshape((-1, 3)) * 255 if not rgb: color_list = color_list[:, ::-1] return color_list color_list = colormap() color_list = color_list.astype("uint8").tolist() def vis_add_mask(image, mask, color, alpha): color = np.array(color_list[color]) mask = mask > 0.5 image[mask] = image[mask] * (1 - alpha) + color * alpha return image.astype("uint8") def point_painter( input_image, input_points, point_color=5, point_alpha=0.9, point_radius=15, contour_color=2, contour_width=5, ): h, w = input_image.shape[:2] point_mask = np.zeros((h, w)).astype("uint8") for point in input_points: point_mask[point[1], point[0]] = 1 kernel = cv2.getStructuringElement(2, (point_radius, point_radius)) point_mask = cv2.dilate(point_mask, kernel) contour_radius = (contour_width - 1) // 2 dist_transform_fore = cv2.distanceTransform(point_mask, cv2.DIST_L2, 3) dist_transform_back = cv2.distanceTransform(1 - point_mask, cv2.DIST_L2, 3) dist_map = dist_transform_fore - dist_transform_back # ...:::!!!:::... contour_radius += 2 contour_mask = np.abs(np.clip(dist_map, -contour_radius, contour_radius)) contour_mask = contour_mask / np.max(contour_mask) contour_mask[contour_mask > 0.5] = 1.0 # paint mask painted_image = vis_add_mask( input_image.copy(), point_mask, point_color, point_alpha ) # paint contour painted_image = vis_add_mask( painted_image.copy(), 1 - contour_mask, contour_color, 1 ) return painted_image def mask_painter( input_image, input_mask, mask_color=5, mask_alpha=0.7, contour_color=1, contour_width=3, ): assert ( input_image.shape[:2] == input_mask.shape ), "different shape between image and mask" # 0: background, 1: foreground mask = np.clip(input_mask, 0, 1) contour_radius = (contour_width - 1) // 2 dist_transform_fore = cv2.distanceTransform(mask, cv2.DIST_L2, 3) dist_transform_back = cv2.distanceTransform(1 - mask, cv2.DIST_L2, 3) dist_map = dist_transform_fore - dist_transform_back # ...:::!!!:::... contour_radius += 2 contour_mask = np.abs(np.clip(dist_map, -contour_radius, contour_radius)) contour_mask = contour_mask / np.max(contour_mask) contour_mask[contour_mask > 0.5] = 1.0 # paint mask painted_image = vis_add_mask( input_image.copy(), mask.copy(), mask_color, mask_alpha ) # paint contour painted_image = vis_add_mask( painted_image.copy(), 1 - contour_mask, contour_color, 1 ) return painted_image def background_remover(input_image, input_mask): """ input_image: H, W, 3, np.array input_mask: H, W, np.array image_wo_background: PIL.Image """ assert ( input_image.shape[:2] == input_mask.shape ), "different shape between image and mask" # 0: background, 1: foreground mask = np.expand_dims(np.clip(input_mask, 0, 1), axis=2) * 255 image_wo_background = np.concatenate([input_image, mask], axis=2) # H, W, 4 image_wo_background = Image.fromarray(image_wo_background).convert("RGBA") return image_wo_background