Francesco Pochetti commited on
Commit
767fc76
β€’
1 Parent(s): 572447c

moving to self trained face segmentation model

Browse files
.DS_Store ADDED
Binary file (6.15 kB). View file
app.py CHANGED
@@ -1,67 +1,67 @@
1
  import cv2
2
  import gradio as gr
3
- from PIL import Image
 
4
  import numpy as np
5
  import torch
6
- import kornia as K
7
- from kornia.contrib import FaceDetector, FaceDetectorResult
8
 
9
- device = torch.device('cpu')
10
- face_detection = FaceDetector().to(device)
11
-
12
- def scale_image(img: np.ndarray, size: int) -> np.ndarray:
13
- h, w = img.shape[:2]
14
- scale = 1. * size / w
15
- return cv2.resize(img, (int(w * scale), int(h * scale)))
16
-
17
-
18
- def apply_blur_face(img: torch.Tensor, img_vis: np.ndarray, det: FaceDetectorResult):
19
- # crop the face
20
- x1, y1 = det.xmin.int(), det.ymin.int()
21
- x2, y2 = det.xmax.int(), det.ymax.int()
22
- roi = img[..., y1:y2, x1:x2]
23
- if roi.shape[-1]==0 or roi.shape[-2]==0:
24
- return
25
-
26
- # apply blurring and put back to the visualisation image
27
- roi = K.filters.gaussian_blur2d(roi, (21, 21), (100., 100.))
28
- roi = K.color.rgb_to_bgr(roi)
29
- img_vis[y1:y2, x1:x2] = K.tensor_to_image(roi)
30
-
31
-
32
- def run(image):
33
- image.thumbnail((1280, 1280))
34
- img_raw = np.array(image)
35
-
36
- # preprocess
37
- img = K.image_to_tensor(img_raw, keepdim=False).to(device)
38
- img = K.color.bgr_to_rgb(img.float())
39
-
40
- with torch.no_grad():
41
- dets = face_detection(img)
42
- dets = [FaceDetectorResult(o) for o in dets]
43
-
44
- img_vis = img_raw.copy()
45
-
46
- for b in dets:
47
- if b.score < 0.5:
48
- continue
49
-
50
- apply_blur_face(img, img_vis, b)
51
-
52
- return Image.fromarray(img_vis)
53
 
54
  content_image_input = gr.inputs.Image(label="Content Image", type="pil")
 
55
 
56
  description="Privacy first! Upload an image of a groupf of people and blur their faces automatically."
57
  article="""
58
- Demo built on top of kornia and opencv, based on
59
- <a href='https://github.com/kornia/kornia/blob/master/examples/face_detection/main.py' target='_blank'>this</a> example.
60
  """
61
- examples = [["./images/family.jpeg"], ["./images/crowd.jpeg"], ["./images/crowd1.jpeg"]]
62
 
63
  app_interface = gr.Interface(fn=run,
64
- inputs=[content_image_input],
65
  outputs="image",
66
  title="Blurry Faces",
67
  description=description,
1
  import cv2
2
  import gradio as gr
3
+ from typing import Union, Tuple
4
+ from PIL import Image, ImageOps
5
  import numpy as np
6
  import torch
 
 
7
 
8
+ model = torch.jit.load('./model/model.pt').eval()
9
+
10
+ def resize_with_padding(img: Image.Image, expected_size: Tuple[int, int]) -> Image.Image:
11
+ img.thumbnail((expected_size[0], expected_size[1]))
12
+ delta_width = expected_size[0] - img.size[0]
13
+ delta_height = expected_size[1] - img.size[1]
14
+ pad_width = delta_width // 2
15
+ pad_height = delta_height // 2
16
+ padding = (pad_width, pad_height, delta_width - pad_width, delta_height - pad_height)
17
+ return ImageOps.expand(img, padding), padding
18
+
19
+ def preprocess_image(img: Image.Image, size: int = 512) -> Tuple[Image.Image, torch.tensor, Tuple[int]]:
20
+ pil_img, padding = resize_with_padding(img, (size, size))
21
+
22
+ img = (np.array(pil_img).astype(np.float32) / 255) - np.array([0.485, 0.456, 0.406], dtype=np.float32).reshape(1, 1, 3)
23
+ img = img / np.array([0.229, 0.224, 0.225], dtype=np.float32).reshape(1, 1, 3)
24
+ img = np.transpose(img, (2, 0, 1))
25
+
26
+ return pil_img, torch.tensor(img[None]), padding
27
+
28
+ def soft_blur_with_mask(image: Image.Image, mask: torch.tensor, padding: Tuple[int]) -> Image.Image:
29
+ image = np.array(image)
30
+ # Create a blurred copy of the original image.
31
+ blurred_image = cv2.GaussianBlur(image, (221, 221), sigmaX=20, sigmaY=20)
32
+ image_height, image_width = image.shape[:2]
33
+ mask = cv2.resize(mask.astype(np.uint8), (image_width, image_height), interpolation=cv2.INTER_NEAREST)
34
+ # Blurring the mask itself to get a softer mask with no firm edges
35
+ mask = cv2.GaussianBlur(mask.astype(np.float32), (11, 11), 10, 10)[:, :, None]
36
+
37
+ # Take the blurred image where the mask it positive, and the original image where the image is original
38
+ image = (mask * blurred_image + (1.0 - mask) * image)
39
+ pad_w, pad_h, _, _ = padding
40
+ img_w, img_h, _ = image.shape
41
+ image = image[(pad_h):(img_h-pad_h), (pad_w):(img_w-pad_w), :]
42
+ return Image.fromarray(image.astype(np.uint8))
43
+
44
+ def run(image, size):
45
+ pil_image, torch_image, padding = preprocess_image(image, size=size)
46
+
47
+ with torch.inference_mode():
48
+ mask = model(torch_image)
49
+ mask = mask.argmax(dim=1).numpy().squeeze()
50
+
51
+ return soft_blur_with_mask(pil_image, mask, padding)
52
 
53
  content_image_input = gr.inputs.Image(label="Content Image", type="pil")
54
+ model_image_size = gr.inputs.Radio([256, 384, 512, 1024], type="value", default=512, label="Inference size")
55
 
56
  description="Privacy first! Upload an image of a groupf of people and blur their faces automatically."
57
  article="""
58
+ Demo built on top of a face segmentation model trained from scratch with IceVision on the
59
+ <a href='https://github.com/microsoft/FaceSynthetics' target='_blank'>FaceSynthetics</a> dataset.
60
  """
61
+ examples = [["./images/girls.jpeg", 384], ["./images/kid.jpeg", 256], ["./images/family.jpeg", 512], ["./images/crowd1.jpeg", 1024], ["./images/crowd2.jpeg", 1024]]
62
 
63
  app_interface = gr.Interface(fn=run,
64
+ inputs=[content_image_input, model_image_size],
65
  outputs="image",
66
  title="Blurry Faces",
67
  description=description,
images/{crowd.jpeg β†’ crowd2.jpeg} RENAMED
File without changes
images/girls.jpeg ADDED
images/kid.jpeg ADDED
model/model.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1e310f25944aaf0a35a334798e72aca4494dd19f3785225042017743ecd37757
3
+ size 165321408