diff --git a/tensorboard/plugins/mesh/BUILD b/tensorboard/plugins/mesh/BUILD index bc5df8a387..0dff55c01d 100644 --- a/tensorboard/plugins/mesh/BUILD +++ b/tensorboard/plugins/mesh/BUILD @@ -169,20 +169,9 @@ py_test( py_binary( name = "mesh_demo", srcs = ["mesh_demo.py"], - srcs_version = "PY3", - deps = [ - ":demo_utils", - ":summary", - "//tensorboard:expect_absl_app_installed", - "//tensorboard:expect_absl_flags_installed", - "//tensorboard:expect_numpy_installed", - "//tensorboard:expect_tensorflow_installed", + data = [ + ":test_data", ], -) - -py_binary( - name = "mesh_demo_v2", - srcs = ["mesh_demo_v2.py"], srcs_version = "PY3", deps = [ ":demo_utils", diff --git a/tensorboard/plugins/mesh/README.md b/tensorboard/plugins/mesh/README.md index 9de1fe78a4..b622273c29 100644 --- a/tensorboard/plugins/mesh/README.md +++ b/tensorboard/plugins/mesh/README.md @@ -27,13 +27,13 @@ and some colors associated with each point. Check out a simple example with static mesh: ```python -from tensorboard.plugins.mesh import summary as mesh_summary +from tensorboard.plugins.mesh import summary_v2 as mesh_summary ... point_cloud = tf.constant([[[0.19, 0.78, 0.02], ...]], shape=[1, 1064, 3]) point_colors = tf.constant([[[128, 104, 227], ...]], shape=[1, 1064, 3]) -summary = mesh_summary.op('point_cloud', vertices=point_cloud, colors=point_colors) +summary = mesh_summary.mesh('point_cloud', vertices=point_cloud, colors=point_colors) ``` **NOTE:** The `colors` tensor is optional in this case but can be useful to @@ -43,14 +43,14 @@ A mesh can be represented by a point cloud together with a set of faces, where each face is represented by a list of indices of vertices in clockwise order around the face. This plugin currently only supports triangular faces. Construct a mesh by including the `faces` parameter to -`mesh_summary.op`: +`mesh_summary.mesh`: ```python mesh = tf.constant([[[0.19, 0.78, 0.02], ...]], shape=[1, 1064, 3]) colors = tf.constant([[[128, 104, 227], ...]], shape=[1, 1064, 3]) faces = tf.constant([[[13, 78, 54], ...]], shape=[1, 752, 3]) -summary = mesh_summary.op('mesh', vertices=mesh, colors=colors, faces=faces) +summary = mesh_summary.mesh('mesh', vertices=mesh, colors=colors, faces=faces) ``` The `colors` tensor is optional for mesh summaries. @@ -66,7 +66,7 @@ representing a valid [THREE.js](https://threejs.org) class name. ```python camera_config = {'cls': 'PerspectiveCamera'} -summary = mesh_summary.op( +summary = mesh_summary.mesh( "mesh", vertices=mesh, colors=colors, diff --git a/tensorboard/plugins/mesh/mesh_demo.py b/tensorboard/plugins/mesh/mesh_demo.py index 4a095821f4..fea67da8fe 100644 --- a/tensorboard/plugins/mesh/mesh_demo.py +++ b/tensorboard/plugins/mesh/mesh_demo.py @@ -14,86 +14,69 @@ # ============================================================================== """Simple demo which displays constant 3D mesh.""" - from absl import app from absl import flags import numpy as np import tensorflow as tf -from tensorboard.plugins.mesh import summary as mesh_summary +from tensorboard.plugins.mesh import summary_v2 as mesh_summary from tensorboard.plugins.mesh import demo_utils + flags.DEFINE_string( "logdir", "/tmp/mesh_demo", "Directory to write event logs to." ) -flags.DEFINE_string("mesh_path", None, "Path to PLY file to visualize.") FLAGS = flags.FLAGS -tf.compat.v1.disable_v2_behavior() - # Max number of steps to run training with. _MAX_STEPS = 10 +DEMO_PLY_MESH_PATH = "tensorboard/plugins/mesh/test_data/icosphere.ply" + + +def train_step(vertices, faces, colors, config_dict, step): + """Executes summary as a train step.""" + # Change colors over time. + t = float(step) / _MAX_STEPS + transformed_colors = t * (255 - colors) + (1 - t) * colors + mesh_summary.mesh( + "mesh_color_tensor", + vertices=vertices, + faces=faces, + colors=transformed_colors, + config_dict=config_dict, + step=step, + ) + def run(): - """Runs session with a mesh summary.""" - # Mesh summaries only work on TensorFlow 1.x. - if int(tf.__version__.split(".")[0]) > 1: - raise ImportError("TensorFlow 1.x is required to run this demo.") - # Flag mesh_path is required. - if FLAGS.mesh_path is None: - raise ValueError( - "Flag --mesh_path is required and must contain path to PLY file." - ) + """Runs training steps with a mesh summary.""" # Camera and scene configuration. config_dict = {"camera": {"cls": "PerspectiveCamera", "fov": 75}} # Read sample PLY file. - vertices, colors, faces = demo_utils.read_ascii_ply(FLAGS.mesh_path) + vertices, colors, faces = demo_utils.read_ascii_ply(DEMO_PLY_MESH_PATH) # Add batch dimension. vertices = np.expand_dims(vertices, 0) faces = np.expand_dims(faces, 0) colors = np.expand_dims(colors, 0) - # Create placeholders for tensors representing the mesh. - step = tf.placeholder(tf.int32, ()) - vertices_tensor = tf.placeholder(tf.float32, vertices.shape) - faces_tensor = tf.placeholder(tf.int32, faces.shape) - colors_tensor = tf.placeholder(tf.int32, colors.shape) + # Create summary writer. + writer = tf.summary.create_file_writer(FLAGS.logdir) - # Change colors over time. - t = tf.cast(step, tf.float32) / _MAX_STEPS - transformed_colors = t * (255 - colors) + (1 - t) * colors - - meshes_summary = mesh_summary.op( - "mesh_color_tensor", - vertices=vertices_tensor, - faces=faces_tensor, - colors=transformed_colors, - config_dict=config_dict, - ) - - # Create summary writer and session. - writer = tf.summary.FileWriter(FLAGS.logdir) - sess = tf.Session() - - for i in range(_MAX_STEPS): - summary = sess.run( - meshes_summary, - feed_dict={ - vertices_tensor: vertices, - faces_tensor: faces, - colors_tensor: colors, - step: i, - }, - ) - writer.add_summary(summary, global_step=i) + with writer.as_default(): + for step in range(_MAX_STEPS): + train_step(vertices, faces, colors, config_dict, step) def main(unused_argv): print("Saving output to %s." % FLAGS.logdir) + print( + "To view results in your browser, run `tensorboard --logdir %s`" + % FLAGS.logdir + ) run() print("Done. Output saved to %s." % FLAGS.logdir) diff --git a/tensorboard/plugins/mesh/mesh_demo_v2.py b/tensorboard/plugins/mesh/mesh_demo_v2.py deleted file mode 100644 index 48135a7cb7..0000000000 --- a/tensorboard/plugins/mesh/mesh_demo_v2.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright 2019 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Simple demo which displays constant 3D mesh.""" - - -from absl import app -from absl import flags -import numpy as np -import tensorflow.compat.v2 as tf - -from tensorboard.plugins.mesh import summary_v2 as mesh_summary -from tensorboard.plugins.mesh import demo_utils - - -flags.DEFINE_string( - "logdir", "/tmp/mesh_demo", "Directory to write event logs to." -) -flags.DEFINE_string("mesh_path", None, "Path to PLY file to visualize.") - -FLAGS = flags.FLAGS - -tf.enable_v2_behavior() - -# Max number of steps to run training with. -_MAX_STEPS = 10 - - -def train_step(vertices, faces, colors, config_dict, step): - """Executes summary as a train step.""" - # Change colors over time. - t = float(step) / _MAX_STEPS - transformed_colors = t * (255 - colors) + (1 - t) * colors - mesh_summary.mesh( - "mesh_color_tensor", - vertices=vertices, - faces=faces, - colors=transformed_colors, - config_dict=config_dict, - step=step, - ) - - -def run(): - """Runs training steps with a mesh summary.""" - # Mesh summaries only work on TensorFlow 2.x. - if int(tf.__version__.split(".")[0]) < 1: - raise ImportError("TensorFlow 2.x is required to run this demo.") - # Flag mesh_path is required. - if FLAGS.mesh_path is None: - raise ValueError( - "Flag --mesh_path is required and must contain path to PLY file." - ) - # Camera and scene configuration. - config_dict = {"camera": {"cls": "PerspectiveCamera", "fov": 75}} - - # Read sample PLY file. - vertices, colors, faces = demo_utils.read_ascii_ply(FLAGS.mesh_path) - - # Add batch dimension. - vertices = np.expand_dims(vertices, 0) - faces = np.expand_dims(faces, 0) - colors = np.expand_dims(colors, 0) - - # Create summary writer. - writer = tf.summary.create_file_writer(FLAGS.logdir) - - with writer.as_default(): - for step in range(_MAX_STEPS): - train_step(vertices, faces, colors, config_dict, step) - - -def main(unused_argv): - print("Saving output to %s." % FLAGS.logdir) - run() - print("Done. Output saved to %s." % FLAGS.logdir) - - -if __name__ == "__main__": - app.run(main) diff --git a/tensorboard/plugins/mesh/summary.py b/tensorboard/plugins/mesh/summary.py index 55fb43f268..a21438290e 100644 --- a/tensorboard/plugins/mesh/summary.py +++ b/tensorboard/plugins/mesh/summary.py @@ -12,7 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Mesh summaries and TensorFlow operations to create them.""" +"""Mesh summaries and TensorFlow operations to create them. + +This file is deprecated. See `summary_v2.py` instead. +""" import json import tensorflow as tf @@ -105,6 +108,8 @@ def op( ): """Creates a TensorFlow summary op for mesh rendering. + DEPRECATED: see `summary_v2.py` instead. + Args: name: A name for this summary operation. vertices: Tensor of shape `[dim_1, ..., dim_n, 3]` representing the 3D @@ -179,6 +184,8 @@ def pb( ): """Create a mesh summary to save in pb format. + DEPRECATED: see `summary_v2.py` instead. + Args: name: A name for this summary operation. vertices: numpy array of shape `[dim_1, ..., dim_n, 3]` representing the 3D