Results 1 to 10 of 10
  1. #1

    Access Z-buffer and save it as file

    Hi all,
    i'm new user of Blender.
    I need to access Z-buffer because I need to use the deistances from the objects in the scene to the camera. Now, I can only get a image in grey-scale that gives me the object's depth but I would like save the value of each pixel in a matrix or array and save it in a file .txt
    I wonder if there is a script that does that. Otherwise, how can I write a script which does it?

    Thanks for your help!!!



  2. #2
    Hi, I want to do the same thing. I think a possible way is render an EXR image and then extract the Z channel... If anybody know any other solutions, please help us!



  3. #3
    Member Crouch's Avatar
    Join Date
    Oct 2004
    Location
    the Netherlands
    Posts
    1,414
    If I'm not mistaken you can save the z-buffer to an image, using the nodes editor. After that it's a simple matter of reading the values and writing them to a text file.

    Alternatively you could use the z-buffer of the 3d-view. Here's some code to do that:
    Code:
    import Blender
    from Blender import *
    from Blender.BGL import *
    
    windows = Window.GetScreenInfo()
    for w in windows:
        if w['type'] == Window.Types.VIEW3D:
            xmin, ymin, xmax, ymax = w['vertices']
            width = xmax-xmin
            height = ymax-ymin
    
    zbuf = Buffer(GL_FLOAT, [width*height])
    glReadPixels(xmin, ymin, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, zbuf)
    
    strbuf = []
    for i in range(height):
        strbuf.append(str(zbuf[i*width:i*width+width]))
    strbuf.reverse()
    
    file = open("C:/test.txt", "w")
    for i in strbuf:
        file.write(i[1:-1]+'\n')
    file.close()
    Some remarks:
    This doesn't work in wireframe and bounding box mode (viewport shading methods).
    It's best to have only one 3d-view when running the script.
    It could be that the z-depth of the grid is also output, so you might want to disable it.



  4. #4
    Many thanks for your answer! But i need to have a correlation between the image render (variable image size) and the z depth pixel to pixel, and I'm afraid that with glReadPixels isn't possible. The EXR image format seems perfect for me, with an EXR viewer I can read the Z channel value referred to the pixel under the cursor. But I haven't found nothing for saving z-values on text file. However thanks!



  5. #5
    ok, I'm not real comfortable with python (I mostly code in c...I could have coded a seq plugin to do the same thing in 1/4 the time it took me to learn enough python to do this) but this will give you a txt file with an array filled with the distance from the camera to each pixel in blender units.


    1. you need a node window, UV/Image window (set to viewer node) and a text window all open at the same time
    2. render
    3. in the node editor, link the renderlayer z socket to a viewer image socket and make that viewer node active so that it shows in the image editor- you will see a white screen...don't worry about it
    4. load the following code into the text window and run it.

    Code:
    import Blender
    from Blender import *
    
    img = Image.GetCurrent()
    if img:
        maxz = 50  #set just past the max depth of your scene
        xs,ys = img.getSize()
        file = open("put your path/filename here", "w")
        file.write("zbuffer_array["+str(xs*ys)+"] = {")
        for y in range(ys):
            for x in range(xs):
                r,g,b,a = img.getPixelHDR(x,y)
                if  r> maxz:
                    r = maxz
                file.write("%.3f, " %r) #change number if you want more or less precision
        file.write("}\n")
        file.close()
        print("done")
    notes:

    • maxz gives you a better value to deal with if a pixel is the blender background... ie: 50.000 instead of 99999997952.000 (it can also make the txt file much smaller if alot of background is present- 50% with default cube)
    • if you want values 0.0->1.0 instead of actual blender units, run the z socket through a normalize node (or Map value node) before the viewer node.
    • This produces a huge text file! default cube at 720*480 is 2.6megs with 345600 array elements
    Last edited by gpaprmh; 28-Jan-10 at 23:35.
    Nowadays, many people are urged to "Think outside the box"... I have spent my entire life wondering what the hell those people inside the box are thinking...



  6. #6
    Is there a way to have the z-buffer with anti-aliased edges instead of the jagged edges?



  7. #7
    Member Michael W's Avatar
    Join Date
    Nov 2007
    Location
    UK
    Posts
    4,992
    Originally Posted by phoenixart View Post
    Is there a way to have the z-buffer with anti-aliased edges instead of the jagged edges?
    It has to be aliased or else z-combine doesn't work.... it's the "standard"

    I guess if you need it smooth you just need to render it twice up an then downsample.... of use your nodes with FSA

    For those wanting a non python way just use openexr....

    or if you want another format :
    compositing nodes and link the "z" output to the output node (or a file output node..)

    if you don't want in as a float you could link the z to a "normalise" node and then to the output....

    Mike Williamson
    www.cowtoolsmedia.co.uk



  8. #8
    Thanks for your explanation Michael W, but I'm not sure to fully understand.
    Following your tips I'm trying to save the Open Exr after having "normalized" it, but I still see the jagged edges. Btw, now that you told me this has to be aliased, I see I've to look for a workaround...



  9. #9
    Many thanks to all! The paprmh's code is great. Now I'm trying to do a tool more automatic, in where the 3 preliminary steps are done by a python script. So:
    1) Is possible render in image window (setting context displayMode=0) -first step done-OK
    2)OK
    3)Without using node editor, I see that U/V image window has a button 'Draws zbuf values mapped to camera clip..'. The result is exactly as connect Z socket to an output viewer, so it's possible use the script for all blend file. But, unfortunately, I'havn't found an API for set this button in a script. Any advice?



  10. #10
    Hello. Sorry for digging up an old thread.
    I'm trying to do the same thing - access Z data dircetly from script. Does enyone know how to port the gpaprmh's code to new python API for Blender 2.64?
    I have the particular problem with this part:
    Code:
    img = Image.GetCurrent()
    EDIT:
    After a few tries I have a more general question - is there a way to access render layers/passes data from python script?
    I know where to find render settings and render the scene but where should I look for the result?

    EDIT2:
    Or maybe is there another way to save Z-Buffer data to a file (16-bit image or text)? Saving to a 8-bit grayscale PNG works great but I need a higher bit depth.
    Last edited by borwa; 29-Oct-12 at 09:00.



Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •