0
$\begingroup$

I am trying to extract the location(x,y,z) of the objects from the camera in my scene(highway scene -autobahn).
Note: I have imported the .obj file as my scene (obtained from elsewhere, not created by me) into the Blender and therefore the objects in my highway scene (like a car, tree, etc) do not show any values for location (x,y,z) in the viewport.

problem 1: But I need a sophisticated way to obtain the distance of all the objects of the scene elements from the camera, pixel-wise, to use it as ground truth for further application.

Methods I tried so far :

  • to create a driver that calculates the distance between two objects but unfortunately, it does not work because the location of the objects does not show as they are imported. it is always (0,0,0). Also, I cannot obtain pixel-wise distance.

  • use the depth render layer of the cycles render in Blender using the composting nodes and creating a node tree that calculates the distance writing it to the output file. This works! But I do not need a converted value, all I need is the Z-component of the distance to the camera. I followed the solution of using shader in this link How to get Z-distance (not depth) from camera to object for every pixel in the frame?. I am stuck in one place :

problem 2: While using shader nodes, I am unable to see the output of it. How can I extract the pixel-wise output into a file? I can build the node tree as shown in the image below, but I do not know how to proceed further. Please guide me on how to obtain the output into a file. Also, problem 3: I do not quite understand why I am multiplying the view vector with view distance? I followed the solution in the link but unable to understand this point.

This might be a trivial question but as I am a newbie in the computer graphics field, any leads would be extremely useful. Thank you in advance

NOdetree

$\endgroup$
6
  • $\begingroup$ Why don't you just use the Z pass in the RenderLayers, and render it as an Exr image? $\endgroup$
    – Secrop
    May 14 '21 at 6:46
  • $\begingroup$ @Secrop thnk you for your response. Actually I do not want to render the image. I want the values of the z pass into a file. Will the above method contain the z pass value that is not alteredn $\endgroup$
    – prath171
    May 19 '21 at 16:11
  • $\begingroup$ Don't know what you mean with unaltered Z pass value.. Putting the z values in a file, is just a matter of looping all pixels, extract the distance and write the value in to a file (using python). Could you detail what kind of file structure you need, and what do you plan to do with it? $\endgroup$
    – Secrop
    May 21 '21 at 9:10
  • $\begingroup$ @Secrop I want to do exactly the above-described procedure. I want an exr or png file or a CSV file will also do. this will act as ground truth for the scene that I export from blender and process for depth in mitsuba renderer(which has a custom depth integrator). As I am new to the field, i am confused if something will change if the Z values are written to OpenEXR format. Also, I am confused on how to extract it with python. I do know my starting point. Any leads would be very helpful. $\endgroup$
    – prath171
    May 21 '21 at 9:19
  • $\begingroup$ taking the example of your nodes setup, here's a simpler version, which does the same as the z pass: VectorMath.Distance between TextureCoordinate.Object from 'Camera' and Geometry.Position (the only thing that needs to be set is sampling to 1, because you don't want to interpolate the distance). I could later today write a small python script to turn the image into a cvs file. $\endgroup$
    – Secrop
    May 21 '21 at 9:29
0
$\begingroup$

Here's a small script that renders the scene and stores the Z_Pass into a CSV file, with {X, Y, Distance} in each entry. All you need to do is paste this in the text editor and execute.

import bpy
import numpy as np

dest = 'C:/tmp/z_data.csv'
backgroundD = 10**10

def getCoordFn(x):
    def gc(i):
        return i%x, i//x
    return gc

def getpixelz(image):
    arr = np.array(image.pixels)
    pix = arr[0:-1:4]
    gc = getCoordFn(image.size[0])
    zpix = [(gc(i), d) for i, d in enumerate(pix) if d < backgroundD]
    return zpix

def writeCsv(data):
    with open(dest, 'w') as file:
        for p in data:
            file.write(f'{p[0][0]} , {p[0][1]} , {p[1]}\n')

def prepareRender():
    rn = bpy.context.scene.render
    rn.engine = 'CYCLES'
    rn.image_settings.file_format = 'OPEN_EXR'
    rn.image_settings.color_depth = '32'
    cl = bpy.context.scene.cycles
    cl.samples = 1
    cl.pixel_filter_type = 'BOX'
    
def prepareOutput():
    scn = bpy.context.scene
    scn.use_nodes = True
    bpy.context.view_layer.use_pass_z = True
    nt = scn.node_tree
    nt.nodes.clear()
    r = nt.nodes.new('CompositorNodeRLayers')      
    v = nt.nodes.new('CompositorNodeViewer')
    nt.links.new(r.outputs['Depth'], v.inputs['Image'])  
    
def execute():
    prepareRender()
    prepareOutput()
    bpy.ops.render.render()
    image = bpy.data.images['Viewer Node']
    writeCsv(getpixelz(image))


execute()

Note that this overwrites any setup you have in the compositor.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.