CoolFace
Apppublic

MirageML/point-e

sourceHugging Facecreativeml-openrail-mupdated 4y agoView on Hugging Face
37likes
app.py297 linesDownload Raw Back to root
1import os2import gradio as gr3from PIL import Image4import torch5import matplotlib.pyplot as plt6import imageio7import numpy as np8import argparse9 10from point_e.diffusion.configs import DIFFUSION_CONFIGS, diffusion_from_config11from point_e.diffusion.sampler import PointCloudSampler12from point_e.models.download import load_checkpoint13from point_e.models.configs import MODEL_CONFIGS, model_from_config14from point_e.util.plotting import plot_point_cloud15from point_e.util.pc_to_mesh import marching_cubes_mesh16 17from diffusers import StableDiffusionPipeline18 19import trimesh20 21 22state = ""23device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')24 25css = '''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 32def set_state(s):33    print(s)34    global state35    state = s36 37def get_state():38    return state39 40def load_img2mesh_model(model_name):41    set_state(f'Creating img2mesh model {model_name}...')42    i2m_name = model_name43    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_i2m51 52 53 54def 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 85def 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 image91 92def 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 prompt106    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 = None111    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 = x114 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 125def prepare_img(img):126 127    w, h = img.size128    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 256x256134    img = img.resize((256, 256))135 136    return img137 138 139def ply_to_glb(ply_file, glb_file):140    mesh = trimesh.load(ply_file)141 142    # Save the mesh as a glb file using Trimesh143    mesh.export(glb_file, file_type='glb')144 145    return glb_file146 147def 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 evals162        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 169def 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 frames175    frames = []176 177    # Create a loop to generate the frames for the GIF178    for angle in range(0, 360, 4):179        # Clear the plot and plot the point cloud180        ax.clear()181        color_args = np.stack(182            [pc.channels["R"], pc.channels["G"], pc.channels["B"]], axis=-1183        )184        c = pc.coords185 186 187        ax.scatter(c[:, 0], c[:, 1], c[:, 2], c=color_args)188 189        # Set the viewpoint for the plot190        ax.view_init(elev=10, azim=angle)191 192        # Turn off the axis labels and ticks193        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 data199        fig.canvas.draw()200 201        # Save the plot as a frame for the GIF202        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 imageio209    imageio.mimsave('/tmp/pointcloud.mp4', frames, fps=30)210    return '/tmp/pointcloud.mp4'211 212block = gr.Blocks().queue(max_size=250, concurrency_count=6)213with 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 UI224                    </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> implementation232                </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 UI246                        </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> implementation254                    </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.1273                )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=True291        )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 296block.launch(show_api=False)297