vgvm commited on
Commit
5f3e3d6
1 Parent(s): fbcab86

add zoedepth, gradio obj loader is struggling locally, but blender is fine

Browse files
Files changed (4) hide show
  1. app.py +156 -139
  2. examples/character.png +0 -0
  3. quads.py +90 -0
  4. 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
- from mediapipe.framework.formats import landmark_pb2
11
- from typing import List, Mapping, Optional, Tuple, Union
12
-
13
  import pygltflib
 
14
  import struct
15
  import tempfile
 
16
 
17
- QUADS = [
18
- [300, 334, 333, 298] , [ 1, 12, 303, 268] , [234, 233, 122, 129] , [270, 304, 305, 271] , [246, 129, 115, 189] ,
19
- [112, 118, 229, 32] , [104, 55, 69, 105] , [228, 35, 128, 235] , [120, 102, 101, 121] , [ 74, 73, 38, 40] ,
20
- [ 71, 47, 54, 64] , [135, 132, 116, 221] , [335, 294, 299, 334] , [ 73, 12, 1, 38] , [ 42, 43, 81, 82] ,
21
- [166, 93, 41, 40] , [122, 233, 232, 121] , [215, 213, 217, 208] , [183, 84, 85, 182] , [376, 308, 321, 322] ,
22
- [ 30, 161, 160, 28] , [ 57, 29, 159, 158] , [ 84, 202, 201, 19] , [117, 144, 35, 228] , [204, 207, 93, 166] ,
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
- demo = gr.Blocks()
 
 
 
 
109
  with demo:
110
- gr.Markdown(
111
- """
112
- # Face Image to Face Quad Mesh
113
- Uses MediaPipe to detect a face in an image and convert it to a quad mesh.
114
- Currently saves to OBJ, hopefully glb at some point with color data.
115
- The 3d viewer has Y pointing the opposite direction from Blender, so ya hafta spin it.
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
- output_mesh = gr.Model3D(clear_color=[0.0, 0.0, 0.0, 0.0], label="3D Model")
148
- output_image = gr.Image(label="Output image")
 
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=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
- points = self.landmarksToPoints( ratio, landmark_list )
 
 
200
  for point in points:
201
- vertex = "v " + " ".join([str(value) for value in point])
202
- lines.append( vertex )
 
 
 
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
- obj_file = tempfile.NamedTemporaryFile(suffix='.obj', delete=False)
210
- output_file = obj_file.name
211
- out = open( output_file, 'w' )
212
- out.write( '\n'.join( lines ) )
 
 
 
 
 
 
 
 
 
213
  out.close()
214
- print( f'I know it is special to you so I saved it to {output_file} since we are friends' )
215
- return output_file
 
216
 
217
- def landmarksToPoints( self, ratio: float, landmark_list: landmark_pb2.NormalizedLandmarkList ):
218
- points = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+