# How to get accurate Z depth?

I‘m struggling to render accurate depth maps of different 3D models using Cycles and was wondering if anybody has/had similar problems and how she/he resolved them. I would greatly apprichiate help! :)

I attempted two different methods to obtain depth maps: 1) Via a camera node, exporting raw Z depth.
2) By rendering the Z pass and later convert them to paralell depths as in 1). In both cases, I store the depth as OpenEXR files. It is my understanding that this is the go-to format in such cases as it is designed to store linear data and, thus, should not distort my Z depth information.

However, in both cases I run into the same problem: I still have inaccurate depth values. I experimented with a simple scene - just a flat plane that is fronto-paralell to the camera. On top of this plane I put a ramp. When rendering this simple scene, e.g. in case of 1), these inacuraccies manifest as staircase artefacts on the ramp.

The thing is, I need accurate Z depths to test my algorithms on this data. So I can't turn on anti-aliasing, since that would also smooth the depth boundaries between fore- and background objects.

EDIT: blend-exchange.giantcowfilms.com/b/6241 & imgur.com/a/mj3JeTR

Any thoughts?

Thanks, Nici

• I'm not sure what you mean by "parallel depth as in 1)". In general saving the Z pass to OpenEXR is the most accuracy you will get. The result should be smooth unless the depth difference between pixels is large. BTW do you really see the staircase/banding artefacts in the data (numeric values) or do you mean visually on your monitor. In the latter case your monitor may simply not be able to display subtle difference due to limited bit width. Jul 9 '19 at 13:53
• In 1) Z-depth is
– Nici
Jul 9 '19 at 13:56
• But what kind of conversion are you talking about? Seems like your comment was cut off? Jul 9 '19 at 13:57
• AFAIK, the depth in 2) the depth is distance from the camera center to the object -- kind of radially. In 1) the depth is measured from a a plane in line with the camera, so the z depth measurement is performed along paralell rays.
– Nici
Jul 9 '19 at 14:06
• That shouldn't work, you can't simply convert perspective to orthographic in post-processing. You're missing significant amount of information for objects that are further away because they get projected on a much smaller space in the image plane. That obviously introduces information loss which may manifest in a form of "staircase" artefacts when converted. Jul 9 '19 at 14:18

If you want depth values that are parallel to the image plane, change the camera to orthographic projection. This will give accurate values in the Z-pass.

Edit:

Your error was having the file output node set to Float (Half) instead of Float (Full). Each file output node as its own settings! The reduced bit width resulted in the loss of precision.

Here is a little script for checking the values and displaying the normalized image. It requires OpenCV.

import cv2
import argparse

def image_values(path):
"""
Print the pixel values of the column at the image center and display the normalized image.
:param path: Path to image
"""
print(path)
(h, w) = img.shape
print("image ({}, {})".format(h, w))
img2 = cv2.normalize(img, None, 0., 1., cv2.NORM_MINMAX)
for y in range(h):
print("({},{}): {}".format(int(w/2), y, img[y, int(w/2)]))
cv2.imshow('image', img2)
cv2.waitKey(0)
cv2.destroyAllWindows()

if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Analyze image values")