def cutout(image_path, trimap_path, cutout_path): """ Generate a cutout image from an input image and an input trimap. This method is using closed-form alpha matting as proposed by :cite:`levin2007closed` and multi-level foreground extraction :cite:`germer2020multilevel`. Parameters ---------- image_path: str Path of input image trimap_path: str Path of input trimap cutout_path: str Path of output cutout image Example ------- >>> cutout("../data/lemur.png", "../data/lemur_trimap.png", "lemur_cutout.png") """ image = load_image(image_path, "RGB") trimap = load_image(trimap_path, "GRAY") if image.shape[:2] != trimap.shape[:2]: raise ValueError("Input image and trimap must have same size") alpha = estimate_alpha_cf(image, trimap) foreground = estimate_foreground_ml(image, alpha) cutout = stack_images(foreground, alpha) save_image(cutout_path, cutout)
def alpha_matting_cutout( img, mask, foreground_threshold, background_threshold, erode_structure_size, ): base_size = (1000, 1000) size = img.size img.thumbnail(base_size, Image.LANCZOS) mask = mask.resize(img.size, Image.LANCZOS) img = np.asarray(img) mask = np.asarray(mask) # guess likely foreground/background is_foreground = mask > foreground_threshold is_background = mask < background_threshold # erode foreground/background structure = None if erode_structure_size > 0: structure = np.ones((erode_structure_size, erode_structure_size), dtype=np.int) is_foreground = binary_erosion(is_foreground, structure=structure) is_background = binary_erosion(is_background, structure=structure, border_value=1) # build trimap # 0 = background # 128 = unknown # 255 = foreground trimap = np.full(mask.shape, dtype=np.uint8, fill_value=128) trimap[is_foreground] = 255 trimap[is_background] = 0 # build the cutout image img_normalized = img / 255.0 trimap_normalized = trimap / 255.0 alpha = estimate_alpha_cf(img_normalized, trimap_normalized) foreground = estimate_foreground_ml(img_normalized, alpha) cutout = stack_images(foreground, alpha) cutout = np.clip(cutout * 255, 0, 255).astype(np.uint8) cutout = Image.fromarray(cutout) cutout = cutout.resize(size, Image.LANCZOS) return cutout
def alpha_matting_cutout( self, foreground_threshold=240, background_threshold=10, erode_structure_size=10, ) -> Image: base_size = (1000, 1000) size = self.__image.size self.__image.thumbnail(base_size, Image.LANCZOS) mask = self.__mask.resize(self.__image.size, Image.LANCZOS) img = numpy.asarray(self.__image) mask = numpy.asarray(mask) self.__image.close() self.__mask.close() # Guess likely foreground/background is_foreground = mask > foreground_threshold is_background = mask < background_threshold # Erode foreground/background structure = None if erode_structure_size > 0: structure = numpy.ones( (erode_structure_size, erode_structure_size), dtype=numpy.int) is_foreground = binary_erosion(is_foreground, structure=structure) is_background = binary_erosion(is_background, structure=structure, border_value=1) trimap = numpy.full(mask.shape, dtype=numpy.uint8, fill_value=128) trimap[is_foreground] = 255 trimap[is_background] = 0 # Build the cutout image img_normalized = img / 255.0 trimap_normalized = trimap / 255.0 alpha = estimate_alpha_cf(img_normalized, trimap_normalized) foreground = estimate_foreground_ml(img_normalized, alpha) cutout = stack_images(foreground, alpha) cutout = numpy.clip(cutout * 255, 0, 255).astype(numpy.uint8) cutout = Image.fromarray(cutout) cutout = cutout.resize(size, Image.LANCZOS) return cutout