File: tensorboard_pytorch.py

package info (click to toggle)
open3d 0.19.0-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 83,496 kB
  • sloc: cpp: 206,543; python: 27,254; ansic: 8,356; javascript: 1,883; sh: 1,527; makefile: 259; xml: 69
file content (187 lines) | stat: -rw-r--r-- 7,844 bytes parent folder | download | duplicates (2)
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# ----------------------------------------------------------------------------
# -                        Open3D: www.open3d.org                            -
# ----------------------------------------------------------------------------
# Copyright (c) 2018-2024 www.open3d.org
# SPDX-License-Identifier: MIT
# ----------------------------------------------------------------------------
import copy
from os.path import exists, join, dirname, basename, splitext
import sys
import numpy as np
import open3d as o3d
# pylint: disable-next=unused-import
from open3d.visualization.tensorboard_plugin import summary  # noqa
from open3d.visualization.tensorboard_plugin.util import to_dict_batch
from torch.utils.tensorboard import SummaryWriter

BASE_LOGDIR = "demo_logs/pytorch/"
MODEL_PATH = o3d.data.MonkeyModel().path


def small_scale(run_name="small_scale"):
    """Basic demo with cube and cylinder with normals and colors.
    """
    logdir = join(BASE_LOGDIR, run_name)
    writer = SummaryWriter(logdir)

    cube = o3d.geometry.TriangleMesh.create_box(1, 2, 4, create_uv_map=True)
    cube.compute_vertex_normals()
    cylinder = o3d.geometry.TriangleMesh.create_cylinder(radius=1.0,
                                                         height=2.0,
                                                         resolution=20,
                                                         split=4,
                                                         create_uv_map=True)
    cylinder.compute_vertex_normals()
    colors = [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0)]
    for step in range(3):
        cube.paint_uniform_color(colors[step])
        writer.add_3d('cube', to_dict_batch([cube]), step=step)
        cylinder.paint_uniform_color(colors[step])
        writer.add_3d('cylinder', to_dict_batch([cylinder]), step=step)


def property_reference(run_name="property_reference"):
    """Produces identical visualization to small_scale, but does not store
    repeated properties of ``vertex_positions`` and ``vertex_normals``.
    """
    logdir = join(BASE_LOGDIR, run_name)
    writer = SummaryWriter(logdir)

    cube = o3d.geometry.TriangleMesh.create_box(1, 2, 4, create_uv_map=True)
    cube.compute_vertex_normals()
    cylinder = o3d.geometry.TriangleMesh.create_cylinder(radius=1.0,
                                                         height=2.0,
                                                         resolution=20,
                                                         split=4,
                                                         create_uv_map=True)
    cylinder.compute_vertex_normals()
    colors = [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0)]
    for step in range(3):
        cube.paint_uniform_color(colors[step])
        cube_summary = to_dict_batch([cube])
        if step > 0:
            cube_summary['vertex_positions'] = 0
            cube_summary['vertex_normals'] = 0
        writer.add_3d('cube', cube_summary, step=step)
        cylinder.paint_uniform_color(colors[step])
        cylinder_summary = to_dict_batch([cylinder])
        if step > 0:
            cylinder_summary['vertex_positions'] = 0
            cylinder_summary['vertex_normals'] = 0
        writer.add_3d('cylinder', cylinder_summary, step=step)


def large_scale(n_steps=16,
                batch_size=1,
                base_resolution=200,
                run_name="large_scale"):
    """Generate a large scale summary. Geometry resolution increases linearly
    with step. Each element in a batch is painted a different color.
    """
    logdir = join(BASE_LOGDIR, run_name)
    writer = SummaryWriter(logdir)
    colors = []
    for k in range(batch_size):
        t = k * np.pi / batch_size
        colors.append(((1 + np.sin(t)) / 2, (1 + np.cos(t)) / 2, t / np.pi))
    for step in range(n_steps):
        resolution = base_resolution * (step + 1)
        cylinder_list = []
        mobius_list = []
        cylinder = o3d.geometry.TriangleMesh.create_cylinder(
            radius=1.0, height=2.0, resolution=resolution, split=4)
        cylinder.compute_vertex_normals()
        mobius = o3d.geometry.TriangleMesh.create_mobius(
            length_split=int(3.5 * resolution),
            width_split=int(0.75 * resolution),
            twists=1,
            raidus=1,
            flatness=1,
            width=1,
            scale=1)
        mobius.compute_vertex_normals()
        for b in range(batch_size):
            cylinder_list.append(copy.deepcopy(cylinder))
            cylinder_list[b].paint_uniform_color(colors[b])
            mobius_list.append(copy.deepcopy(mobius))
            mobius_list[b].paint_uniform_color(colors[b])
        writer.add_3d('cylinder',
                      to_dict_batch(cylinder_list),
                      step=step,
                      max_outputs=batch_size)
        writer.add_3d('mobius',
                      to_dict_batch(mobius_list),
                      step=step,
                      max_outputs=batch_size)


def with_material(model_path=MODEL_PATH):
    """Read an obj model from a directory and write as a TensorBoard summary.
    """
    model_dir = dirname(model_path)
    model_name = splitext(basename(model_path))[0]
    logdir = join(BASE_LOGDIR, model_name)
    model = o3d.t.io.read_triangle_mesh(model_path)
    summary_3d = {
        "vertex_positions": model.vertex.positions,
        "vertex_normals": model.vertex.normals,
        "triangle_texture_uvs": model.triangle["texture_uvs"],
        "triangle_indices": model.triangle.indices,
        "material_name": "defaultLit"
    }
    names_to_o3dprop = {"ao": "ambient_occlusion"}

    for texture in ("albedo", "normal", "ao", "metallic", "roughness"):
        texture_file = join(model_dir, texture + ".png")
        if exists(texture_file):
            texture = names_to_o3dprop.get(texture, texture)
            summary_3d.update({
                ("material_texture_map_" + texture):
                    o3d.t.io.read_image(texture_file)
            })
            if texture == "metallic":
                summary_3d.update(material_scalar_metallic=1.0)

    writer = SummaryWriter(logdir)
    writer.add_3d(model_name, summary_3d, step=0)


def demo_scene():
    """Write the demo_scene.py example showing rich PBR materials as a summary.
    """
    import demo_scene
    geoms = demo_scene.create_scene()
    writer = SummaryWriter(join(BASE_LOGDIR, 'demo_scene'))
    for geom_data in geoms:
        geom = geom_data["geometry"]
        summary_3d = {}
        for key, tensor in geom.vertex.items():
            summary_3d["vertex_" + key] = tensor
        for key, tensor in geom.triangle.items():
            summary_3d["triangle_" + key] = tensor
        if geom.has_valid_material():
            summary_3d["material_name"] = geom.material.material_name
            for key, value in geom.material.scalar_properties.items():
                summary_3d["material_scalar_" + key] = value
            for key, value in geom.material.vector_properties.items():
                summary_3d["material_vector_" + key] = value
            for key, value in geom.material.texture_maps.items():
                summary_3d["material_texture_map_" + key] = value
        writer.add_3d(geom_data["name"], summary_3d, step=0)


if __name__ == "__main__":

    examples = ('small_scale', 'large_scale', 'property_reference',
                'with_material', 'demo_scene')
    selected = tuple(eg for eg in sys.argv[1:] if eg in examples)
    if len(selected) == 0:
        print(f'Usage: python {__file__} EXAMPLE...')
        print(f'  where EXAMPLE are from {examples}')
        selected = ('property_reference', 'with_material')

    for eg in selected:
        locals()[eg]()

    print(f"Run 'tensorboard --logdir {BASE_LOGDIR}' to visualize the 3D "
          "summary.")