I followed the answer of this question in order to get a bounding box of visible area of an object in a rendered image. Since I have multiple objects that I add in the scene dynamically through script, and assign each of them a different pass_index, I use the following function (again, adapted from here) to get the bounding box of each object:
def getVisibleBoundingBox(objectPassIndex):
S = bpy.context.scene
width = int( S.render.resolution_x * S.render.resolution_percentage / 100 )
height = int( S.render.resolution_y * S.render.resolution_percentage / 100 )
depth = 4
#set the index to the object's pass index
bpy.context.scene.node_tree.nodes['ID Mask'].index = objectPassIndex
#render.render is very slow, try to find alternative to update the Viewer Node
#bpy.ops.render.render()
pixels = np.array( bpy.data.images['Viewer Node'].pixels[:] ).reshape( [height, width, depth] )
# Keep only one value for each pixel (white pixels have 1 in all RGBA channels anyway), thus converting the image to black and white
pixels = np.array( [ [ pixel[0] for pixel in row ] for row in pixels ] )
bbox = np.argwhere( pixels )
(ystart, xstart), (ystop, xstop) = bbox.min(0), bbox.max(0) + 1
return xstart, xstop, height - ystart, height - ystop
The problem is that the Viewer Node image data does not update when I change the index of the ID Mask node with:
bpy.context.scene.node_tree.nodes['ID Mask'].index = objectPassIndex
and it contains stale data from another object's pass index, so I get the same result all the time for different objectPassIndex when I try to take the pixels with:
pixels = np.array( [ [ pixel[0] for pixel in row ] for row in pixels ] )
This is not the case if I change the pass index in the GUI, where the Viewer node updates immediately. A workaround I found is to call bpy.ops.render.render() after changing the index and before taking the pixels, however, this operation is very slow and therefore not applicable for my use case. I also tried calling bpy.data.images['Viewer Node'].reload() without success.
So, the question is, is there a faster way to refresh the data of the Viewer node?
If not, another alternative that might work for me is to get a combined image containing in each pixel the pass_index of the particular object. I noticed that this image can be generated in the GUI by rendering and selecting the pass to IndexOB (image attached). But I do not know if it is possible to change the pass to IndexOB from python and grab the rendered image.
So the alternative question is if there is a way to get access to the pixels of this image in python?