Camera position: (0, -6, 6); Camera angles: (45, 0, 0) (zyx rotation sequence); Camera resolution: X=64 [px]; Y=64[px]; Sensor sizes: 32 [mm] x 32 [mm]; => px_per_mm: 2 [px/mm]; Focal length: 35 [mm]; Clipping: Start = 2 [m]; End = 16 [m];
Object: Plane orthogonal to z-axis located at z=0.
[EDIT] Used 'Blender Render' not 'Blender Cycles'.
The depth map is determined by an easy-to-compute formula, namely:
depth(x, y) = fy * sqrt(2) * L / (fy - (y - cy)) (1)
L = 6 [m] (height of the camera) fy = focal length * px_per_mm = 70 [px] cy = y-coordinate of the principal located in the middle of the screen, i.e. at 32 [px]
depth(x, y) = 593.969696 / (70 - (y - 32)) (2)
Saving the rendered image into an OpenEXR file 'plane.exr' allows to access the depth- coordinate and compare it to the theoretical solution in (2). Save the script below into 'extract_this.py':
import OpenEXR, Imath import numpy import sys pt = Imath.PixelType(Imath.PixelType.FLOAT) handle = OpenEXR.InputFile("plane.exr") dw = handle.header()['dataWindow'] x_size, y_size = (dw.max.x - dw.min.x + 1, dw.max.y - dw.min.y + 1) array = numpy.fromstring(handle.channel('Z', pt), dtype=numpy.float32) array.shape = (y_size, x_size) it = numpy.nditer(array, flags=["multi_index"]) while not it.finished: depth = float(it) if depth < 10000: y, x = it.multi_index print x, y_size - y, depth it.iternext()
The call it with:
> python extract_this.py > tmp.txt
will deliver the a data file with x and y in columns 1 and 2. The depth is stored in column 3. This can be displayed with gnuplot:
> depth(y) = 593.969696 / (70 - (y - 32)) > splot "tmp.txt" u 1:2:($3 - depth($2-0.5))
and delivers a picture as shown below. A '0.5' is subtracted to account for the fact that blender seems to deliver the depth at the pixel's center. As can be seen, there is a line where the z-coordinate is simply off the track. What can be done about that?