Spaces:
Build error
Build error
| import cv2 | |
| import gradio as gr | |
| from typing import Union, Tuple | |
| from PIL import Image, ImageOps | |
| import numpy as np | |
| import torch | |
| model = torch.jit.load('./model/model.pt').eval() | |
| def resize_with_padding(img: Image.Image, expected_size: Tuple[int, int]) -> Image.Image: | |
| img.thumbnail((expected_size[0], expected_size[1])) | |
| delta_width = expected_size[0] - img.size[0] | |
| delta_height = expected_size[1] - img.size[1] | |
| pad_width = delta_width // 2 | |
| pad_height = delta_height // 2 | |
| padding = (pad_width, pad_height, delta_width - pad_width, delta_height - pad_height) | |
| return ImageOps.expand(img, padding), padding | |
| def preprocess_image(img: Image.Image, size: int = 512) -> Tuple[Image.Image, torch.tensor, Tuple[int]]: | |
| pil_img, padding = resize_with_padding(img, (size, size)) | |
| img = (np.array(pil_img).astype(np.float32) / 255) - np.array([0.485, 0.456, 0.406], dtype=np.float32).reshape(1, 1, 3) | |
| img = img / np.array([0.229, 0.224, 0.225], dtype=np.float32).reshape(1, 1, 3) | |
| img = np.transpose(img, (2, 0, 1)) | |
| return pil_img, torch.tensor(img[None]), padding | |
| def soft_blur_with_mask(image: Image.Image, mask: torch.tensor, padding: Tuple[int]) -> Image.Image: | |
| image = np.array(image) | |
| # Create a blurred copy of the original image. | |
| blurred_image = cv2.GaussianBlur(image, (221, 221), sigmaX=20, sigmaY=20) | |
| image_height, image_width = image.shape[:2] | |
| mask = cv2.resize(mask.astype(np.uint8), (image_width, image_height), interpolation=cv2.INTER_NEAREST) | |
| # Blurring the mask itself to get a softer mask with no firm edges | |
| mask = cv2.GaussianBlur(mask.astype(np.float32), (11, 11), 10, 10)[:, :, None] | |
| # Take the blurred image where the mask it positive, and the original image where the image is original | |
| image = (mask * blurred_image + (1.0 - mask) * image) | |
| pad_w, pad_h, _, _ = padding | |
| img_w, img_h, _ = image.shape | |
| image = image[(pad_h):(img_h-pad_h), (pad_w):(img_w-pad_w), :] | |
| return Image.fromarray(image.astype(np.uint8)) | |
| def run(image, size): | |
| pil_image, torch_image, padding = preprocess_image(image, size=size) | |
| with torch.inference_mode(): | |
| mask = model(torch_image) | |
| mask = mask.argmax(dim=1).numpy().squeeze() | |
| return soft_blur_with_mask(pil_image, mask, padding) | |
| content_image_input = gr.inputs.Image(label="Content Image", type="pil") | |
| model_image_size = gr.inputs.Radio([256, 384, 512, 1024], type="value", default=512, label="Inference size") | |
| description="Privacy first! Upload an image of a groupf of people and blur their faces automatically." | |
| article=""" | |
| Demo built on top of a face segmentation model trained from scratch with IceVision on the | |
| <a href='https://github.com/microsoft/FaceSynthetics' target='_blank'>FaceSynthetics</a> dataset. | |
| """ | |
| examples = [["./images/girls.jpeg", 384], ["./images/kid.jpeg", 256], ["./images/family.jpeg", 512], ["./images/crowd1.jpeg", 1024], ["./images/crowd2.jpeg", 1024]] | |
| app_interface = gr.Interface(fn=run, | |
| inputs=[content_image_input, model_image_size], | |
| outputs="image", | |
| title="Blurry Faces", | |
| description=description, | |
| examples=examples, | |
| article=article) | |
| app_interface.launch() |