forked from DLR-RM/BlenderProc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Hdf5Writer.py
115 lines (91 loc) · 5.24 KB
/
Hdf5Writer.py
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
import os
import bpy
import h5py
import numpy as np
from src.writer.WriterInterface import WriterInterface
from src.utility.Utility import Utility
class Hdf5Writer(WriterInterface):
""" For each key frame merges all registered output files into one hdf5 file
**Configuration**:
.. csv-table::
:header: "Parameter", "Description"
"append_to_existing_output", "If true, the names of the output hdf5 files will be chosen in a way such that "
"there are no collisions with already existing hdf5 files in the output directory. "
"Type: bool. Default: False"
"compression", "The compression technique that should be used when storing data in a hdf5 file. Type: string."
"delete_temporary_files_afterwards", "True, if all temporary files should be deleted after merging. "
"Type: bool. Default value: True."
"stereo_separate_keys", "If true, stereo images are saved as two separate images *_0 and *_1. Type: bool. "
"Default: False (stereo images are combined into one np.array (2, ...))."
"avoid_rendering", "If true, exit. Type: bool. Default: False."
"""
def __init__(self, config):
WriterInterface.__init__(self, config)
self._avoid_rendering = config.get_bool("avoid_rendering", False)
def run(self):
if self._avoid_rendering:
print("Avoid rendering is on, no output produced!")
return
if self.config.get_bool("append_to_existing_output", False):
frame_offset = 0
# Look for hdf5 file with highest index
for path in os.listdir(self._determine_output_dir(False)):
if path.endswith(".hdf5"):
index = path[:-len(".hdf5")]
if index.isdigit():
frame_offset = max(frame_offset, int(index) + 1)
else:
frame_offset = 0
# Go through all frames
for frame in range(bpy.context.scene.frame_start, bpy.context.scene.frame_end):
# Create output hdf5 file
hdf5_path = os.path.join(self._determine_output_dir(False), str(frame + frame_offset) + ".hdf5")
with h5py.File(hdf5_path, "w") as f:
if 'output' not in bpy.context.scene:
print("No output was designed in prior models!")
return
# Go through all the output types
print("Merging data for frame " + str(frame) + " into " + hdf5_path)
for output_type in bpy.context.scene["output"]:
use_stereo = output_type["stereo"]
# Build path (path attribute is format string)
file_path = output_type["path"]
if '%' in file_path:
file_path = file_path % frame
if use_stereo:
path_l, path_r = self._get_stereo_path_pair(file_path)
img_l, new_key, new_version = self._load_and_postprocess(path_l, output_type["key"],
output_type["version"])
img_r, new_key, new_version = self._load_and_postprocess(path_r, output_type["key"],
output_type["version"])
if self.config.get_bool("stereo_separate_keys", False):
self._write_to_hdf_file(f, new_key + "_0", img_l)
self._write_to_hdf_file(f, new_key + "_1", img_r)
else:
data = np.array([img_l, img_r])
self._write_to_hdf_file(f, new_key, data)
else:
data, new_key, new_version = self._load_and_postprocess(file_path, output_type["key"],
output_type["version"])
self._write_to_hdf_file(f, new_key, data)
self._write_to_hdf_file(f, new_key + "_version", np.string_([new_version]))
def _write_to_hdf_file(self, file, key, data):
""" Adds the given data as a new entry to the given hdf5 file.
:param file: The hdf5 file handle.
:param key: The key at which the data should be stored in the hdf5 file. Type: string.
:param data: The data to store.
"""
if data.dtype.char == 'S':
file.create_dataset(key, data=data, dtype=data.dtype)
else:
file.create_dataset(key, data=data, compression=self.config.get_string("compression", 'gzip'))
def _get_stereo_path_pair(self, file_path):
"""
Returns stereoscopic file path pair for a given "normal" image file path.
:param file_path: The file path of a single image. Type: string.
:return: The pair of file paths corresponding to the stereo images,
"""
path_split = file_path.split(".")
path_l = "{}_L.{}".format(path_split[0], path_split[1])
path_r = "{}_R.{}".format(path_split[0], path_split[1])
return path_l, path_r