-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Video summary support #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
sounds good. i look forward to that 😄 |
@dandelionmane @falcondai @jart I'd be willing to build it as part of #130, if @falcondai doesn't mind. I think my project should be split into two pieces - the piece that generates the frames, and the summary piece that streams frames to TensorBoard. |
@chrisranderson i originally planned to implement the video summaries as GIF's: I have experience doing that from a related project tensorflow/models#553. I thought of the alternative of showing the videos as full-blown HTML5-standard videos (i assume that is what you have in mind) but decided it is less desirable. My reasons:
That said, i can see the merit of a full-blown video playback being useful (in video segmentation and long video prediction?). and the playback controls associated with video formats are useful in these cases. I wonder what other people think. It might be worth implementing both and let end-users choose whichever it is more appropriate for their usage. what do you think @dandelionmane? in any case, help is more than welcome! |
I have no objection to having a "gif dashboard" plugin and a "streaming video dashboard" plugin. They do seem like they satisfy potentially different usecases, and the more plugins the merrier, imo. |
out of curiosity, how would the tensorboard UI change to accommodate many plugins? i imagine that only showing the ones being used would be great (up to now a few tabs on mine are always empty). |
Check out #181 from @wchargin! It makes it only display active plugins. We'll still need to change it if people start to have many active plugins at the same time, but we haven't reached that point yet. In the long term, I've thought about moving the plugin list to the left side, and having it expand/collapse using a hamburger pullout style menu. That way, if the number of plugins is large, you can scroll in the list. (When the pullout menu is retracted, each plugin would show a small icon representation, so if you remember the icons, you can switch plugins without pulling out the menu, and save horizontal space.) |
sounds good! look forward to these UI changes. Sorry to digress (further) from the original issue: is mobile support on the feature timeline? i sometimes found myself using TB on my phone on-the-go. Honestly it works okay as is for inspecting a chart or two, but i think just a little CSS-fu responsive design will significantly improve it. |
Mobile support isn't on the feature timeline, but if you want to take a stab at CSS-fu, we'll be happy to review the pull request :) |
Is the video summary feature still on the table? I think an important use case is reinforcement learning. For example, being able to see a video of the current Cartpole policy would be very helpful. The video is typically at most 1 minute for many Gym environments. |
@miriaford You can, as of #613. There's an example on the README here of passing in an |
I would like to add to @miriaford 's comment. I also think it would be VERY useful for reinforcement learning (RL), just to control if the agent is actually learning something that makes sense. Like @miriaford says, these little GIFs are really short. In my case (playing VizDoom), at most a couple of hundred of stacks. Most often they are also low resolution (84x84) and single channel. @chrisranderson your tool looks awesome, I will definitely try it out some day. But it looks a little overkill for the "quick and dirty" diagnosis of RL agents. I was wondering. Instead of an additional plugin, wouldn't it be more straightforward to just add GIF support to the already existing and excellent Image tab? What would be the main constrains then? Many thanks to anyone working on this (these) feature(s)! |
@chrisranderson This looks nice. Is there a way to write these summaries from within the graph, something like a |
I'm not sure why this hasn't been mentioned before, but I just noticed that TensorBoard's image plugin has supported GIFs all along. What's missing is an out-of-the-box way to add GIF summaries with TF. Currently, it's not possible to do that because it lacks a GIF encoder and
|
Thanks @alexlee-gk! I have simplified the interface to match the standard summary ops below.
|
That's neat! For the encoding of the GIF, I'd like to suggest to directly use ffmpeg instead of moviepy by using the |
Still waiting for the tensorboard video and very excited. Till then if there is anyone wanting to read about tensorboard can follow this link - https://data-flair.training/blogs/tensorboard-tutorial/ |
I also wrote gif summaries for the new summary API. Here are self-contained colabs that uses gif summaries for the original summary API and the summary API v2. Original summary API: Summary API v2: |
The original ffmpeg command was dropping some frames for gifs that had more than a certain number of frames. This would only happen under certain circumstances (e.g. only in some machines I tried). The dropping issue is fixed by adding |
@alexlee-gk Is there a way to use this for tf2, which is in eager mode. |
The summary api v2 works for me in 1.14 in eager mode |
This is a simple adaptation of the @alexlee-gk's original code, but for TF2.x. Demo collab: https://colab.research.google.com/drive/1ut0eJJ3pLjJYrgqVfz2QG69JnKA_2wQO CodeAs earlier in the comments, this uses import tempfile
import moviepy.editor as mpy
import os
import tensorflow as tf
def encode_gif_bytes(im_thwc, fps=4):
with tempfile.NamedTemporaryFile() as f: fname = f.name + '.gif'
clip = mpy.ImageSequenceClip(list(im_thwc), fps=fps)
clip.write_gif(fname, verbose=False, progress_bar=False)
with open(fname, 'rb') as f: enc_gif = f.read()
os.remove(fname)
return enc_gif
def gif_summary(im_thwc, fps=4):
"""
Given a 4D numpy tensor of images (TxHxWxC), encode a gif into a Summary protobuf.
NOTE: Tensor must be in the range [0, 255] as opposed to the usual small float values.
"""
# create a tensorflow image summary protobuf:
thwc = im_thwc.shape
im_summ = tf.compat.v1.Summary.Image()
im_summ.height = thwc[1]
im_summ.width = thwc[2]
im_summ.colorspace = 3 # fix to 3 for RGB
im_summ.encoded_image_string = encode_gif_bytes(im_thwc, fps)
# create a serialized summary obj:
summ = tf.compat.v1.Summary()
summ.value.add(image=im_summ)
return summ.SerializeToString() UsageThe summary object can be used with the new summary writer as follows: # Tensorboard boilerplate
from tensorflow import summary
import numpy as np
import datetime
current_time = str(datetime.datetime.now().timestamp())
log_dir = 'logs/tensorboard/' + current_time
summary_writer = summary.create_file_writer(log_dir)
# Here I'll make T=48 frames of greyscale noise. Any tensor of
# shape TxHxWxC with pixel values in range [0, 255] will work.
gif_tensor = np.random.random((48, 100, 100, 1))
gif_tensor = gif_tensor * 255
# Just call gif_summary and pass it to the summary you imported
gif = gif_summary(gif_tensor, fps=24)
with summary_writer.as_default():
# Optionally pass step and name
summary.experimental.write_raw_pb(gif, step=1, name='wow gifs') |
I also wrote a cleaned-up TF 2 version of Alex' GIF summary a few days ago. It works for both eager tensors, Numpy arrays, and with the note below also for graph tensors inside def video_summary(name, video, step=None, fps=20):
name = tf.constant(name).numpy().decode('utf-8')
video = np.array(video)
if video.dtype in (np.float32, np.float64):
video = np.clip(255 * video, 0, 255).astype(np.uint8)
B, T, H, W, C = video.shape
try:
frames = video.transpose((1, 2, 0, 3, 4)).reshape((T, H, B * W, C))
summary = tf.compat.v1.Summary()
image = tf.compat.v1.Summary.Image(height=B * H, width=T * W, colorspace=C)
image.encoded_image_string = encode_gif(frames, fps)
summary.value.add(tag=name + '/gif', image=image)
tf.summary.experimental.write_raw_pb(summary.SerializeToString(), step)
except (IOError, OSError) as e:
print('GIF summaries require ffmpeg in $PATH.', e)
frames = video.transpose((0, 2, 1, 3, 4)).reshape((1, B * H, T * W, C))
tf.summary.image(name + '/grid', frames, step)
def encode_gif(frames, fps):
from subprocess import Popen, PIPE
h, w, c = frames[0].shape
pxfmt = {1: 'gray', 3: 'rgb24'}[c]
cmd = ' '.join([
f'ffmpeg -y -f rawvideo -vcodec rawvideo',
f'-r {fps:.02f} -s {w}x{h} -pix_fmt {pxfmt} -i - -filter_complex',
f'[0:v]split[x][z];[z]palettegen[y];[x]fifo[x];[x][y]paletteuse',
f'-r {fps:.02f} -f gif -'])
proc = Popen(cmd.split(' '), stdin=PIPE, stdout=PIPE, stderr=PIPE)
for image in frames:
proc.stdin.write(image.tostring())
out, err = proc.communicate()
if proc.returncode:
raise IOError('\n'.join([' '.join(cmd), err.decode('utf8')]))
del proc
return out If you want to use it inside @tf.function
def foo():
# ...
robust_video_summary(writer, 'name', video)
# ...
def robust_video_summary(writer, name, video):
step = tf.summary.experimental.get_step()
def inner(name, video):
if step is not None:
tf.summary.experimental.set_step(step)
with writer.as_default():
video_summary(name, video)
return tf.py_function(inner, args, []) @alextp What do you think about adding something like this to |
@nfelt I think we should add this; WDYT? |
Any update on this? |
No; we’ll post here if there’s an update. |
Okay, thanks! Looking forward to this. |
Doing reinforcement learning, it would be great to have it and be able to see video from last evaluation in tensorboard. |
I tried encoding to a GIF, following code from tensorboardX: https://github.com/pytorch/pytorch/blob/1152726febfb034b12235fd044345a417a0f1607/torch/utils/tensorboard/summary.py#L652. However, this uses the raw summary proto from tensorflow 1, and functions in the SummaryWriter which are no longer supported in TF2, and other libraries which import it like Flax. Is there a new recommended way to do this? |
After 8 years of waiting, I've given up on TensorBoard and wrote my own with video support: github.com/danijar/scope |
We were looking for something similar. We were working to get a video plugin setup to use with Tensorboard and a summary writer in PyTorch. This repository has the work we did to record and display MP4s. The repository is split up into two parts. The PyTorch part which writes summaries to the event file and the Tensorboard part which displays the video. Sorry it is incomplete, but it works for our purposes. Perhaps somebody could take the logic from here and implement it so that others can use the Tensorboard plugin (and the PyTorch summary writer that goes along with it) or make a pull request to the repository. |
Migrated from tensorflow/tensorflow#3936
@falcondai offered to implement it as a plugin. @falcondai, I think we are almost at the point where we're ready to accept a plugin like that. Give us a few more weeks to clean up the plugin API and get some good examples you can work off of.
The text was updated successfully, but these errors were encountered: