def save_to_hdf5(output_dir_path: str, output_data_dict: Dict[str, List[np.ndarray]], append_to_existing_output: bool = False, stereo_separate_keys: bool = False): """ Saves the information provided inside of the output_data_dict into a .hdf5 container :param output_dir_path: The folder path in which the .hdf5 containers will be generated :param output_data_dict: The container, which keeps the different images, which should be saved to disc. Each key will be saved as its own key in the .hdf5 container. :param append_to_existing_output: If this is True, the output_dir_path folder will be scanned for pre-existing .hdf5 containers and the numbering of the newly added containers, will start right where the last run left off. :param stereo_separate_keys: If this is True and the rendering was done in stereo mode, than the stereo images won't be saved in one tensor [2, img_x, img_y, channels], where the img[0] is the left image and img[1] the right. They will be saved in separate keys: for example for colors in colors_0 and colors_1. """ if not os.path.exists(output_dir_path): os.makedirs(output_dir_path) amount_of_frames = 0 for data_block in output_data_dict.values(): if isinstance(data_block, list): amount_of_frames = max([amount_of_frames, len(data_block)]) # if append to existing output is turned on the existing folder is searched for the highest occurring # index, which is then used as starting point for this run if append_to_existing_output: frame_offset = 0 # Look for hdf5 file with highest index for path in os.listdir(output_dir_path): if path.endswith(".hdf5"): index = path[:-len(".hdf5")] if index.isdigit(): frame_offset = max(frame_offset, int(index) + 1) else: frame_offset = 0 if amount_of_frames != bpy.context.scene.frame_end - bpy.context.scene.frame_start: raise Exception( "The amount of images stored in the output_data_dict does not correspond with the amount" "of images specified by frame_start to frame_end.") for frame in range(bpy.context.scene.frame_start, bpy.context.scene.frame_end): # for each frame a new .hdf5 file is generated hdf5_path = os.path.join(output_dir_path, str(frame + frame_offset) + ".hdf5") with h5py.File(hdf5_path, "w") as file: # Go through all the output types print(f"Merging data for frame {frame} into {hdf5_path}") for key, data_block in output_data_dict.items(): if frame < len(data_block): # get the current data block for the current frame used_data_block = data_block[frame] if stereo_separate_keys and ( bpy.context.scene.render.use_multiview or used_data_block.shape[0] == 2): # stereo mode was activated WriterUtility._write_to_hdf_file( file, key + "_0", data_block[frame][0]) WriterUtility._write_to_hdf_file( file, key + "_1", data_block[frame][1]) else: WriterUtility._write_to_hdf_file( file, key, data_block[frame]) else: raise Exception( f"There are more frames {frame} then there are blocks of information " f" {len(data_block)} in the given list for key {key}." ) blender_proc_version = Utility.get_current_version() if blender_proc_version: WriterUtility._write_to_hdf_file( file, "blender_proc_version", np.string_(blender_proc_version))
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 not GlobalStorage.is_in_storage("output"): 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 GlobalStorage.get("output"): # Build path (path attribute is format string) file_path = output_type["path"] if '%' in file_path: file_path = file_path % frame # Check if file exists if not os.path.exists(file_path): # If not try stereo suffixes path_l, path_r = self._get_stereo_path_pair(file_path) if not os.path.exists(path_l) or not os.path.exists( path_r): raise Exception("File not found: " + file_path) else: use_stereo = True else: use_stereo = False 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])) blender_proc_version = Utility.get_current_version() if blender_proc_version: self._write_to_hdf_file(f, "blender_proc_version", np.string_(blender_proc_version))