tomas-gajarsky commited on
Commit
f7b06e7
1 Parent(s): e674bd0
Files changed (8) hide show
  1. README.md +26 -5
  2. app.py +36 -0
  3. config.merged.yml +363 -0
  4. requirements.txt +1 -0
  5. test.jpg +0 -0
  6. test2.jpg +0 -0
  7. test3.jpg +0 -0
  8. test4.jpg +0 -0
README.md CHANGED
@@ -1,8 +1,8 @@
1
  ---
2
- title: Facetorch App
3
- emoji: 👁
4
- colorFrom: blue
5
- colorTo: pink
6
  sdk: gradio
7
  sdk_version: 3.8.2
8
  app_file: app.py
@@ -10,4 +10,25 @@ pinned: false
10
  license: apache-2.0
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: facetorch-app
3
+ emoji: 🧑‍🦲
4
+ colorFrom: red
5
+ colorTo: black
6
  sdk: gradio
7
  sdk_version: 3.8.2
8
  app_file: app.py
 
10
  license: apache-2.0
11
  ---
12
 
13
+
14
+ # ![](https://raw.githubusercontent.com/tomas-gajarsky/facetorch/main/data/facetorch-logo-42.png "facetorch logo") facetorch
15
+ ![build](https://github.com/tomas-gajarsky/facetorch/actions/workflows/build.yml/badge.svg?branch=main)
16
+ ![lint](https://github.com/tomas-gajarsky/facetorch/actions/workflows/lint.yml/badge.svg?branch=main)
17
+ [![PyPI](https://img.shields.io/pypi/v/facetorch)](https://pypi.org/project/facetorch/)
18
+ [![Conda (channel only)](https://img.shields.io/conda/vn/conda-forge/facetorch)](https://anaconda.org/conda-forge/facetorch)
19
+ [![PyPI - License](https://img.shields.io/pypi/l/facetorch)](https://raw.githubusercontent.com/tomas-gajarsky/facetorch/main/LICENSE)
20
+ <a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
21
+
22
+
23
+ [Documentation](https://tomas-gajarsky.github.io/facetorch/facetorch/index.html), [Docker Hub](https://hub.docker.com/repository/docker/tomasgajarsky/facetorch) [(GPU)](https://hub.docker.com/repository/docker/tomasgajarsky/facetorch-gpu)
24
+
25
+ Facetorch is a Python library that can detect faces and analyze facial features using deep neural networks. The goal is to gather open sourced face analysis models from the community, optimize them for performance using TorchScript and combine them to create a face analysis tool that one can:
26
+
27
+ 1. configure using [Hydra](https://hydra.cc/docs/intro/) (OmegaConf)
28
+ 2. reproduce with [conda-lock](https://github.com/conda-incubator/conda-lock) and [Docker](https://docs.docker.com/get-docker/)
29
+ 3. accelerate on CPU and GPU with [TorchScript](https://pytorch.org/docs/stable/jit.html)
30
+ 4. extend by uploading a model file to Google Drive and adding a config yaml file to the repository
31
+
32
+ Please, use the library responsibly with caution and follow the
33
+ [ethics guidelines for Trustworthy AI from European Commission](https://ec.europa.eu/futurium/en/ai-alliance-consultation.1.html).
34
+ The models are not perfect and may be biased.
app.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torchvision
3
+ from facetorch import FaceAnalyzer
4
+ from OmegaConf import OmegaConf
5
+
6
+
7
+ cfg = OmegaConf.load("config.merged.yaml")
8
+ analyzer = FaceAnalyzer(cfg.analyzer)
9
+
10
+
11
+ def inference(path_image):
12
+ response = analyzer.run(
13
+ path_image=path_image,
14
+ batch_size=cfg.batch_size,
15
+ fix_img_size=cfg.fix_img_size,
16
+ return_img_data=cfg.return_img_data,
17
+ include_tensors=cfg.include_tensors,
18
+ path_output=cfg.path_output,
19
+ )
20
+ pil_image = torchvision.transforms.functional.to_pil_image(response.img)
21
+ return pil_image
22
+
23
+
24
+ title = "facetorch"
25
+ description = "Demo for facetorch, a Python library that can detect faces and analyze facial features using deep neural networks. The goal is to gather open sourced face analysis models from the community and optimize them for performance using TorchScrip. Try selecting one of the example images or upload your own."
26
+ article = "<p style='text-align: center'><a href='https://github.com/tomas-gajarsky/facetorch' target='_blank'>Github Repo</a></p>"
27
+
28
+ gr.Interface(
29
+ inference,
30
+ [gr.inputs.Image(label="Input")],
31
+ gr.outputs.Image(type="pil", label="Output"),
32
+ title=title,
33
+ description=description,
34
+ article=article,
35
+ examples=[["./data/input/test.jpg"], ["./data/input/test2.jpg"]],
36
+ ).launch(debug=True)
config.merged.yml ADDED
@@ -0,0 +1,363 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ analyzer:
2
+ device: cpu
3
+ optimize_transforms: true
4
+ reader:
5
+ _target_: facetorch.analyzer.reader.ImageReader
6
+ device:
7
+ _target_: torch.device
8
+ type: ${analyzer.device}
9
+ optimize_transform: ${analyzer.optimize_transforms}
10
+ transform:
11
+ _target_: torchvision.transforms.Compose
12
+ transforms:
13
+ - _target_: facetorch.transforms.SquarePad
14
+ - _target_: torchvision.transforms.Resize
15
+ size:
16
+ - 1080
17
+ detector:
18
+ _target_: facetorch.analyzer.detector.FaceDetector
19
+ downloader:
20
+ _target_: facetorch.downloader.DownloaderGDrive
21
+ file_id: 154x2VjmTQVqmowB0yZw4Uck7uQs2vVBs
22
+ path_local: /opt/facetorch/models/torchscript/detector/1/model.pt
23
+ device:
24
+ _target_: torch.device
25
+ type: ${analyzer.device}
26
+ reverse_colors: true
27
+ preprocessor:
28
+ _target_: facetorch.analyzer.detector.pre.DetectorPreProcessor
29
+ transform:
30
+ _target_: torchvision.transforms.Compose
31
+ transforms:
32
+ - _target_: torchvision.transforms.Normalize
33
+ mean:
34
+ - 104.0
35
+ - 117.0
36
+ - 123.0
37
+ std:
38
+ - 1.0
39
+ - 1.0
40
+ - 1.0
41
+ device:
42
+ _target_: torch.device
43
+ type: ${analyzer.device}
44
+ optimize_transform: ${analyzer.optimize_transforms}
45
+ reverse_colors: ${analyzer.detector.reverse_colors}
46
+ postprocessor:
47
+ _target_: facetorch.analyzer.detector.post.PostRetFace
48
+ transform: None
49
+ device:
50
+ _target_: torch.device
51
+ type: ${analyzer.device}
52
+ optimize_transform: ${analyzer.optimize_transforms}
53
+ confidence_threshold: 0.02
54
+ top_k: 5000
55
+ nms_threshold: 0.4
56
+ keep_top_k: 750
57
+ score_threshold: 0.6
58
+ prior_box:
59
+ _target_: facetorch.analyzer.detector.post.PriorBox
60
+ min_sizes:
61
+ - - 16
62
+ - 32
63
+ - - 64
64
+ - 128
65
+ - - 256
66
+ - 512
67
+ steps:
68
+ - 8
69
+ - 16
70
+ - 32
71
+ clip: false
72
+ variance:
73
+ - 0.1
74
+ - 0.2
75
+ reverse_colors: ${analyzer.detector.reverse_colors}
76
+ expand_pixels: 4
77
+ unifier:
78
+ _target_: facetorch.analyzer.unifier.FaceUnifier
79
+ transform:
80
+ _target_: torchvision.transforms.Compose
81
+ transforms:
82
+ - _target_: torchvision.transforms.Normalize
83
+ mean:
84
+ - -123.0
85
+ - -117.0
86
+ - -104.0
87
+ std:
88
+ - 255.0
89
+ - 255.0
90
+ - 255.0
91
+ - _target_: torchvision.transforms.Resize
92
+ size:
93
+ - 380
94
+ - 380
95
+ device:
96
+ _target_: torch.device
97
+ type: ${analyzer.device}
98
+ optimize_transform: ${analyzer.optimize_transforms}
99
+ predictor:
100
+ embed:
101
+ _target_: facetorch.analyzer.predictor.FacePredictor
102
+ downloader:
103
+ _target_: facetorch.downloader.DownloaderGDrive
104
+ file_id: 19h3kqar1wlELAmM5hDyj9tlrUh8yjrCl
105
+ path_local: /opt/facetorch/models/torchscript/predictor/embed/1/model.pt
106
+ device:
107
+ _target_: torch.device
108
+ type: ${analyzer.device}
109
+ preprocessor:
110
+ _target_: facetorch.analyzer.predictor.pre.PredictorPreProcessor
111
+ transform:
112
+ _target_: torchvision.transforms.Compose
113
+ transforms:
114
+ - _target_: torchvision.transforms.Resize
115
+ size:
116
+ - 244
117
+ - 244
118
+ - _target_: torchvision.transforms.Normalize
119
+ mean:
120
+ - 0.485
121
+ - 0.456
122
+ - 0.406
123
+ std:
124
+ - 0.228
125
+ - 0.224
126
+ - 0.225
127
+ device:
128
+ _target_: torch.device
129
+ type: ${analyzer.predictor.fer.device.type}
130
+ optimize_transform: ${analyzer.optimize_transforms}
131
+ reverse_colors: false
132
+ postprocessor:
133
+ _target_: facetorch.analyzer.predictor.post.PostEmbedder
134
+ transform: None
135
+ device:
136
+ _target_: torch.device
137
+ type: ${analyzer.predictor.fer.device.type}
138
+ optimize_transform: ${analyzer.optimize_transforms}
139
+ labels:
140
+ - abstract
141
+ verify:
142
+ _target_: facetorch.analyzer.predictor.FacePredictor
143
+ downloader:
144
+ _target_: facetorch.downloader.DownloaderGDrive
145
+ file_id: 1H-aPtFd9C5D7y1vzoWsObKAxeIBE9QPd
146
+ path_local: /opt/facetorch/models/torchscript/predictor/verify/1/model.pt
147
+ device:
148
+ _target_: torch.device
149
+ type: ${analyzer.device}
150
+ preprocessor:
151
+ _target_: facetorch.analyzer.predictor.pre.PredictorPreProcessor
152
+ transform:
153
+ _target_: torchvision.transforms.Compose
154
+ transforms:
155
+ - _target_: torchvision.transforms.Resize
156
+ size:
157
+ - 112
158
+ - 112
159
+ - _target_: torchvision.transforms.Normalize
160
+ mean:
161
+ - 0.485
162
+ - 0.456
163
+ - 0.406
164
+ std:
165
+ - 0.229
166
+ - 0.224
167
+ - 0.225
168
+ device:
169
+ _target_: torch.device
170
+ type: ${analyzer.predictor.fer.device.type}
171
+ optimize_transform: ${analyzer.optimize_transforms}
172
+ reverse_colors: false
173
+ postprocessor:
174
+ _target_: facetorch.analyzer.predictor.post.PostEmbedder
175
+ transform: None
176
+ device:
177
+ _target_: torch.device
178
+ type: ${analyzer.predictor.fer.device.type}
179
+ optimize_transform: ${analyzer.optimize_transforms}
180
+ labels:
181
+ - abstract
182
+ fer:
183
+ _target_: facetorch.analyzer.predictor.FacePredictor
184
+ downloader:
185
+ _target_: facetorch.downloader.DownloaderGDrive
186
+ file_id: 1xoB5VYOd0XLjb-rQqqHWCkQvma4NytEd
187
+ path_local: /opt/facetorch/models/torchscript/predictor/fer/2/model.pt
188
+ device:
189
+ _target_: torch.device
190
+ type: ${analyzer.device}
191
+ preprocessor:
192
+ _target_: facetorch.analyzer.predictor.pre.PredictorPreProcessor
193
+ transform:
194
+ _target_: torchvision.transforms.Compose
195
+ transforms:
196
+ - _target_: torchvision.transforms.Resize
197
+ size:
198
+ - 260
199
+ - 260
200
+ - _target_: torchvision.transforms.Normalize
201
+ mean:
202
+ - 0.485
203
+ - 0.456
204
+ - 0.406
205
+ std:
206
+ - 0.229
207
+ - 0.224
208
+ - 0.225
209
+ device:
210
+ _target_: torch.device
211
+ type: ${analyzer.predictor.fer.device.type}
212
+ optimize_transform: ${analyzer.optimize_transforms}
213
+ reverse_colors: false
214
+ postprocessor:
215
+ _target_: facetorch.analyzer.predictor.post.PostArgMax
216
+ transform: None
217
+ device:
218
+ _target_: torch.device
219
+ type: ${analyzer.predictor.fer.device.type}
220
+ optimize_transform: ${analyzer.optimize_transforms}
221
+ dim: 1
222
+ labels:
223
+ - Anger
224
+ - Contempt
225
+ - Disgust
226
+ - Fear
227
+ - Happiness
228
+ - Neutral
229
+ - Sadness
230
+ - Surprise
231
+ deepfake:
232
+ _target_: facetorch.analyzer.predictor.FacePredictor
233
+ downloader:
234
+ _target_: facetorch.downloader.DownloaderGDrive
235
+ file_id: 1GjDTwQpvrkCjXOdiBy1oMkzm7nt-bXFg
236
+ path_local: /opt/facetorch/models/torchscript/predictor/deepfake/1/model.pt
237
+ device:
238
+ _target_: torch.device
239
+ type: ${analyzer.device}
240
+ preprocessor:
241
+ _target_: facetorch.analyzer.predictor.pre.PredictorPreProcessor
242
+ transform:
243
+ _target_: torchvision.transforms.Compose
244
+ transforms:
245
+ - _target_: torchvision.transforms.Resize
246
+ size:
247
+ - 380
248
+ - 380
249
+ - _target_: torchvision.transforms.Normalize
250
+ mean:
251
+ - 0.485
252
+ - 0.456
253
+ - 0.406
254
+ std:
255
+ - 0.229
256
+ - 0.224
257
+ - 0.225
258
+ device:
259
+ _target_: torch.device
260
+ type: ${analyzer.device}
261
+ optimize_transform: ${analyzer.optimize_transforms}
262
+ reverse_colors: false
263
+ postprocessor:
264
+ _target_: facetorch.analyzer.predictor.post.PostSigmoidBinary
265
+ transform: None
266
+ device:
267
+ _target_: torch.device
268
+ type: ${analyzer.device}
269
+ optimize_transform: ${analyzer.optimize_transforms}
270
+ labels:
271
+ - Real
272
+ - Fake
273
+ threshold: 0.7
274
+ align:
275
+ _target_: facetorch.analyzer.predictor.FacePredictor
276
+ downloader:
277
+ _target_: facetorch.downloader.DownloaderGDrive
278
+ file_id: 16gNFQdEH2nWvW3zTbdIAniKIbPAp6qBA
279
+ path_local: /opt/facetorch/models/torchscript/predictor/align/1/model.pt
280
+ device:
281
+ _target_: torch.device
282
+ type: ${analyzer.device}
283
+ preprocessor:
284
+ _target_: facetorch.analyzer.predictor.pre.PredictorPreProcessor
285
+ transform:
286
+ _target_: torchvision.transforms.Compose
287
+ transforms:
288
+ - _target_: torchvision.transforms.Resize
289
+ size:
290
+ - 120
291
+ - 120
292
+ device:
293
+ _target_: torch.device
294
+ type: ${analyzer.predictor.align.device.type}
295
+ optimize_transform: ${analyzer.optimize_transforms}
296
+ reverse_colors: false
297
+ postprocessor:
298
+ _target_: facetorch.analyzer.predictor.post.PostEmbedder
299
+ transform: None
300
+ device:
301
+ _target_: torch.device
302
+ type: ${analyzer.predictor.align.device.type}
303
+ optimize_transform: ${analyzer.optimize_transforms}
304
+ labels:
305
+ - abstract
306
+ utilizer:
307
+ align:
308
+ _target_: facetorch.analyzer.utilizer.align.Lmk3DMeshPose
309
+ transform: None
310
+ device:
311
+ _target_: torch.device
312
+ type: ${analyzer.device}
313
+ optimize_transform: false
314
+ downloader_meta:
315
+ _target_: facetorch.downloader.DownloaderGDrive
316
+ file_id: 11tdAcFuSXqCCf58g52WT1Rpa8KuQwe2o
317
+ path_local: /opt/facetorch/data/3dmm/meta.pt
318
+ image_size: 120
319
+ draw_boxes:
320
+ _target_: facetorch.analyzer.utilizer.draw.BoxDrawer
321
+ transform: None
322
+ device:
323
+ _target_: torch.device
324
+ type: ${analyzer.device}
325
+ optimize_transform: false
326
+ color: green
327
+ line_width: 3
328
+ draw_landmarks:
329
+ _target_: facetorch.analyzer.utilizer.draw.LandmarkDrawer
330
+ transform: None
331
+ device:
332
+ _target_: torch.device
333
+ type: ${analyzer.device}
334
+ optimize_transform: false
335
+ marker: o
336
+ markersize: 0.9
337
+ opacity: 0.8
338
+ line_width: 0.8
339
+ color: g
340
+ markeredgecolor: green
341
+ save:
342
+ _target_: facetorch.analyzer.utilizer.save.ImageSaver
343
+ transform: None
344
+ device:
345
+ _target_: torch.device
346
+ type: ${analyzer.device}
347
+ optimize_transform: false
348
+ logger:
349
+ _target_: facetorch.logger.LoggerJsonFile
350
+ name: facetorch
351
+ level: 20
352
+ path_file: /opt/logs/facetorch/main.log
353
+ json_format: '%(asctime)s %(levelname)s %(message)s'
354
+ main:
355
+ sleep: 3
356
+ debug: true
357
+ path_image: /opt/facetorch/data/input/test.jpg
358
+ batch_size: 8
359
+ fix_img_size: true
360
+ return_img_data: false
361
+ include_tensors: false
362
+ path_output: /opt/facetorch/data/output/test.png
363
+ path_image_2: /opt/facetorch/data/input/test3.jpg
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ facetorch
test.jpg ADDED
test2.jpg ADDED
test3.jpg ADDED
test4.jpg ADDED