I render RGB images and their depth maps as well for a series of frames (using cycles). Specifically, I need not a B/W depth png/jpg image, rather the actual depth values itself, which I can later read off in python. I found the exr to be the oft suggested format in online forums, as I want to store float values as such.
So, I stored the rgb image as well as the z buffer together in a .exr file. In python, while I could reassemble the rgb image perfectly, I discovered the Z channel info to be a matrix of ones. It should actually contain the float depth values.
What could be going wrong here? I have checked the 'zbuf' option in output properties.
For reference, this is the code I use to separate rgb and z values from the exr file:
import sys
import numpy as np
import OpenEXR as exr
import Imath
def readEXR(filename):
"""Read color + depth data from EXR image file.
Parameters
----------
filename : str
File path.
Returns
-------
img : RGB or RGBA image in float32 format. Each color channel
lies within the interval [0, 1].
Color conversion from linear RGB to standard RGB is performed
internally. See https://en.wikipedia.org/wiki/SRGB#The_forward_transformation_(CIE_XYZ_to_sRGB)
for more information.
Z : Depth buffer in float32 format or None if the EXR file has no Z channel.
"""
print(filename)
filename = str(filename)
exrfile = exr.InputFile(filename)
header = exrfile.header()
dw = header['dataWindow']
isize = (dw.max.y - dw.min.y + 1, dw.max.x - dw.min.x + 1)
channelData = dict()
# convert all channels in the image to numpy arrays
for c in header['channels']:
C = exrfile.channel(c, Imath.PixelType(Imath.PixelType.FLOAT))
C = np.fromstring(C, dtype=np.float32)
C = np.reshape(C, isize)
channelData[c] = C
colorChannels = ['R', 'G', 'B', 'A'] if 'A' in header['channels'] else ['R', 'G', 'B']
img = np.concatenate([channelData[c][...,np.newaxis] for c in colorChannels], axis=2)
# linear to standard RGB
img[..., :3] = np.where(img[..., :3] <= 0.0031308,
12.92 * img[..., :3],
1.055 * np.power(img[..., :3], 1 / 2.4) - 0.055)
# sanitize image to be in range [0, 1]
img = np.where(img < 0.0, 0.0, np.where(img > 1.0, 1, img))
Z = None if 'Z' not in header['channels'] else channelData['Z']
return img, Z
def main(fpth):
img, depth = readEXR(fpth[-1])
print(np.max(depth))
print(np.min(depth))
return
if __name__ == '__main__':
main(sys.argv[1:])
image
,alpha
anddepth
to the output node before rendering and saving the exr file $\endgroup$