File size: 6,173 Bytes
f77687d
 
 
 
 
f9d3dcc
8fee2d3
f77687d
 
18eb0a8
f77687d
18eb0a8
4b7c5a5
8fee2d3
 
 
 
 
 
 
 
 
f9d3dcc
b46e8b2
8fee2d3
f77687d
 
4e10b60
8fee2d3
4e10b60
8fee2d3
 
 
 
 
 
 
 
4e10b60
8fee2d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4e10b60
8fee2d3
18eb0a8
 
 
 
f77687d
4e10b60
8fee2d3
4e10b60
 
8fee2d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4e10b60
 
 
8fee2d3
4e10b60
 
 
8fee2d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4e10b60
8fee2d3
f77687d
18eb0a8
8794cba
8fee2d3
 
 
 
 
8794cba
 
 
 
 
 
f77687d
a48ee33
64d4127
4e10b60
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python

from __future__ import annotations

import os
import datetime
import subprocess

import gradio as gr
import spaces


@spaces.GPU(duration=60 * 3)
def run_on_gpu(input_shape):
    print('Started inference at {}'.format(datetime.datetime.now()))
    call_base = ['python', 'ppsurf/pps.py', 'rec']
    call_args = ['pps.py',
                 'rec',
                 'data/{}'.format(input_shape),
                 'results/rec/{}'.format(input_shape),
                 ]
    res = subprocess.check_output(call_base + call_args)
    print('Finished inference at {}'.format(datetime.datetime.now()))

    return res


def main():
    description = '''# [PPSurf](https://github.com/cg-tuwien/ppsurf)
    
    Supported file formats: PLY, STL, OBJ and other mesh files, XYZ as whitespace-separated text file, 
    NPY and NPZ (key='arr_0'), LAS and LAZ (version 1.0-1.4), COPC and CRS.
    Best results for 50k-250k points. 
    
    This method is meant for scans of single and few objects. 
    Quality for scenes and landscapes will be lower.
    
    Inference takes about 2 minutes.
    '''

    def convert_to_ply(input_point_cloud_upload: gr.File):
        print('inputs:', input_point_cloud_upload.value)
        input_shape = input_point_cloud_upload.value[0]
        if not input_shape.endswith('.ply'):
            # load file
            from ppsurf.source.occupancy_data_module import OccupancyDataModule
            pts_np = OccupancyDataModule.load_pts(input_shape)

            # convert to ply
            import trimesh
            mesh = trimesh.Trimesh(vertices=pts_np[:, :3])
            input_shape = input_shape + '.ply'
            mesh.export(input_shape)

        # show in viewer
        input_tabs.selected = 'pc_viewer'
        input_point_cloud_viewer.value = input_shape

    if (SPACE_ID := os.getenv('SPACE_ID')) is not None:
        description += (f'\n<p>For faster inference without waiting in queue, '
                        f'you may duplicate the space and upgrade to GPU in settings. '
                        f'<a href="https://huggingface.co/spaces/{SPACE_ID}?duplicate=true">'
                        f'<img style="display: inline; margin-top: 0em; margin-bottom: 0em" '
                        f'src="https://bit.ly/3gLdBN6" alt="Duplicate Space" /></a></p>')

    with gr.Blocks(css='style.css') as demo:
        gr.Markdown(description)
        with gr.Row():
            with gr.Column():
                with gr.Tabs() as input_tabs:
                    with gr.TabItem(label='Input Point Cloud Upload', id='pc_upload'):
                        input_point_cloud_upload = gr.File(
                            show_label=False, file_count='single')
                        input_point_cloud_upload.upload(fn=convert_to_ply,
                        inputs=[
                            input_point_cloud_upload,
                        ],
                        outputs=[
                            # input_point_cloud_viewer,  # not available here
                        ])
                        # input_point_cloud_upload.attach_load_event(convert_to_ply, every=None)
                    with gr.TabItem(label='Input Point Cloud Viewer', id='pc_viewer'):
                        input_point_cloud_viewer = gr.Model3D(show_label=False)
                gen_resolution_global = gr.Slider(
                    label='Grid Resolution (larger for more details)',
                    minimum=17, maximum=513, value=129, step=2)
                padding_factor = gr.Slider(
                    label='Padding Factor (larger if object is cut off at boundaries)',
                    minimum=0, maximum=1.0, value=0.05, step=1)
                gen_subsample_manifold_iter = gr.Slider(
                    label='Subsample Manifold Iterations (larger for larger point clouds)',
                    minimum=3, maximum=30, value=10, step=1)
                gen_refine_iter = gr.Slider(
                    label='Edge Refinement Iterations (larger for more details)',
                    minimum=3, maximum=30, value=10, step=1)
                # run_button = gr.Button('Run')
            with gr.Column():
                progress_text = gr.Text(label='Progress')
                with gr.Tabs():
                    with gr.TabItem(label='Reconstructed 3D model'):
                        result_3d_model = gr.Model3D(show_label=False)
                    with gr.TabItem(label='Output mesh file'):
                        output_file = gr.File(show_label=False)
        # with gr.Row():
        #     examples = [
        #         ['shapes/dragon1.obj', 'a photo of a dragon', 0, 7.5],
        #         ['shapes/dragon2.obj', 'a photo of a dragon', 0, 7.5],
        #         ['shapes/eagle.obj', 'a photo of an eagle', 0, 7.5],
        #         ['shapes/napoleon.obj', 'a photo of Napoleon Bonaparte', 3, 7.5],
        #         ['shapes/nascar.obj', 'A next gen nascar', 2, 10],
        #     ]
        #     gr.Examples(examples=examples,
        #                 inputs=[
        #                     input_point_cloud_viewer,
        #                     text,
        #                     seed,
        #                     guidance_scale,
        #                 ],
        #                 outputs=[
        #                     result_3d_model,
        #                     output_file,
        #                 ],
        #                 cache_examples=False)

        with gr.Row():
            run_button = gr.Button('=> Run PPSurf =>')

        run_button.click(fn=run_on_gpu,
                         inputs=[
                             input_point_cloud_viewer,
                             gen_resolution_global,
                             padding_factor,
                             gen_subsample_manifold_iter,
                             gen_refine_iter,
                         ],
                         outputs=[
                             result_3d_model,
                             output_file,
                             progress_text,
                         ])

    demo.queue(max_size=5)
    demo.launch(debug=True)


if __name__ == '__main__':
    main()