leonelhs commited on
Commit
84ce4ca
1 Parent(s): 20d4099
Files changed (5) hide show
  1. .gitignore +2 -0
  2. README.md +1 -1
  3. app.py +79 -0
  4. requirements.txt +5 -0
  5. utils.py +50 -0
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ .idea/
2
+ __pycache__/
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: Faceparser
3
  emoji: 👁
4
  colorFrom: blue
5
  colorTo: green
 
1
  ---
2
+ title: Face Parser
3
  emoji: 👁
4
  colorFrom: blue
5
  colorTo: green
app.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import gradio as gr
4
+ import numpy as np
5
+ import torch
6
+ from PIL import Image
7
+ from bisnet import BiSeNet
8
+ from huggingface_hub import snapshot_download
9
+
10
+ from utils import vis_parsing_maps, decode_segmentation_masks, image_to_tensor
11
+
12
+ os.system("pip freeze")
13
+
14
+ REPO_ID = "leonelhs/faceparser"
15
+ MODEL_NAME = "79999_iter.pth"
16
+
17
+ model = BiSeNet(n_classes=19)
18
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
19
+ snapshot_folder = snapshot_download(repo_id=REPO_ID)
20
+ model_path = os.path.join(snapshot_folder, MODEL_NAME)
21
+ model.load_state_dict(torch.load(model_path, map_location=device))
22
+ model.eval()
23
+
24
+
25
+ def makeOverlay(image, mask):
26
+ prediction_mask = np.asarray(mask)
27
+ image = image.resize((512, 512), Image.BILINEAR)
28
+ dark_map, overlay = vis_parsing_maps(image, prediction_mask)
29
+ colormap = decode_segmentation_masks(dark_map)
30
+ return overlay, colormap
31
+
32
+
33
+ def predict(image):
34
+ with torch.no_grad():
35
+ image = image.resize((512, 512), Image.BILINEAR)
36
+ input_tensor = image_to_tensor(image)
37
+ input_tensor = torch.unsqueeze(input_tensor, 0)
38
+ if torch.cuda.is_available():
39
+ input_tensor = input_tensor.cuda()
40
+ output = model(input_tensor)[0]
41
+ return output.squeeze(0).cpu().numpy().argmax(0)
42
+
43
+
44
+ def inference(image):
45
+ mask = predict(image)
46
+ overlay, colormap = makeOverlay(image, mask)
47
+ return overlay
48
+
49
+
50
+ title = "Face Parser"
51
+ description = r"""
52
+ ## Image face parser for research
53
+
54
+ This is an implementation of <a href='https://github.com/zllrunning/face-parsing.PyTorch' target='_blank'>face-parsing.PyTorch</a>.
55
+ It has no any particular purpose than start research on AI models.
56
+
57
+ """
58
+
59
+ article = r"""
60
+ Questions, doubts, comments, please email 📧 `leonelhs@gmail.com`
61
+
62
+ This demo is running on a CPU, if you like this project please make us a donation to run on a GPU or just give us a <a href='https://github.com/leonelhs/zeroscratches/' target='_blank'>Github ⭐</a>
63
+
64
+ <a href="https://www.buymeacoffee.com/leonelhs"><img src="https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=&slug=leonelhs&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff" /></a>
65
+
66
+ <center><img src='https://visitor-badge.glitch.me/badge?page_id=zeroscratches.visitor-badge' alt='visitor badge'></center>
67
+ """
68
+
69
+ demo = gr.Interface(
70
+ inference, [
71
+ gr.Image(type="pil", label="Input"),
72
+ ], [
73
+ gr.Image(type="numpy", label="Image face parsed")
74
+ ],
75
+ title=title,
76
+ description=description,
77
+ article=article)
78
+
79
+ demo.queue().launch()
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ torch>=2.0.1
2
+ torchvision~=0.15.2
3
+ pillow~=9.5.0
4
+ bisnet~=1.0.1
5
+ opencv-python
utils.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ import torchvision.transforms as transforms
4
+
5
+ # Colors for all 20 parts
6
+ part_colors = [[255, 0, 0], [255, 85, 0], [255, 170, 0], [255, 0, 85], [255, 0, 170],
7
+ [0, 255, 0], [85, 255, 0], [170, 255, 0], [0, 255, 85], [0, 255, 170],
8
+ [0, 0, 255], [85, 0, 255], [170, 0, 255], [0, 85, 255], [0, 170, 255],
9
+ [255, 255, 0], [255, 255, 85], [255, 255, 170], [255, 0, 255], [255, 85, 255],
10
+ [255, 170, 255], [0, 255, 255], [85, 255, 255], [170, 255, 255]]
11
+
12
+ colormap = np.array(part_colors, dtype=np.uint8)
13
+
14
+
15
+ def image_to_tensor(image):
16
+ return transforms.Compose([
17
+ transforms.ToTensor(),
18
+ transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)),
19
+ ])(image)
20
+
21
+
22
+ def decode_segmentation_masks(mask, n_classes=20):
23
+ red = np.zeros_like(mask).astype(np.uint8)
24
+ green = np.zeros_like(mask).astype(np.uint8)
25
+ blue = np.zeros_like(mask).astype(np.uint8)
26
+ for chanel in range(0, n_classes):
27
+ idx = mask == chanel
28
+ red[idx] = colormap[chanel, 0]
29
+ green[idx] = colormap[chanel, 1]
30
+ blue[idx] = colormap[chanel, 2]
31
+ return np.stack([red, green, blue], axis=2)
32
+
33
+
34
+ def vis_parsing_maps(image: np.array, parsing_anno, stride=1):
35
+ image = np.array(image)
36
+ vis_im = image.copy().astype(np.uint8)
37
+ vis_parsing_anno = parsing_anno.copy().astype(np.uint8)
38
+ vis_parsing_anno = cv2.resize(vis_parsing_anno, None, fx=stride, fy=stride, interpolation=cv2.INTER_NEAREST)
39
+ vis_parsing_anno_color = np.zeros((vis_parsing_anno.shape[0], vis_parsing_anno.shape[1], 3)) + 255
40
+
41
+ num_of_class = np.max(vis_parsing_anno)
42
+
43
+ for pi in range(1, num_of_class + 1):
44
+ index = np.where(vis_parsing_anno == pi)
45
+ vis_parsing_anno_color[index[0], index[1], :] = part_colors[pi]
46
+
47
+ vis_parsing_anno_color = vis_parsing_anno_color.astype(np.uint8)
48
+ vis_im = cv2.addWeighted(cv2.cvtColor(vis_im, cv2.COLOR_RGB2BGR), 0.4, vis_parsing_anno_color, 0.6, 0)
49
+
50
+ return vis_parsing_anno, vis_im