I'm doing synthetic data generation for AI training. I need to render lots of images a scene, and giving the 2d bounding box value of each object in the image(assuming that all object in the scene will show up in the image). By setting up pass index for each object and enable Object Index form output-passes--data panel. with compositor nodes and a python script i could achieve it.
Here is the code:
import bpy
import numpy as np
import json
import os
def getVisibleBoundingBox(number_of_instances):
# build pass index list
id_list = [n for n in range(1,number_of_instances+1)]
# initiate a dict
gt = {}
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
#op =bpy.context.scene.node_tree.nodes['Render Layers'].outputs['IndexOB']
pixels = np.array( bpy.data.images[-1].pixels[:] ).reshape( [height, width, depth] )
pixels = np.array( [ [ pixel[0] for pixel in row ] for row in pixels ] )
for id in id_list:
bbox = np.argwhere( pixels == id)
#print(bbox)
if len(bbox) == 0:
return None
else:
(ystart, xstart), (ystop, xstop) = bbox.min(0), bbox.max(0) + 1
gt[id] = str(xstart), str(xstop), str(height - ystop), str(height - ystart)
#print(gt)
return gt
getVisibleBoundingBox(7)
This uses a viewer node to catch the IndexOb data and turn it an image, and turn the picture into number array to get the 2D-Boundingbox for each object. The thing is, when i run this script(within this scene) in background mode. The viewer node image won't be available. So i'm looking for a way to get the 2D-Boundingbox info directly from IndexOB.