amankishore commited on
Commit
6e20537
1 Parent(s): 5e74c8d

Point E Gradio

Browse files
app.py ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ from PIL import Image
4
+ import torch
5
+ import matplotlib.pyplot as plt
6
+ import imageio
7
+ import numpy as np
8
+ import argparse
9
+
10
+ from point_e.diffusion.configs import DIFFUSION_CONFIGS, diffusion_from_config
11
+ from point_e.diffusion.sampler import PointCloudSampler
12
+ from point_e.models.download import load_checkpoint
13
+ from point_e.models.configs import MODEL_CONFIGS, model_from_config
14
+ from point_e.util.plotting import plot_point_cloud
15
+ from point_e.util.pc_to_mesh import marching_cubes_mesh
16
+
17
+ from diffusers import StableDiffusionPipeline
18
+
19
+ import trimesh
20
+
21
+
22
+ state = ""
23
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
24
+
25
+ css = '''
26
+ .instruction{position: absolute; top: 0;right: 0;margin-top: 0px !important}
27
+ .arrow{position: absolute;top: 0;right: -110px;margin-top: -8px !important}
28
+ #component-4, #component-3, #component-10{min-height: 0}
29
+ .duplicate-button img{margin: 0}
30
+ '''
31
+
32
+ def set_state(s):
33
+ print(s)
34
+ global state
35
+ state = s
36
+
37
+ def get_state():
38
+ return state
39
+
40
+ def load_img2mesh_model(model_name):
41
+ set_state(f'Creating img2mesh model {model_name}...')
42
+ i2m_name = model_name
43
+ i2m_model = model_from_config(MODEL_CONFIGS[i2m_name], device)
44
+ i2m_model.eval()
45
+ base_diffusion_i2m = diffusion_from_config(DIFFUSION_CONFIGS[i2m_name])
46
+
47
+ set_state(f'Downloading img2mesh checkpoint {model_name}...')
48
+ i2m_model.load_state_dict(load_checkpoint(i2m_name, device))
49
+
50
+ return i2m_model, base_diffusion_i2m
51
+
52
+
53
+
54
+ def get_sampler(model_name, txt2obj, guidance_scale):
55
+ if txt2obj:
56
+ set_state('Creating txt2mesh model...')
57
+ t2m_name = 'base40M-textvec'
58
+ t2m_model = model_from_config(MODEL_CONFIGS[t2m_name], device)
59
+ t2m_model.eval()
60
+ base_diffusion_t2m = diffusion_from_config(DIFFUSION_CONFIGS[t2m_name])
61
+
62
+ set_state('Downloading txt2mesh checkpoint...')
63
+ t2m_model.load_state_dict(load_checkpoint(t2m_name, device))
64
+ else:
65
+ i2m_model, base_diffusion_i2m = load_img2mesh_model(model_name)
66
+
67
+ set_state('Creating upsample model...')
68
+ upsampler_model = model_from_config(MODEL_CONFIGS['upsample'], device)
69
+ upsampler_model.eval()
70
+ upsampler_diffusion = diffusion_from_config(DIFFUSION_CONFIGS['upsample'])
71
+
72
+ set_state('Downloading upsampler checkpoint...')
73
+ upsampler_model.load_state_dict(load_checkpoint('upsample', device))
74
+
75
+ return PointCloudSampler(
76
+ device=device,
77
+ models=[t2m_model if txt2obj else i2m_model, upsampler_model],
78
+ diffusions=[base_diffusion_t2m if txt2obj else base_diffusion_i2m, upsampler_diffusion],
79
+ num_points=[1024, 4096 - 1024],
80
+ aux_channels=['R', 'G', 'B'],
81
+ guidance_scale=[guidance_scale, 0.0 if txt2obj else guidance_scale],
82
+ model_kwargs_key_filter=('texts', '') if txt2obj else ("*",)
83
+ )
84
+
85
+ def generate_txt2img(prompt):
86
+ pipe = StableDiffusionPipeline.from_pretrained("point_e_model_cache/stable-diffusion-2-1", torch_dtype=torch.float16)
87
+ pipe = pipe.to("cuda")
88
+ image = pipe(prompt).images[0]
89
+
90
+ return image
91
+
92
+ def generate_3D(input, model_name='base1B', guidance_scale=3.0, grid_size=128):
93
+ set_state('Entered generate function...')
94
+
95
+ # try:
96
+ # input = Image.fromarray(input)
97
+ # except:
98
+ # img = generate_txt2img(input)
99
+ # img.save('/tmp/img.png')
100
+ # input = Image.open('/tmp/img.png')
101
+
102
+ if isinstance(input, Image.Image):
103
+ input = prepare_img(input)
104
+
105
+ # if input is a string, it's a text prompt
106
+ sampler = get_sampler(model_name, txt2obj=True if isinstance(input, str) else False, guidance_scale=guidance_scale)
107
+
108
+ # Produce a sample from the model.
109
+ set_state('Sampling...')
110
+ samples = None
111
+ kw_args = dict(texts=[input]) if isinstance(input, str) else dict(images=[input])
112
+ for x in sampler.sample_batch_progressive(batch_size=1, model_kwargs=kw_args):
113
+ samples = x
114
+
115
+ set_state('Converting to point cloud...')
116
+ pc = sampler.output_to_point_clouds(samples)[0]
117
+
118
+ set_state('Converting to mesh...')
119
+ save_ply(pc, '/tmp/mesh.ply', grid_size)
120
+
121
+ set_state('')
122
+
123
+ return ply_to_glb('/tmp/mesh.ply', '/tmp/mesh.glb'), create_gif(pc), gr.update(value=['/tmp/mesh.glb', '/tmp/mesh.ply'], visible=True)
124
+
125
+ def prepare_img(img):
126
+
127
+ w, h = img.size
128
+ if w > h:
129
+ img = img.crop((w - h) / 2, 0, w - (w - h) / 2, h)
130
+ else:
131
+ img = img.crop((0, (h - w) / 2, w, h - (h - w) / 2))
132
+
133
+ # resize to 256x256
134
+ img = img.resize((256, 256))
135
+
136
+ return img
137
+
138
+
139
+ def ply_to_glb(ply_file, glb_file):
140
+ mesh = trimesh.load(ply_file)
141
+
142
+ # Save the mesh as a glb file using Trimesh
143
+ mesh.export(glb_file, file_type='glb')
144
+
145
+ return glb_file
146
+
147
+ def save_ply(pc, file_name, grid_size):
148
+ set_state('Creating SDF model...')
149
+ sdf_name = 'sdf'
150
+ sdf_model = model_from_config(MODEL_CONFIGS[sdf_name], device)
151
+ sdf_model.eval()
152
+
153
+ set_state('Loading SDF model...')
154
+ sdf_model.load_state_dict(load_checkpoint(sdf_name, device))
155
+
156
+ # Produce a mesh (with vertex colors)
157
+ mesh = marching_cubes_mesh(
158
+ pc=pc,
159
+ model=sdf_model,
160
+ batch_size=4096,
161
+ grid_size=grid_size, # increase to 128 for resolution used in evals
162
+ progress=True,
163
+ )
164
+
165
+ # Write the mesh to a PLY file to import into some other program.
166
+ with open(file_name, 'wb') as f:
167
+ mesh.write_ply(f)
168
+
169
+ def create_gif(pc):
170
+ fig = plt.figure(facecolor='black', figsize=(4, 4))
171
+ ax = fig.add_subplot(111, projection='3d', facecolor='black')
172
+ fixed_bounds=((-0.75, -0.75, -0.75),(0.75, 0.75, 0.75))
173
+
174
+ # Create an empty list to store the frames
175
+ frames = []
176
+
177
+ # Create a loop to generate the frames for the GIF
178
+ for angle in range(0, 360, 4):
179
+ # Clear the plot and plot the point cloud
180
+ ax.clear()
181
+ color_args = np.stack(
182
+ [pc.channels["R"], pc.channels["G"], pc.channels["B"]], axis=-1
183
+ )
184
+ c = pc.coords
185
+
186
+
187
+ ax.scatter(c[:, 0], c[:, 1], c[:, 2], c=color_args)
188
+
189
+ # Set the viewpoint for the plot
190
+ ax.view_init(elev=10, azim=angle)
191
+
192
+ # Turn off the axis labels and ticks
193
+ ax.axis('off')
194
+ ax.set_xlim3d(fixed_bounds[0][0], fixed_bounds[1][0])
195
+ ax.set_ylim3d(fixed_bounds[0][1], fixed_bounds[1][1])
196
+ ax.set_zlim3d(fixed_bounds[0][2], fixed_bounds[1][2])
197
+
198
+ # Draw the figure to update the image data
199
+ fig.canvas.draw()
200
+
201
+ # Save the plot as a frame for the GIF
202
+ frame = np.array(fig.canvas.renderer.buffer_rgba())
203
+ w, h = frame.shape[0], frame.shape[1]
204
+ i = int(round((h - int(h*0.6)) / 2.))
205
+ frame = frame[i:i + int(h*0.6),i:i + int(h*0.6)]
206
+ frames.append(frame)
207
+
208
+ # Save the GIF using imageio
209
+ imageio.mimsave('/tmp/pointcloud.mp4', frames, fps=30)
210
+ return '/tmp/pointcloud.mp4'
211
+
212
+ block = gr.Blocks().queue(max_size=250, concurrency_count=6)
213
+ with block:
214
+ with gr.Box():
215
+ if(not torch.cuda.is_available()):
216
+ top_description = gr.HTML(f'''
217
+ <div style="text-align: center; max-width: 650px; margin: 0 auto;">
218
+ <div>
219
+ <img class="logo" src="file/images/mirage.png" alt="Mirage Logo"
220
+ style="margin: auto; max-width: 7rem;">
221
+ <br />
222
+ <h1 style="font-weight: 900; font-size: 2.5rem;">
223
+ Point-E Web UI
224
+ </h1>
225
+ <br />
226
+ <a class="duplicate-button" style="display:inline-block" target="_blank" href="https://huggingface.co/spaces/MirageML/point-e?duplicate=true"><img src="https://img.shields.io/badge/-Duplicate%20Space-blue?labelColor=white&style=flat&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAP5JREFUOE+lk7FqAkEURY+ltunEgFXS2sZGIbXfEPdLlnxJyDdYB62sbbUKpLbVNhyYFzbrrA74YJlh9r079973psed0cvUD4A+4HoCjsA85X0Dfn/RBLBgBDxnQPfAEJgBY+A9gALA4tcbamSzS4xq4FOQAJgCDwV2CPKV8tZAJcAjMMkUe1vX+U+SMhfAJEHasQIWmXNN3abzDwHUrgcRGmYcgKe0bxrblHEB4E/pndMazNpSZGcsZdBlYJcEL9Afo75molJyM2FxmPgmgPqlWNLGfwZGG6UiyEvLzHYDmoPkDDiNm9JR9uboiONcBXrpY1qmgs21x1QwyZcpvxt9NS09PlsPAAAAAElFTkSuQmCC&logoWidth=14" alt="Duplicate Space"></a>
227
+ </div>
228
+ <br />
229
+ <p style="margin-bottom: 10px; font-size: 94%">
230
+ Generate 3D Assets in 2 minutes with a prompt or image!
231
+ Based on the <a href="https://github.com/openai/point-e">Point-E</a> implementation
232
+ </p>
233
+ <br />
234
+ <p>There's only one step left before you can train your model: <a href="https://huggingface.co/spaces/{os.environ['SPACE_ID']}/settings" style="text-decoration: underline" target="_blank">attribute a <b>T4 GPU</b> to it (via the Settings tab)</a> and run the training below. Other GPUs are not compatible for now. You will be billed by the minute from when you activate the GPU until when it is turned it off.</p>
235
+ </div>
236
+ ''')
237
+ else:
238
+ top_description = gr.HTML(f'''
239
+ <div style="text-align: center; max-width: 650px; margin: 0 auto;">
240
+ <div>
241
+ <img class="logo" src="file/images/mirage.png" alt="Mirage Logo"
242
+ style="margin: auto; max-width: 7rem;">
243
+ <br />
244
+ <h1 style="font-weight: 900; font-size: 2.5rem;">
245
+ Point-E Web UI
246
+ </h1>
247
+ <br />
248
+ <a class="duplicate-button" style="display:inline-block" target="_blank" href="https://huggingface.co/spaces/MirageML/point-e?duplicate=true"><img src="https://img.shields.io/badge/-Duplicate%20Space-blue?labelColor=white&style=flat&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAP5JREFUOE+lk7FqAkEURY+ltunEgFXS2sZGIbXfEPdLlnxJyDdYB62sbbUKpLbVNhyYFzbrrA74YJlh9r079973psed0cvUD4A+4HoCjsA85X0Dfn/RBLBgBDxnQPfAEJgBY+A9gALA4tcbamSzS4xq4FOQAJgCDwV2CPKV8tZAJcAjMMkUe1vX+U+SMhfAJEHasQIWmXNN3abzDwHUrgcRGmYcgKe0bxrblHEB4E/pndMazNpSZGcsZdBlYJcEL9Afo75molJyM2FxmPgmgPqlWNLGfwZGG6UiyEvLzHYDmoPkDDiNm9JR9uboiONcBXrpY1qmgs21x1QwyZcpvxt9NS09PlsPAAAAAElFTkSuQmCC&logoWidth=14" alt="Duplicate Space"></a>
249
+ </div>
250
+ <br />
251
+ <p style="margin-bottom: 10px; font-size: 94%">
252
+ Generate 3D Assets in 2 minutes with a prompt or image!
253
+ Based on the <a href="https://github.com/openai/point-e">Point-E</a> implementation
254
+ </p>
255
+ </div>
256
+ ''')
257
+ with gr.Row():
258
+ with gr.Column():
259
+ with gr.Tab("Image to 3D"):
260
+ gr.Markdown("Best results with images of objects on an empty background.")
261
+ input_image = gr.Image(label="Image")
262
+ img_button = gr.Button(label="Generate")
263
+
264
+ with gr.Tab("Text to 3D"):
265
+ gr.Markdown("Uses Stable Diffusion to create an image from the prompt.")
266
+ prompt = gr.Textbox(label="Prompt", placeholder="A HD photo of a Corgi")
267
+ text_button = gr.Button(label="Generate")
268
+
269
+ with gr.Accordion("Advanced options", open=False):
270
+ model = gr.Radio(["base40M", "base300M", "base1B"], label="Model", value="base1B")
271
+ scale = gr.Slider(
272
+ label="Guidance Scale", minimum=1.0, maximum=10.0, value=3.0, step=0.1
273
+ )
274
+
275
+ with gr.Column():
276
+ model_gif = gr.Video(label="3D Model GIF")
277
+ # btn_pc_to_obj = gr.Button(value="Convert to OBJ", visible=False)
278
+ model_3d = gr.Model3D(value=None)
279
+ file_out = gr.File(label="Files", visible=False)
280
+
281
+ if torch.cuda.is_available():
282
+ gr.Examples(
283
+ examples=[
284
+ ["images/pumpkin.png"],
285
+ ["images/fantasy_world.png"],
286
+ ],
287
+ inputs=[input_image],
288
+ outputs=[model_3d, model_gif, file_out],
289
+ fn=generate_3D,
290
+ cache_examples=True
291
+ )
292
+
293
+ img_button.click(fn=generate_3D, inputs=[input_image, model, scale], outputs=[model_3d, model_gif, file_out])
294
+ text_button.click(fn=generate_3D, inputs=[prompt, model, scale], outputs=[model_3d, model_gif, file_out])
295
+
296
+ block.launch(show_api=False)
images/fantasy_world.png ADDED
images/mirage.png ADDED
images/pumpkin.png ADDED
point_e_model_cache/ViT-L-14.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b8cca3fd41ae0c99ba7e8951adf17d267cdb84cd88be6f7c2e0eca1737a03836
3
+ size 932768134
point_e_model_cache/base_1b.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7db9afee292de4b00375c1d31f9722658cafcae4aefa51cb878bd5a8e34dc471
3
+ size 4977344725
point_e_model_cache/base_1b.pt.lock ADDED
File without changes
point_e_model_cache/base_300m.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9e624b54a24cd2cf01dd2abcd8a60afd28f62876b17d1b6d9b334ff488a4bbec
3
+ size 1247211041
point_e_model_cache/base_300m.pt.lock ADDED
File without changes
point_e_model_cache/base_40m.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8fa7cc025b08e13f5b5c622ea8f7dcdaa8a29bfbe069438f8e171db82826963b
3
+ size 161918529
point_e_model_cache/base_40m.pt.lock ADDED
File without changes
point_e_model_cache/base_40m_textvec.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c01c13df8f2f6ebdc4daf360625350a3715e7cd3ed4ac93e577f9f1958bfccc4
3
+ size 161385413
point_e_model_cache/base_40m_textvec.pt.lock ADDED
File without changes
point_e_model_cache/sdf.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:fb57517e81dfc8ecb78d4ab8a75175cd27a6b0cf399800da751cc651add94d30
3
+ size 37988721
point_e_model_cache/sdf.pt.lock ADDED
File without changes
point_e_model_cache/stable-diffusion-2-1 ADDED
@@ -0,0 +1 @@
 
 
1
+ Subproject commit 20894417d46f63722c24c620b03b9ea058c31270
point_e_model_cache/upsample_40m.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:07881c369ee0bef1a45b8ff1f464626a099a6023eef4197e4a445f5dce37ed20
3
+ size 161934137
point_e_model_cache/upsample_40m.pt.lock ADDED
File without changes
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ git+https://github.com/openai/point-e@main
2
+ trimesh
3
+ diffusers
4
+ transformers
5
+ accelerate
6
+ imageio[ffmpeg]
7
+ imageio[pyav]