Skip to content

Instantly share code, notes, and snippets.

@cormoran
Created January 7, 2019 21:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cormoran/c820b398a5b068bb1812838ebb488d0a to your computer and use it in GitHub Desktop.
Save cormoran/c820b398a5b068bb1812838ebb488d0a to your computer and use it in GitHub Desktop.
tensorboard(X) のログから gif 画像を作るスクリプト
'''
references:
https://github.com/lanpa/tensorboardX/blob/master/tensorboardX/event_file_writer.py
'''
import struct
from tensorboardX.crc32c import crc32c
from tensorboardX.record_writer import masked_crc32c
from tensorboardX.proto.event_pb2 import Event
class RecordReader():
def __init__(self, path):
self.path = path
self._reader = open(path, 'rb')
def read(self):
length_b = self._reader.read(8)
if len(length_b) == 0:
raise EOFError()
length = struct.unpack('Q', length_b)[0]
length_masked_crc32c_b = self._reader.read(4)
length_masked_crc32c = struct.unpack('I', length_masked_crc32c_b)[0]
assert length_masked_crc32c == masked_crc32c(length_b), 'length crc32c'
event_str = self._reader.read(length)
event_masked_crc32c_b = self._reader.read(4)
event_masked_crc32c = struct.unpack('I', event_masked_crc32c_b)[0]
assert event_masked_crc32c == masked_crc32c(event_str), 'event crc32c'
res = Event()
res.ParseFromString(event_str)
return res
def close(self):
self._reader.close()
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.close()
def __iter__(self):
return self
def __next__(self):
try:
return self.read()
except EOFError:
raise StopIteration()
import os
from argparse import ArgumentParser
from record_reader import RecordReader
from tensorboardX import FileWriter
from PIL import Image, ImageDraw
import io
parser = ArgumentParser()
parser.add_argument('src', type=str, help='path to event file')
parser.add_argument('tag', type=str, help='tag name of image')
parser.add_argument('--output', type=str, default='out.gif')
parser.add_argument('--keep_freq', type=str, default='5', help='ex) 5,8 then epoch 5n and 8n will be kept')
parser.add_argument('--keep_epoch', type=str, default=None, help='ex) 5,8 then epoch 5 and 8 will be kept')
parser.add_argument('--duration', type=int, default=500, help='ms')
args = parser.parse_args()
args.keep_freq = list(map(int, args.keep_freq.split(',')))
args.keep_epoch = list(map(int, args.keep_epoch.split(','))) if args.keep_epoch else []
images = []
reader = RecordReader(args.src)
for event in reader:
save = False
save = save or any([event.step % freq == 0 for freq in args.keep_freq])
save = save or event.step in args.keep_epoch
save = save and (len(event.summary.value) > 0 and event.summary.value[0].WhichOneof('value') == 'image')
save = save and event.summary.value[0].tag == args.tag
if not save:
continue
image = event.summary.value[0].image
image = Image.open(io.BytesIO(image.encoded_image_string))
# 画像に epoch を表示する
draw = ImageDraw.Draw(image)
draw.text((5, 5), 'step {}'.format(event.step), fill=128)
images.append(image)
#
print('{:5}'.format(len(images)), end='\r')
reader.close()
# gif 生成
images[0].save(args.output, save_all=True, append_images=images[1:], duration=args.duration, loop=0)
print('generated gif from {} images.'.format(len(images)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment