Spaces:
Runtime error
Runtime error
vgvm
commited on
Commit
•
5f3e3d6
1
Parent(s):
fbcab86
add zoedepth, gradio obj loader is struggling locally, but blender is fine
Browse files- app.py +156 -139
- examples/character.png +0 -0
- quads.py +90 -0
- utils.py +88 -0
app.py
CHANGED
@@ -1,168 +1,134 @@
|
|
|
|
1 |
import gradio as gr
|
2 |
|
3 |
import cv2
|
|
|
|
|
4 |
import mediapipe as mp
|
5 |
-
mp_drawing = mp.solutions.drawing_utils
|
6 |
-
mp_drawing_styles = mp.solutions.drawing_styles
|
7 |
-
mp_face_mesh = mp.solutions.face_mesh
|
8 |
-
|
9 |
import numpy as np
|
10 |
-
|
11 |
-
from typing import List, Mapping, Optional, Tuple, Union
|
12 |
-
|
13 |
import pygltflib
|
|
|
14 |
import struct
|
15 |
import tempfile
|
|
|
16 |
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
[139, 216, 59, 173] , [276, 282, 6, 5] , [ 25, 145, 164, 111] , [292, 307, 308, 376] , [143, 127, 48, 101] ,
|
24 |
-
[419, 422, 429, 263] , [147, 44, 107, 92] , [ 17, 86, 85, 18] , [ 78, 77, 62, 147] , [127, 210, 199, 218] ,
|
25 |
-
[397, 378, 401, 370] , [166, 40, 38, 168] , [245, 234, 129, 246] , [ 31, 248, 247, 162] , [ 34, 247, 248, 131] ,
|
26 |
-
[175, 218, 199, 237] , [418, 352, 413, 466] , [125, 114, 226, 47] , [225, 224, 53, 54] , [ 99, 65, 103, 130] ,
|
27 |
-
[193, 215, 208, 188] , [219, 80, 240, 238] , [134, 156, 113, 244] , [345, 361, 364, 441] , [141, 171, 150, 177] ,
|
28 |
-
[400, 413, 352, 420] , [119, 230, 229, 118] , [282, 276, 441, 364] , [ 71, 64, 69, 72] , [315, 314, 407, 406] ,
|
29 |
-
[222, 190, 194, 56] , [114, 248, 31, 226] , [106, 53, 66, 67] , [236, 60, 167, 220] , [108, 56, 9, 10] ,
|
30 |
-
[ 67, 66, 56, 108] , [ 69, 64, 106, 105] , [120, 119, 51, 102] , [242, 126, 45, 238] , [ 6, 196, 4, 52] ,
|
31 |
-
[143, 130, 210, 127] , [ 34, 131, 26, 8] , [323, 271, 410, 411] , [ 33, 195, 205, 212] , [ 37, 102, 51, 206] ,
|
32 |
-
[195, 202, 84, 183] , [238, 240, 239, 242] , [ 26, 111, 164, 8] , [225, 54, 47, 226] , [154, 146, 24, 23] ,
|
33 |
-
[211, 203, 213, 215] , [246, 194, 190, 245] , [425, 336, 407, 419] , [318, 317, 404, 403] , [ 33, 212, 171, 141] ,
|
34 |
-
[ 12, 73, 39, 13] , [208, 217, 207, 206] , [238, 221, 116, 219] , [ 46, 221, 238, 45] , [184, 43, 75, 185] ,
|
35 |
-
[209, 202, 195, 33] , [269, 272, 304, 303] , [214, 148, 178, 216] , [235, 94, 138, 228] , [ 67, 108, 109, 70] ,
|
36 |
-
[ 7, 352, 418, 169] , [193, 188, 148, 214] , [ 97, 63, 77, 78] , [125, 47, 71, 157] , [317, 16, 17, 316] ,
|
37 |
-
[180, 87, 88, 179] , [106, 64, 54, 53] , [119, 118, 124, 51] , [146, 145, 25, 24] , [325, 319, 320, 326] ,
|
38 |
-
[123, 189, 175, 197] , [293, 309, 325, 326] , [150, 171, 170, 151] , [178, 138, 94, 133] , [328, 295, 456, 461] ,
|
39 |
-
[361, 421, 457, 364] , [336, 274, 376, 322] , [396, 395, 431, 432] , [ 13, 39, 83, 14] , [278, 330, 350, 351] ,
|
40 |
-
[191, 57, 158, 174] , [117, 112, 36, 144] , [224, 223, 66, 53] , [140, 72, 22, 163] , [163, 128, 35, 140] ,
|
41 |
-
[366, 365, 395, 380] , [219, 116, 49, 220] , [430, 359, 372, 356] , [157, 144, 36, 125] , [377, 353, 281, 412] ,
|
42 |
-
[125, 36, 227, 114] , [355, 20, 95, 371] , [120, 231, 230, 119] , [249, 457, 400, 420] , [162, 161, 30, 31] ,
|
43 |
-
[ 46, 45, 2, 5] , [141, 172, 209, 33] , [394, 392, 328, 327] , [ 32, 26, 131, 227] , [300, 298, 339, 338] ,
|
44 |
-
[395, 396, 379, 380] , [102, 37, 143, 101] , [217, 213, 58, 187] , [327, 3, 165, 394] , [242, 239, 21, 243] ,
|
45 |
-
[186, 41, 93, 187] , [269, 303, 12, 13] , [192, 81, 43, 184] , [140, 35, 144, 157] , [223, 222, 56, 66] ,
|
46 |
-
[189, 115, 218, 175] , [323, 427, 424, 392] , [ 37, 204, 130, 143] , [280, 430, 421, 361] , [ 2, 275, 276, 5] ,
|
47 |
-
[134, 244, 191, 174] , [241, 76, 60, 236] , [108, 10, 152, 109] , [ 27, 155, 154, 23] , [211, 215, 136, 170] ,
|
48 |
-
[355, 275, 2, 20] , [ 90, 89, 96, 97] , [321, 320, 404, 405] , [316, 315, 406, 405] , [107, 44, 203, 205] ,
|
49 |
-
[201, 422, 314, 19] , [153, 176, 172, 149] , [376, 274, 288, 292] , [292, 288, 411, 410] , [130, 204, 166, 99] ,
|
50 |
-
[115, 48, 127, 218] , [327, 328, 461, 329] , [105, 106, 67, 70] , [236, 65, 99, 241] , [200, 201, 202, 209] ,
|
51 |
-
[332, 295, 328, 359] , [100, 61, 76, 241] , [243, 142, 126, 242] , [329, 463, 371, 327] , [220, 167, 80, 219] ,
|
52 |
-
[233, 27, 23, 232] , [190, 222, 57, 191] , [223, 29, 57, 222] , [244, 113, 234, 245] , [ 32, 229, 111, 26] ,
|
53 |
-
[226, 31, 30, 225] , [232, 23, 24, 231] , [225, 30, 28, 224] , [114, 227, 131, 248] , [ 32, 227, 36, 112] ,
|
54 |
-
[234, 113, 27, 233] , [230, 25, 111, 229] , [224, 28, 29, 223] , [ 95, 20, 126, 142] , [239, 240, 80, 21] ,
|
55 |
-
[243, 21, 61, 100] , [157, 71, 72, 140] , [ 76, 61, 167, 60] , [189, 123, 194, 246] , [231, 24, 25, 230] ,
|
56 |
-
[232, 231, 120, 121] , [121, 101, 48, 122] , [208, 206, 51, 188] , [332, 280, 279, 295] , [196, 249, 420, 198] ,
|
57 |
-
[199, 210, 50, 132] , [177, 149, 172, 141] , [117, 124, 118, 112] , [ 28, 160, 159, 29] , [245, 190, 191, 244] ,
|
58 |
-
[379, 396, 370, 401] , [268, 303, 304, 270] , [351, 453, 454, 358] , [ 75, 74, 40, 41] , [169, 418, 286, 9] ,
|
59 |
-
[283, 444, 445, 284] , [397, 176, 153, 378] , [110, 68, 70, 109] , [301, 277, 354, 384] , [186, 62, 77, 185] ,
|
60 |
-
[299, 294, 301, 302] , [ 50, 49, 116, 132] , [422, 201, 200, 429] , [304, 272, 273, 305] , [271, 323, 392, 270] ,
|
61 |
-
[296, 443, 444, 283] , [427, 437, 428, 426] , [336, 322, 406, 407] , [ 19, 314, 315, 18] , [387, 388, 260, 258] ,
|
62 |
-
[255, 374, 375, 254] , [314, 422, 419, 407] , [297, 335, 334, 300] , [313, 312, 272, 269] , [ 55, 22, 72, 69] ,
|
63 |
-
[221, 46, 52, 135] , [391, 374, 255, 340] , [315, 316, 17, 18] , [372, 267, 331, 330] , [423, 274, 336, 425] ,
|
64 |
-
[ 58, 44, 147, 62] , [ 91, 78, 147, 92] , [182, 85, 86, 181] , [423, 425, 432, 431] , [357, 265, 448, 455] ,
|
65 |
-
[268, 270, 392, 394] , [358, 454, 465, 466] , [264, 360, 468, 467] , [264, 250, 256, 360] , [421, 430, 356, 438] ,
|
66 |
-
[194, 123, 7, 169] , [449, 450, 348, 347] , [277, 284, 445, 446] , [241, 99, 98, 100] , [281, 331, 267, 426] ,
|
67 |
-
[307, 292, 410, 409] , [260, 388, 389, 261] , [364, 457, 249, 282] , [338, 339, 11, 152] , [438, 344, 413, 400] ,
|
68 |
-
[349, 451, 452, 350] , [345, 279, 280, 361] , [402, 377, 434, 436] , [367, 324, 455, 448] , [182, 92, 107, 183] ,
|
69 |
-
[418, 414, 442, 286] , [360, 256, 262, 447] , [284, 277, 301, 294] , [291, 251, 463, 329] , [344, 358, 466, 413] ,
|
70 |
-
[179, 89, 90, 180] , [266, 341, 346, 373] , [429, 397, 370, 263] , [296, 283, 335, 297] , [275, 355, 462, 458] ,
|
71 |
-
[ 4, 237, 135, 52] , [359, 424, 267, 372] , [386, 387, 258, 259] , [394, 165, 1, 268] , [207, 217, 187, 93] ,
|
72 |
-
[278, 356, 372, 330] , [ 44, 58, 213, 203] , [459, 460, 458, 462] , [381, 382, 257, 253] , [266, 447, 262, 341] ,
|
73 |
-
[399, 385, 287, 415] , [437, 433, 435, 428] , [447, 266, 354, 343] , [183, 107, 205, 195] , [ 43, 42, 74, 75] ,
|
74 |
-
[302, 301, 384, 369] , [425, 419, 263, 432] , [295, 279, 440, 456] , [ 49, 50, 103, 65] , [ 74, 42, 39, 73] ,
|
75 |
-
[433, 423, 431, 435] , [311, 273, 272, 312] , [353, 367, 448, 346] , [252, 302, 369, 390] , [209, 172, 176, 200] ,
|
76 |
-
[ 56, 194, 169, 9] , [377, 412, 417, 434] , [ 90, 97, 78, 91] , [330, 331, 349, 350] , [180, 90, 91, 181] ,
|
77 |
-
[281, 348, 349, 331] , [265, 373, 346, 448] , [324, 367, 402, 362] , [308, 326, 320, 321] , [ 16, 15, 88, 87] ,
|
78 |
-
[266, 373, 384, 354] , [353, 347, 348, 281] , [363, 399, 415, 464] , [318, 15, 16, 317] , [356, 278, 344, 438] ,
|
79 |
-
[ 96, 79, 63, 97] , [ 11, 110, 109, 152] , [398, 368, 365, 366] , [ 2, 45, 126, 20] , [313, 269, 13, 14] ,
|
80 |
-
[237, 199, 132, 135] , [187, 58, 62, 186] , [152, 10, 337, 338] , [ 42, 82, 83, 39] , [414, 418, 466, 465] ,
|
81 |
-
[467, 468, 261, 389] , [ 9, 286, 337, 10] , [446, 343, 354, 277] , [265, 357, 390, 369] , [436, 434, 417, 368] ,
|
82 |
-
[170, 136, 137, 151] , [458, 441, 276, 275] , [212, 205, 203, 211] , [347, 353, 346, 341] , [284, 294, 335, 283] ,
|
83 |
-
[452, 453, 351, 350] , [ 95, 3, 327, 371] , [450, 451, 349, 348] , [197, 4, 196, 198] , [254, 375, 381, 253] ,
|
84 |
-
[345, 441, 458, 439] , [367, 353, 377, 402] , [449, 347, 341, 262] , [360, 447, 343, 468] , [136, 139, 173, 137] ,
|
85 |
-
[289, 436, 368, 398] , [281, 426, 428, 412] , [288, 433, 437, 411] , [ 99, 166, 168, 98] , [142, 243, 100, 98] ,
|
86 |
-
[175, 237, 4, 197] , [185, 75, 41, 186] , [307, 293, 326, 308] , [396, 432, 263, 370] , [286, 442, 443, 296] ,
|
87 |
-
[428, 435, 417, 412] , [411, 437, 427, 323] , [421, 438, 400, 457] , [165, 3, 98, 168] , [279, 345, 439, 440] ,
|
88 |
-
[391, 340, 256, 250] , [306, 291, 329, 461] , [373, 265, 369, 384] , [386, 259, 287, 385] , [435, 365, 368, 417] ,
|
89 |
-
[251, 459, 462, 463] , [320, 319, 403, 404] , [ 17, 16, 87, 86] , [322, 321, 405, 406] , [ 85, 84, 19, 18] ,
|
90 |
-
[433, 288, 274, 423] , [362, 402, 436, 289] , [185, 77, 63, 184] , [293, 307, 409, 408] , [392, 424, 359, 328] ,
|
91 |
-
[352, 7, 198, 420] , [228, 138, 124, 117] , [393, 290, 456, 440] , [176, 397, 429, 200] , [220, 49, 65, 236] ,
|
92 |
-
[424, 427, 426, 267] , [332, 359, 430, 280] , [365, 435, 431, 395] , [310, 251, 291, 393] , [355, 371, 463, 462] ,
|
93 |
-
[ 98, 3, 95, 142] , [255, 254, 451, 450] , [415, 414, 465, 464] , [254, 253, 452, 451] , [261, 468, 343, 446] ,
|
94 |
-
[260, 261, 446, 445] , [258, 260, 445, 444] , [454, 342, 464, 465] , [198, 7, 123, 197] , [259, 258, 444, 443] ,
|
95 |
-
[287, 442, 414, 415] , [340, 449, 262, 256] , [340, 255, 450, 449] , [257, 342, 454, 453] , [ 61, 21, 80, 167] ,
|
96 |
-
[310, 393, 440, 439] , [338, 337, 297, 300] , [310, 460, 459, 251] , [ 51, 124, 148, 188] , [253, 257, 453, 452] ,
|
97 |
-
[215, 193, 139, 136] , [351, 358, 344, 278] , [113, 156, 155, 27] , [ 6, 52, 46, 5] , [206, 207, 204, 37] ,
|
98 |
-
[249, 196, 6, 282] , [216, 178, 133, 59] , [286, 296, 297, 337] , [382, 383, 342, 257] , [287, 259, 443, 442] ,
|
99 |
-
[211, 170, 171, 212] , [306, 461, 456, 290] , [104, 105, 70, 68] , [271, 305, 409, 410] , [460, 310, 439, 458] ,
|
100 |
-
[214, 216, 139, 193] , [317, 316, 405, 404] , [181, 91, 92, 182] , [ 1, 165, 168, 38] , [363, 464, 342, 383] ,
|
101 |
-
[210, 130, 103, 50] , [305, 273, 408, 409] , [311, 416, 408, 273] , [309, 293, 408, 416] , [184, 63, 79, 192] ,
|
102 |
-
[115, 129, 122, 48] , [148, 124, 138, 178] , [181, 86, 87, 180] , [290, 393, 291, 306] , [252, 285, 299, 302] ,
|
103 |
-
[285, 333, 334, 299]
|
104 |
-
]
|
105 |
|
106 |
class face_image_to_face_mesh:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
def demo(self):
|
108 |
-
|
|
|
|
|
|
|
|
|
109 |
with demo:
|
110 |
-
gr.Markdown(
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
The initial workflow I was imagining was:
|
118 |
-
|
119 |
-
1. sculpt high poly mesh in blender
|
120 |
-
2. snapshot the face
|
121 |
-
3. generate the mesh using the mediapipe stuff
|
122 |
-
4. import the low poly mediapipe face
|
123 |
-
5. snap the mesh to the high poly model
|
124 |
-
6. model the rest of the low poly model
|
125 |
-
7. bake the normal / etc maps to the low poly face model
|
126 |
-
8. it's just that easy 😛
|
127 |
-
|
128 |
-
Ideally it would be a plugin...
|
129 |
""")
|
130 |
|
131 |
with gr.Row():
|
132 |
with gr.Column():
|
133 |
upload_image = gr.Image(label="Input image", type="numpy", source="upload")
|
|
|
134 |
gr.Examples( examples=[
|
135 |
'examples/blonde-00019-1421846474.png',
|
136 |
'examples/dude-00110-1227390728.png',
|
137 |
'examples/granny-00056-1867315302.png',
|
138 |
'examples/tuffie-00039-499759385.png',
|
|
|
139 |
], inputs=[upload_image] )
|
140 |
upload_image_btn = gr.Button(value="Detect faces")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
with gr.Group():
|
142 |
min_detection_confidence = gr.Slider(label="Min detection confidence", value=0.5, minimum=0.0, maximum=1.0, step=0.01)
|
143 |
gr.Textbox(show_label=False, value="Minimum confidence value ([0.0, 1.0]) from the face detection model for the detection to be considered successful.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
144 |
with gr.Column():
|
145 |
with gr.Group():
|
146 |
num_faces_detected = gr.Number(label="Number of faces detected", value=0)
|
147 |
-
|
148 |
-
|
|
|
149 |
|
150 |
-
outputs = [output_mesh, output_image, num_faces_detected]
|
151 |
upload_image_btn.click(
|
152 |
fn=self.detect,
|
153 |
-
inputs=[upload_image, min_detection_confidence],
|
154 |
-
outputs=
|
155 |
)
|
156 |
demo.launch()
|
157 |
|
158 |
|
159 |
-
def detect(self, image, min_detection_confidence):
|
160 |
width = image.shape[1]
|
161 |
height = image.shape[0]
|
162 |
ratio = width / height
|
|
|
|
|
|
|
|
|
163 |
|
164 |
mesh = "examples/jackiechan.obj"
|
165 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
drawing_spec = mp_drawing.DrawingSpec(thickness=1, circle_radius=1)
|
167 |
with mp_face_mesh.FaceMesh(
|
168 |
static_image_mode=True,
|
@@ -170,11 +136,11 @@ class face_image_to_face_mesh:
|
|
170 |
min_detection_confidence=min_detection_confidence) as face_mesh:
|
171 |
results = face_mesh.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
|
172 |
if not results.multi_face_landmarks:
|
173 |
-
return mesh, image, 0
|
174 |
|
175 |
annotated_image = image.copy()
|
176 |
for face_landmarks in results.multi_face_landmarks:
|
177 |
-
mesh = self.toObj(ratio=ratio, landmark_list=face_landmarks)
|
178 |
|
179 |
mp_drawing.draw_landmarks(
|
180 |
image=annotated_image,
|
@@ -191,31 +157,75 @@ class face_image_to_face_mesh:
|
|
191 |
connection_drawing_spec=mp_drawing_styles
|
192 |
.get_default_face_mesh_contours_style())
|
193 |
|
194 |
-
return mesh, annotated_image,1
|
195 |
|
196 |
-
def toObj( self, ratio: float, landmark_list: landmark_pb2.NormalizedLandmarkList):
|
197 |
print( f'you have such pretty hair' )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
lines = []
|
199 |
-
|
|
|
|
|
200 |
for point in points:
|
201 |
-
|
202 |
-
|
|
|
|
|
|
|
203 |
for quad in QUADS:
|
204 |
-
face = "f " + " ".join([str(vertex) for vertex in quad])
|
205 |
-
lines.append( face )
|
206 |
normal = self.totallyNormal( points[ quad[ 0 ] -1 ], points[ quad[ 1 ] -1 ], points[ quad[ 2 ] -1 ] )
|
207 |
lines.append( "vn " + " ".join([str(value) for value in normal]) )
|
208 |
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
213 |
out.close()
|
214 |
-
|
215 |
-
|
|
|
216 |
|
217 |
-
|
218 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
mins = [+np.inf] * 3
|
220 |
maxs = [-np.inf] * 3
|
221 |
for idx, landmark in enumerate(landmark_list.landmark):
|
@@ -224,6 +234,10 @@ class face_image_to_face_mesh:
|
|
224 |
(landmark.HasField('presence') and
|
225 |
landmark.presence < _PRESENCE_THRESHOLD)):
|
226 |
idk_what_to_do_for_this = True
|
|
|
|
|
|
|
|
|
227 |
point = [landmark.x * ratio, -landmark.y, -landmark.z];
|
228 |
for pidx,value in enumerate( point ):
|
229 |
mins[pidx] = min(mins[pidx],value)
|
@@ -237,7 +251,7 @@ class face_image_to_face_mesh:
|
|
237 |
print( f'mins: {mins}' )
|
238 |
print( f'mids: {mids}' )
|
239 |
print( f'maxs: {maxs}' )
|
240 |
-
return points
|
241 |
|
242 |
def totallyNormal(self, p0, p1, p2):
|
243 |
v1 = np.array(p1) - np.array(p0)
|
@@ -248,3 +262,6 @@ class face_image_to_face_mesh:
|
|
248 |
|
249 |
|
250 |
face_image_to_face_mesh().demo()
|
|
|
|
|
|
|
|
1 |
+
########################################################################################
|
2 |
import gradio as gr
|
3 |
|
4 |
import cv2
|
5 |
+
import matplotlib
|
6 |
+
import matplotlib.cm
|
7 |
import mediapipe as mp
|
|
|
|
|
|
|
|
|
8 |
import numpy as np
|
9 |
+
import os
|
|
|
|
|
10 |
import pygltflib
|
11 |
+
import shutil
|
12 |
import struct
|
13 |
import tempfile
|
14 |
+
import torch
|
15 |
|
16 |
+
from mediapipe.framework.formats import landmark_pb2
|
17 |
+
from mediapipe.python.solutions.drawing_utils import _normalized_to_pixel_coordinates
|
18 |
+
from PIL import Image
|
19 |
+
from quads import QUADS
|
20 |
+
from typing import List, Mapping, Optional, Tuple, Union
|
21 |
+
from utils import colorize
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
|
23 |
class face_image_to_face_mesh:
|
24 |
+
def __init__(self):
|
25 |
+
self.zoe_me = True
|
26 |
+
self.css = ("""
|
27 |
+
#img-display-container {
|
28 |
+
max-height: 50vh;
|
29 |
+
}
|
30 |
+
#img-display-input {
|
31 |
+
max-height: 40vh;
|
32 |
+
}
|
33 |
+
#img-display-output {
|
34 |
+
max-height: 55vh;
|
35 |
+
max-width: 55vh;
|
36 |
+
width:auto;
|
37 |
+
height:auto
|
38 |
+
}
|
39 |
+
""")
|
40 |
+
|
41 |
def demo(self):
|
42 |
+
if self.zoe_me:
|
43 |
+
DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'
|
44 |
+
self.zoe = torch.hub.load('isl-org/ZoeDepth', "ZoeD_N", pretrained=True).to(DEVICE).eval()
|
45 |
+
|
46 |
+
demo = gr.Blocks(css=self.css)
|
47 |
with demo:
|
48 |
+
gr.Markdown("""
|
49 |
+
# Face Image to Face Quad Mesh
|
50 |
+
|
51 |
+
Uses MediaPipe to detect a face in an image and convert it to a quad mesh.
|
52 |
+
Saves to OBJ since gltf does not support quad faces. The 3d viewer has Y pointing the opposite direction from Blender, so ya hafta spin it.
|
53 |
+
|
54 |
+
The face depth with Zoe can be a bit much and without it is a bit generic. In blender you can fix this just by snapping to the high poly model.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
""")
|
56 |
|
57 |
with gr.Row():
|
58 |
with gr.Column():
|
59 |
upload_image = gr.Image(label="Input image", type="numpy", source="upload")
|
60 |
+
|
61 |
gr.Examples( examples=[
|
62 |
'examples/blonde-00019-1421846474.png',
|
63 |
'examples/dude-00110-1227390728.png',
|
64 |
'examples/granny-00056-1867315302.png',
|
65 |
'examples/tuffie-00039-499759385.png',
|
66 |
+
'examples/character.png',
|
67 |
], inputs=[upload_image] )
|
68 |
upload_image_btn = gr.Button(value="Detect faces")
|
69 |
+
if self.zoe_me:
|
70 |
+
with gr.Group():
|
71 |
+
use_zoe = gr.Checkbox(label="Use ZoeDepth for Z", value=True)
|
72 |
+
gr.Textbox(show_label=False, value="Override the MediaPipe depth with ZoeDepth.")
|
73 |
+
zoe_scale = gr.Slider(label="Zoe Scale", value=1.44, minimum=0.0, maximum=3.3, step=0.1)
|
74 |
+
gr.Textbox(show_label=False, value="How much to scale the ZoeDepth. 2x is pretty dramatic...")
|
75 |
+
else:
|
76 |
+
use_zoe = False
|
77 |
+
zoe_scale = 0
|
78 |
with gr.Group():
|
79 |
min_detection_confidence = gr.Slider(label="Min detection confidence", value=0.5, minimum=0.0, maximum=1.0, step=0.01)
|
80 |
gr.Textbox(show_label=False, value="Minimum confidence value ([0.0, 1.0]) from the face detection model for the detection to be considered successful.")
|
81 |
+
with gr.Group():
|
82 |
+
gr.Markdown(
|
83 |
+
"""
|
84 |
+
The initial workflow I was imagining was:
|
85 |
+
|
86 |
+
1. sculpt high poly mesh in blender
|
87 |
+
2. snapshot the face
|
88 |
+
3. generate the mesh using the mediapipe stuff
|
89 |
+
4. import the low poly mediapipe face
|
90 |
+
5. snap the mesh to the high poly model
|
91 |
+
6. model the rest of the low poly model
|
92 |
+
7. bake the normal / etc maps to the low poly face model
|
93 |
+
8. it's just that easy 😛
|
94 |
+
|
95 |
+
Ideally it would be a plugin...
|
96 |
+
""")
|
97 |
+
|
98 |
with gr.Column():
|
99 |
with gr.Group():
|
100 |
num_faces_detected = gr.Number(label="Number of faces detected", value=0)
|
101 |
+
output_image = gr.Image(label="Output image",elem_id='img-display-output')
|
102 |
+
output_mesh = gr.Model3D(clear_color=[0.0, 0.0, 0.0, 0.0], label="3D Model",elem_id='img-display-output')
|
103 |
+
depth_image = gr.Image(label="Depth image",elem_id='img-display-output')
|
104 |
|
|
|
105 |
upload_image_btn.click(
|
106 |
fn=self.detect,
|
107 |
+
inputs=[upload_image, min_detection_confidence,use_zoe,zoe_scale],
|
108 |
+
outputs=[output_mesh, output_image, depth_image, num_faces_detected]
|
109 |
)
|
110 |
demo.launch()
|
111 |
|
112 |
|
113 |
+
def detect(self, image, min_detection_confidence, use_zoe,zoe_scale):
|
114 |
width = image.shape[1]
|
115 |
height = image.shape[0]
|
116 |
ratio = width / height
|
117 |
+
|
118 |
+
mp_drawing = mp.solutions.drawing_utils
|
119 |
+
mp_drawing_styles = mp.solutions.drawing_styles
|
120 |
+
mp_face_mesh = mp.solutions.face_mesh
|
121 |
|
122 |
mesh = "examples/jackiechan.obj"
|
123 |
|
124 |
+
if self.zoe_me and use_zoe:
|
125 |
+
depth = self.zoe.infer_pil(image)
|
126 |
+
print( f'type of depth is {type(depth)}' )
|
127 |
+
idepth = colorize(depth, cmap='gray_r')
|
128 |
+
else:
|
129 |
+
depth = None
|
130 |
+
idepth = image
|
131 |
+
|
132 |
drawing_spec = mp_drawing.DrawingSpec(thickness=1, circle_radius=1)
|
133 |
with mp_face_mesh.FaceMesh(
|
134 |
static_image_mode=True,
|
|
|
136 |
min_detection_confidence=min_detection_confidence) as face_mesh:
|
137 |
results = face_mesh.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
|
138 |
if not results.multi_face_landmarks:
|
139 |
+
return mesh, image, idepth, 0
|
140 |
|
141 |
annotated_image = image.copy()
|
142 |
for face_landmarks in results.multi_face_landmarks:
|
143 |
+
mesh = self.toObj(image=image, width=width, height=height, ratio=ratio, landmark_list=face_landmarks, depth=depth, zoe_scale=zoe_scale)
|
144 |
|
145 |
mp_drawing.draw_landmarks(
|
146 |
image=annotated_image,
|
|
|
157 |
connection_drawing_spec=mp_drawing_styles
|
158 |
.get_default_face_mesh_contours_style())
|
159 |
|
160 |
+
return mesh, annotated_image, idepth, 1
|
161 |
|
162 |
+
def toObj( self, image: np.ndarray, width:int, height:int, ratio: float, landmark_list: landmark_pb2.NormalizedLandmarkList, depth: np.ndarray, zoe_scale: float):
|
163 |
print( f'you have such pretty hair' )
|
164 |
+
|
165 |
+
obj_file = tempfile.NamedTemporaryFile(suffix='.obj', delete=False)
|
166 |
+
mtl_file = tempfile.NamedTemporaryFile(suffix='.mtl', delete=False)
|
167 |
+
png_file = tempfile.NamedTemporaryFile(suffix='.png', delete=False)
|
168 |
+
|
169 |
+
############################################
|
170 |
+
|
171 |
lines = []
|
172 |
+
lines.append( f'mtllib {os.path.basename(mtl_file.name)}' )
|
173 |
+
|
174 |
+
(points,coordinates) = self.landmarksToPoints( width, height, ratio, landmark_list, depth, zoe_scale )
|
175 |
for point in points:
|
176 |
+
lines.append( "v " + " ".join([str(value) for value in point]) )
|
177 |
+
|
178 |
+
for coordinate in coordinates:
|
179 |
+
lines.append( "vt " + " ".join([str(value) for value in coordinate]) )
|
180 |
+
|
181 |
for quad in QUADS:
|
|
|
|
|
182 |
normal = self.totallyNormal( points[ quad[ 0 ] -1 ], points[ quad[ 1 ] -1 ], points[ quad[ 2 ] -1 ] )
|
183 |
lines.append( "vn " + " ".join([str(value) for value in normal]) )
|
184 |
|
185 |
+
lines.append( 'usemtl MyMaterial' )
|
186 |
+
|
187 |
+
quadIndex = 0
|
188 |
+
for quad in QUADS:
|
189 |
+
quadIndex = 1 + quadIndex
|
190 |
+
if True:
|
191 |
+
lines.append( "f " + " ".join([f'{vertex}/{vertex}/{quadIndex}' for vertex in quad]) )
|
192 |
+
else:
|
193 |
+
lines.append( "f " + " ".join([str(vertex) for vertex in quad]) )
|
194 |
+
|
195 |
+
|
196 |
+
out = open( obj_file.name, 'w' )
|
197 |
+
out.write( '\n'.join( lines ) + '\n' )
|
198 |
out.close()
|
199 |
+
shutil.copy(obj_file.name, "/tmp/lol.obj")
|
200 |
+
|
201 |
+
############################################
|
202 |
|
203 |
+
lines = []
|
204 |
+
lines.append( 'newmtl MyMaterial' )
|
205 |
+
lines.append( f'Ka 1.000 1.000 1.000 # white' )
|
206 |
+
lines.append( f'Kd 1.000 1.000 1.000 # white' )
|
207 |
+
lines.append( f'Ks 0.000 0.000 0.000 # black (off)' )
|
208 |
+
lines.append( f'map_Ka {os.path.basename(png_file.name)}' )
|
209 |
+
lines.append( f'map_Kd {os.path.basename(png_file.name)}' )
|
210 |
+
|
211 |
+
out = open( mtl_file.name, 'w' )
|
212 |
+
out.write( '\n'.join( lines ) + '\n' )
|
213 |
+
out.close()
|
214 |
+
shutil.copy(mtl_file.name, "/tmp/lol.mtl")
|
215 |
+
|
216 |
+
############################################
|
217 |
+
|
218 |
+
cv2.imwrite(png_file.name, cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
|
219 |
+
shutil.copy(png_file.name, "/tmp/lol.png")
|
220 |
+
|
221 |
+
############################################
|
222 |
+
|
223 |
+
print( f'I know it is special to you so I saved it to {obj_file.name} since we are friends' )
|
224 |
+
return obj_file.name
|
225 |
+
|
226 |
+
def landmarksToPoints( self, width: int, height: int, ratio: float, landmark_list: landmark_pb2.NormalizedLandmarkList, depth: np.ndarray, zoe_scale: float ):
|
227 |
+
points = [] # 3d vertices
|
228 |
+
coordinates = [] # 2d texture coordinates
|
229 |
mins = [+np.inf] * 3
|
230 |
maxs = [-np.inf] * 3
|
231 |
for idx, landmark in enumerate(landmark_list.landmark):
|
|
|
234 |
(landmark.HasField('presence') and
|
235 |
landmark.presence < _PRESENCE_THRESHOLD)):
|
236 |
idk_what_to_do_for_this = True
|
237 |
+
x, y = _normalized_to_pixel_coordinates(landmark.x,landmark.y,width,height)
|
238 |
+
coordinates.append( [x/width,1-y/height] )
|
239 |
+
if depth is not None:
|
240 |
+
landmark.z = depth[y, x] * zoe_scale
|
241 |
point = [landmark.x * ratio, -landmark.y, -landmark.z];
|
242 |
for pidx,value in enumerate( point ):
|
243 |
mins[pidx] = min(mins[pidx],value)
|
|
|
251 |
print( f'mins: {mins}' )
|
252 |
print( f'mids: {mids}' )
|
253 |
print( f'maxs: {maxs}' )
|
254 |
+
return (points,coordinates)
|
255 |
|
256 |
def totallyNormal(self, p0, p1, p2):
|
257 |
v1 = np.array(p1) - np.array(p0)
|
|
|
262 |
|
263 |
|
264 |
face_image_to_face_mesh().demo()
|
265 |
+
|
266 |
+
# EOF
|
267 |
+
########################################################################################
|
examples/character.png
ADDED
quads.py
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# This was created by importing a MediaPipe tesselated mesh and manually converting it in blender
|
2 |
+
|
3 |
+
QUADS = [
|
4 |
+
[300, 334, 333, 298] , [ 1, 12, 303, 268] , [234, 233, 122, 129] , [270, 304, 305, 271] , [246, 129, 115, 189] ,
|
5 |
+
[112, 118, 229, 32] , [104, 55, 69, 105] , [228, 35, 128, 235] , [120, 102, 101, 121] , [ 74, 73, 38, 40] ,
|
6 |
+
[ 71, 47, 54, 64] , [135, 132, 116, 221] , [335, 294, 299, 334] , [ 73, 12, 1, 38] , [ 42, 43, 81, 82] ,
|
7 |
+
[166, 93, 41, 40] , [122, 233, 232, 121] , [215, 213, 217, 208] , [183, 84, 85, 182] , [376, 308, 321, 322] ,
|
8 |
+
[ 30, 161, 160, 28] , [ 57, 29, 159, 158] , [ 84, 202, 201, 19] , [117, 144, 35, 228] , [204, 207, 93, 166] ,
|
9 |
+
[139, 216, 59, 173] , [276, 282, 6, 5] , [ 25, 145, 164, 111] , [292, 307, 308, 376] , [143, 127, 48, 101] ,
|
10 |
+
[419, 422, 429, 263] , [147, 44, 107, 92] , [ 17, 86, 85, 18] , [ 78, 77, 62, 147] , [127, 210, 199, 218] ,
|
11 |
+
[397, 378, 401, 370] , [166, 40, 38, 168] , [245, 234, 129, 246] , [ 31, 248, 247, 162] , [ 34, 247, 248, 131] ,
|
12 |
+
[175, 218, 199, 237] , [418, 352, 413, 466] , [125, 114, 226, 47] , [225, 224, 53, 54] , [ 99, 65, 103, 130] ,
|
13 |
+
[193, 215, 208, 188] , [219, 80, 240, 238] , [134, 156, 113, 244] , [345, 361, 364, 441] , [141, 171, 150, 177] ,
|
14 |
+
[400, 413, 352, 420] , [119, 230, 229, 118] , [282, 276, 441, 364] , [ 71, 64, 69, 72] , [315, 314, 407, 406] ,
|
15 |
+
[222, 190, 194, 56] , [114, 248, 31, 226] , [106, 53, 66, 67] , [236, 60, 167, 220] , [108, 56, 9, 10] ,
|
16 |
+
[ 67, 66, 56, 108] , [ 69, 64, 106, 105] , [120, 119, 51, 102] , [242, 126, 45, 238] , [ 6, 196, 4, 52] ,
|
17 |
+
[143, 130, 210, 127] , [ 34, 131, 26, 8] , [323, 271, 410, 411] , [ 33, 195, 205, 212] , [ 37, 102, 51, 206] ,
|
18 |
+
[195, 202, 84, 183] , [238, 240, 239, 242] , [ 26, 111, 164, 8] , [225, 54, 47, 226] , [154, 146, 24, 23] ,
|
19 |
+
[211, 203, 213, 215] , [246, 194, 190, 245] , [425, 336, 407, 419] , [318, 317, 404, 403] , [ 33, 212, 171, 141] ,
|
20 |
+
[ 12, 73, 39, 13] , [208, 217, 207, 206] , [238, 221, 116, 219] , [ 46, 221, 238, 45] , [184, 43, 75, 185] ,
|
21 |
+
[209, 202, 195, 33] , [269, 272, 304, 303] , [214, 148, 178, 216] , [235, 94, 138, 228] , [ 67, 108, 109, 70] ,
|
22 |
+
[ 7, 352, 418, 169] , [193, 188, 148, 214] , [ 97, 63, 77, 78] , [125, 47, 71, 157] , [317, 16, 17, 316] ,
|
23 |
+
[180, 87, 88, 179] , [106, 64, 54, 53] , [119, 118, 124, 51] , [146, 145, 25, 24] , [325, 319, 320, 326] ,
|
24 |
+
[123, 189, 175, 197] , [293, 309, 325, 326] , [150, 171, 170, 151] , [178, 138, 94, 133] , [328, 295, 456, 461] ,
|
25 |
+
[361, 421, 457, 364] , [336, 274, 376, 322] , [396, 395, 431, 432] , [ 13, 39, 83, 14] , [278, 330, 350, 351] ,
|
26 |
+
[191, 57, 158, 174] , [117, 112, 36, 144] , [224, 223, 66, 53] , [140, 72, 22, 163] , [163, 128, 35, 140] ,
|
27 |
+
[366, 365, 395, 380] , [219, 116, 49, 220] , [430, 359, 372, 356] , [157, 144, 36, 125] , [377, 353, 281, 412] ,
|
28 |
+
[125, 36, 227, 114] , [355, 20, 95, 371] , [120, 231, 230, 119] , [249, 457, 400, 420] , [162, 161, 30, 31] ,
|
29 |
+
[ 46, 45, 2, 5] , [141, 172, 209, 33] , [394, 392, 328, 327] , [ 32, 26, 131, 227] , [300, 298, 339, 338] ,
|
30 |
+
[395, 396, 379, 380] , [102, 37, 143, 101] , [217, 213, 58, 187] , [327, 3, 165, 394] , [242, 239, 21, 243] ,
|
31 |
+
[186, 41, 93, 187] , [269, 303, 12, 13] , [192, 81, 43, 184] , [140, 35, 144, 157] , [223, 222, 56, 66] ,
|
32 |
+
[189, 115, 218, 175] , [323, 427, 424, 392] , [ 37, 204, 130, 143] , [280, 430, 421, 361] , [ 2, 275, 276, 5] ,
|
33 |
+
[134, 244, 191, 174] , [241, 76, 60, 236] , [108, 10, 152, 109] , [ 27, 155, 154, 23] , [211, 215, 136, 170] ,
|
34 |
+
[355, 275, 2, 20] , [ 90, 89, 96, 97] , [321, 320, 404, 405] , [316, 315, 406, 405] , [107, 44, 203, 205] ,
|
35 |
+
[201, 422, 314, 19] , [153, 176, 172, 149] , [376, 274, 288, 292] , [292, 288, 411, 410] , [130, 204, 166, 99] ,
|
36 |
+
[115, 48, 127, 218] , [327, 328, 461, 329] , [105, 106, 67, 70] , [236, 65, 99, 241] , [200, 201, 202, 209] ,
|
37 |
+
[332, 295, 328, 359] , [100, 61, 76, 241] , [243, 142, 126, 242] , [329, 463, 371, 327] , [220, 167, 80, 219] ,
|
38 |
+
[233, 27, 23, 232] , [190, 222, 57, 191] , [223, 29, 57, 222] , [244, 113, 234, 245] , [ 32, 229, 111, 26] ,
|
39 |
+
[226, 31, 30, 225] , [232, 23, 24, 231] , [225, 30, 28, 224] , [114, 227, 131, 248] , [ 32, 227, 36, 112] ,
|
40 |
+
[234, 113, 27, 233] , [230, 25, 111, 229] , [224, 28, 29, 223] , [ 95, 20, 126, 142] , [239, 240, 80, 21] ,
|
41 |
+
[243, 21, 61, 100] , [157, 71, 72, 140] , [ 76, 61, 167, 60] , [189, 123, 194, 246] , [231, 24, 25, 230] ,
|
42 |
+
[232, 231, 120, 121] , [121, 101, 48, 122] , [208, 206, 51, 188] , [332, 280, 279, 295] , [196, 249, 420, 198] ,
|
43 |
+
[199, 210, 50, 132] , [177, 149, 172, 141] , [117, 124, 118, 112] , [ 28, 160, 159, 29] , [245, 190, 191, 244] ,
|
44 |
+
[379, 396, 370, 401] , [268, 303, 304, 270] , [351, 453, 454, 358] , [ 75, 74, 40, 41] , [169, 418, 286, 9] ,
|
45 |
+
[283, 444, 445, 284] , [397, 176, 153, 378] , [110, 68, 70, 109] , [301, 277, 354, 384] , [186, 62, 77, 185] ,
|
46 |
+
[299, 294, 301, 302] , [ 50, 49, 116, 132] , [422, 201, 200, 429] , [304, 272, 273, 305] , [271, 323, 392, 270] ,
|
47 |
+
[296, 443, 444, 283] , [427, 437, 428, 426] , [336, 322, 406, 407] , [ 19, 314, 315, 18] , [387, 388, 260, 258] ,
|
48 |
+
[255, 374, 375, 254] , [314, 422, 419, 407] , [297, 335, 334, 300] , [313, 312, 272, 269] , [ 55, 22, 72, 69] ,
|
49 |
+
[221, 46, 52, 135] , [391, 374, 255, 340] , [315, 316, 17, 18] , [372, 267, 331, 330] , [423, 274, 336, 425] ,
|
50 |
+
[ 58, 44, 147, 62] , [ 91, 78, 147, 92] , [182, 85, 86, 181] , [423, 425, 432, 431] , [357, 265, 448, 455] ,
|
51 |
+
[268, 270, 392, 394] , [358, 454, 465, 466] , [264, 360, 468, 467] , [264, 250, 256, 360] , [421, 430, 356, 438] ,
|
52 |
+
[194, 123, 7, 169] , [449, 450, 348, 347] , [277, 284, 445, 446] , [241, 99, 98, 100] , [281, 331, 267, 426] ,
|
53 |
+
[307, 292, 410, 409] , [260, 388, 389, 261] , [364, 457, 249, 282] , [338, 339, 11, 152] , [438, 344, 413, 400] ,
|
54 |
+
[349, 451, 452, 350] , [345, 279, 280, 361] , [402, 377, 434, 436] , [367, 324, 455, 448] , [182, 92, 107, 183] ,
|
55 |
+
[418, 414, 442, 286] , [360, 256, 262, 447] , [284, 277, 301, 294] , [291, 251, 463, 329] , [344, 358, 466, 413] ,
|
56 |
+
[179, 89, 90, 180] , [266, 341, 346, 373] , [429, 397, 370, 263] , [296, 283, 335, 297] , [275, 355, 462, 458] ,
|
57 |
+
[ 4, 237, 135, 52] , [359, 424, 267, 372] , [386, 387, 258, 259] , [394, 165, 1, 268] , [207, 217, 187, 93] ,
|
58 |
+
[278, 356, 372, 330] , [ 44, 58, 213, 203] , [459, 460, 458, 462] , [381, 382, 257, 253] , [266, 447, 262, 341] ,
|
59 |
+
[399, 385, 287, 415] , [437, 433, 435, 428] , [447, 266, 354, 343] , [183, 107, 205, 195] , [ 43, 42, 74, 75] ,
|
60 |
+
[302, 301, 384, 369] , [425, 419, 263, 432] , [295, 279, 440, 456] , [ 49, 50, 103, 65] , [ 74, 42, 39, 73] ,
|
61 |
+
[433, 423, 431, 435] , [311, 273, 272, 312] , [353, 367, 448, 346] , [252, 302, 369, 390] , [209, 172, 176, 200] ,
|
62 |
+
[ 56, 194, 169, 9] , [377, 412, 417, 434] , [ 90, 97, 78, 91] , [330, 331, 349, 350] , [180, 90, 91, 181] ,
|
63 |
+
[281, 348, 349, 331] , [265, 373, 346, 448] , [324, 367, 402, 362] , [308, 326, 320, 321] , [ 16, 15, 88, 87] ,
|
64 |
+
[266, 373, 384, 354] , [353, 347, 348, 281] , [363, 399, 415, 464] , [318, 15, 16, 317] , [356, 278, 344, 438] ,
|
65 |
+
[ 96, 79, 63, 97] , [ 11, 110, 109, 152] , [398, 368, 365, 366] , [ 2, 45, 126, 20] , [313, 269, 13, 14] ,
|
66 |
+
[237, 199, 132, 135] , [187, 58, 62, 186] , [152, 10, 337, 338] , [ 42, 82, 83, 39] , [414, 418, 466, 465] ,
|
67 |
+
[467, 468, 261, 389] , [ 9, 286, 337, 10] , [446, 343, 354, 277] , [265, 357, 390, 369] , [436, 434, 417, 368] ,
|
68 |
+
[170, 136, 137, 151] , [458, 441, 276, 275] , [212, 205, 203, 211] , [347, 353, 346, 341] , [284, 294, 335, 283] ,
|
69 |
+
[452, 453, 351, 350] , [ 95, 3, 327, 371] , [450, 451, 349, 348] , [197, 4, 196, 198] , [254, 375, 381, 253] ,
|
70 |
+
[345, 441, 458, 439] , [367, 353, 377, 402] , [449, 347, 341, 262] , [360, 447, 343, 468] , [136, 139, 173, 137] ,
|
71 |
+
[289, 436, 368, 398] , [281, 426, 428, 412] , [288, 433, 437, 411] , [ 99, 166, 168, 98] , [142, 243, 100, 98] ,
|
72 |
+
[175, 237, 4, 197] , [185, 75, 41, 186] , [307, 293, 326, 308] , [396, 432, 263, 370] , [286, 442, 443, 296] ,
|
73 |
+
[428, 435, 417, 412] , [411, 437, 427, 323] , [421, 438, 400, 457] , [165, 3, 98, 168] , [279, 345, 439, 440] ,
|
74 |
+
[391, 340, 256, 250] , [306, 291, 329, 461] , [373, 265, 369, 384] , [386, 259, 287, 385] , [435, 365, 368, 417] ,
|
75 |
+
[251, 459, 462, 463] , [320, 319, 403, 404] , [ 17, 16, 87, 86] , [322, 321, 405, 406] , [ 85, 84, 19, 18] ,
|
76 |
+
[433, 288, 274, 423] , [362, 402, 436, 289] , [185, 77, 63, 184] , [293, 307, 409, 408] , [392, 424, 359, 328] ,
|
77 |
+
[352, 7, 198, 420] , [228, 138, 124, 117] , [393, 290, 456, 440] , [176, 397, 429, 200] , [220, 49, 65, 236] ,
|
78 |
+
[424, 427, 426, 267] , [332, 359, 430, 280] , [365, 435, 431, 395] , [310, 251, 291, 393] , [355, 371, 463, 462] ,
|
79 |
+
[ 98, 3, 95, 142] , [255, 254, 451, 450] , [415, 414, 465, 464] , [254, 253, 452, 451] , [261, 468, 343, 446] ,
|
80 |
+
[260, 261, 446, 445] , [258, 260, 445, 444] , [454, 342, 464, 465] , [198, 7, 123, 197] , [259, 258, 444, 443] ,
|
81 |
+
[287, 442, 414, 415] , [340, 449, 262, 256] , [340, 255, 450, 449] , [257, 342, 454, 453] , [ 61, 21, 80, 167] ,
|
82 |
+
[310, 393, 440, 439] , [338, 337, 297, 300] , [310, 460, 459, 251] , [ 51, 124, 148, 188] , [253, 257, 453, 452] ,
|
83 |
+
[215, 193, 139, 136] , [351, 358, 344, 278] , [113, 156, 155, 27] , [ 6, 52, 46, 5] , [206, 207, 204, 37] ,
|
84 |
+
[249, 196, 6, 282] , [216, 178, 133, 59] , [286, 296, 297, 337] , [382, 383, 342, 257] , [287, 259, 443, 442] ,
|
85 |
+
[211, 170, 171, 212] , [306, 461, 456, 290] , [104, 105, 70, 68] , [271, 305, 409, 410] , [460, 310, 439, 458] ,
|
86 |
+
[214, 216, 139, 193] , [317, 316, 405, 404] , [181, 91, 92, 182] , [ 1, 165, 168, 38] , [363, 464, 342, 383] ,
|
87 |
+
[210, 130, 103, 50] , [305, 273, 408, 409] , [311, 416, 408, 273] , [309, 293, 408, 416] , [184, 63, 79, 192] ,
|
88 |
+
[115, 129, 122, 48] , [148, 124, 138, 178] , [181, 86, 87, 180] , [290, 393, 291, 306] , [252, 285, 299, 302] ,
|
89 |
+
[285, 333, 334, 299]
|
90 |
+
]
|
utils.py
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# from https://huggingface.co/spaces/shariqfarooq/ZoeDepth/raw/main/utils.py
|
2 |
+
|
3 |
+
# MIT License
|
4 |
+
|
5 |
+
# Copyright (c) 2022 Intelligent Systems Lab Org
|
6 |
+
|
7 |
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
# of this software and associated documentation files (the "Software"), to deal
|
9 |
+
# in the Software without restriction, including without limitation the rights
|
10 |
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
# copies of the Software, and to permit persons to whom the Software is
|
12 |
+
# furnished to do so, subject to the following conditions:
|
13 |
+
|
14 |
+
# The above copyright notice and this permission notice shall be included in all
|
15 |
+
# copies or substantial portions of the Software.
|
16 |
+
|
17 |
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23 |
+
# SOFTWARE.
|
24 |
+
|
25 |
+
# File author: Shariq Farooq Bhat
|
26 |
+
|
27 |
+
import matplotlib
|
28 |
+
import matplotlib.cm
|
29 |
+
import numpy as np
|
30 |
+
import torch
|
31 |
+
|
32 |
+
def colorize(value, vmin=None, vmax=None, cmap='magma_r', invalid_val=-99, invalid_mask=None, background_color=(128, 128, 128, 255), gamma_corrected=False, value_transform=None):
|
33 |
+
"""Converts a depth map to a color image.
|
34 |
+
|
35 |
+
Args:
|
36 |
+
value (torch.Tensor, numpy.ndarry): Input depth map. Shape: (H, W) or (1, H, W) or (1, 1, H, W). All singular dimensions are squeezed
|
37 |
+
vmin (float, optional): vmin-valued entries are mapped to start color of cmap. If None, value.min() is used. Defaults to None.
|
38 |
+
vmax (float, optional): vmax-valued entries are mapped to end color of cmap. If None, value.max() is used. Defaults to None.
|
39 |
+
cmap (str, optional): matplotlib colormap to use. Defaults to 'magma_r'.
|
40 |
+
invalid_val (int, optional): Specifies value of invalid pixels that should be colored as 'background_color'. Defaults to -99.
|
41 |
+
invalid_mask (numpy.ndarray, optional): Boolean mask for invalid regions. Defaults to None.
|
42 |
+
background_color (tuple[int], optional): 4-tuple RGB color to give to invalid pixels. Defaults to (128, 128, 128, 255).
|
43 |
+
gamma_corrected (bool, optional): Apply gamma correction to colored image. Defaults to False.
|
44 |
+
value_transform (Callable, optional): Apply transform function to valid pixels before coloring. Defaults to None.
|
45 |
+
|
46 |
+
Returns:
|
47 |
+
numpy.ndarray, dtype - uint8: Colored depth map. Shape: (H, W, 4)
|
48 |
+
"""
|
49 |
+
if isinstance(value, torch.Tensor):
|
50 |
+
value = value.detach().cpu().numpy()
|
51 |
+
|
52 |
+
value = value.squeeze()
|
53 |
+
if invalid_mask is None:
|
54 |
+
invalid_mask = value == invalid_val
|
55 |
+
mask = np.logical_not(invalid_mask)
|
56 |
+
|
57 |
+
# normalize
|
58 |
+
vmin = np.percentile(value[mask],2) if vmin is None else vmin
|
59 |
+
vmax = np.percentile(value[mask],85) if vmax is None else vmax
|
60 |
+
if vmin != vmax:
|
61 |
+
value = (value - vmin) / (vmax - vmin) # vmin..vmax
|
62 |
+
else:
|
63 |
+
# Avoid 0-division
|
64 |
+
value = value * 0.
|
65 |
+
|
66 |
+
# squeeze last dim if it exists
|
67 |
+
# grey out the invalid values
|
68 |
+
|
69 |
+
value[invalid_mask] = np.nan
|
70 |
+
cmapper = matplotlib.cm.get_cmap(cmap)
|
71 |
+
if value_transform:
|
72 |
+
value = value_transform(value)
|
73 |
+
# value = value / value.max()
|
74 |
+
value = cmapper(value, bytes=True) # (nxmx4)
|
75 |
+
|
76 |
+
# img = value[:, :, :]
|
77 |
+
img = value[...]
|
78 |
+
img[invalid_mask] = background_color
|
79 |
+
|
80 |
+
# return img.transpose((2, 0, 1))
|
81 |
+
if gamma_corrected:
|
82 |
+
# gamma correction
|
83 |
+
img = img / 255
|
84 |
+
img = np.power(img, 2.2)
|
85 |
+
img = img * 255
|
86 |
+
img = img.astype(np.uint8)
|
87 |
+
return img
|
88 |
+
|