Sampling objects in the 3D Front Dataset
In this example, we explain to you how to sample specific objects in the 3D-Front Dataset with the BlenderProc pipeline. What’s special is, that we select the surface object beforehand and that the sampled object is placed directly on the surface of a table for example. This is an advanced example, make sure that you have executed the basic examples before proceeding to this one.
Get the 3D-Front dataset
Please have a look at our description here.
Get the sampling object
We used an apple, downloaded from here.
Usage
Execute in the BlenderProc main directory:
blenderproc run examples/datasets/front_3d_object_sampling/main.py {PATH_TO_3D-Front-Json-File} {PATH_TO_3D-Future} {PATH_TO_3D-Front-texture} {PATH_TO_3d_object} examples/datasets/front_3d/output
examples/datasets/front_3d/main.py
: path to the python file with pipeline configuration.PATH_TO_3D-Front-Json-File: path to the 3D-Front json file. For the example pictures we used: “036bc96c-419d-4a43-812e-1e533d95dfd3.json”
PATH_TO_3D-Future
: path to the folder where all 3D-Future objects are storedPATH_TO_3D-Front-texture
: path to the folder where all 3D-Front textures are storedPATH_TO_3D-Object: path to the downloaded 3D object, get it [here](https://www.cgtrader.com/free-3d-models/food/fruit/apple-1)
examples/datasets/front_3d_object_sampling/output
: path to the output directory
Visualization
Visualize the generated data:
blenderproc vis hdf5 examples/datasets/front_3d_object_sampling/output/0.hdf5
Steps
Loads the
.json
file:bproc.loader.load_front3d
. It creates the rooms and also adds emission shaders to the ceiling and lamps.Select the surfaces, where the objects should be sampled on:
bproc.object.slice_faces_with_normals()
.Load the object, which should be sampled on the surface:
bproc.loader.load_blend()
.Sample the object on the surface:
bproc.object.sample_poses_on_surface()
.Run the physics simulation:
bproc.object.simulate_physics_and_fix_final_poses
.Check if the objects are still on the surface.
Adds camera pose to the scene:
bproc.camera.add_camera_pose()
.Renders all set camera poses:
bproc.renderer.render()
.Writes the output to .hdf5 containers:
bproc.writer.write_hdf5()
.
Python file (main.py)
Front3DObjectSelection
# Select the objects, where other objects should be sampled on
for obj in room_objs:
if "table" in obj.get_name().lower() or "desk" in obj.get_name().lower():
left_objects.append(obj)
for obj in left_objects:
# The loop starts with and UndoAfterExecution in order to restore the camera positions for each object
with bproc.utility.UndoAfterExecution():
# Select the surfaces, where the object should be sampled on
droppable_surface = bproc.object.slice_faces_with_normals(obj)
Specify with objects to use to sample on. In this case, it’s “table” and “desk”.
Then for each of those objects, the biggest surface is selected (e. g. top of the table) for sampling.
Front3DObjectSampling
surface_height_z = np.mean(surface_obj.get_bound_box(), axis=0)[2]
def sample_pose(obj: bproc.types.MeshObject):
# Sample the spheres location above the surface
obj.set_location(bproc.sampler.upper_region(
objects_to_sample_on=[surface_obj],
min_height=1,
max_height=4,
use_ray_trace_check=False
))
#Randomized rotation of the sampled object
obj.set_rotation_euler(np.random.uniform([0, 0, 0], [np.pi * 2, np.pi * 2, np.pi * 2]))
dropped_object_list = bproc.object.sample_poses_on_surface(sampling_obj, surface_obj, sample_pose,
min_distance=0.1, max_distance=10,
check_all_bb_corners_over_surface=False)
Get the height of the sampling surface
For every surface, the object is placed by
bproc.object.sample_poses_on_surface
.This also needs a pre-defined
sample_pose()
function, where the sampling surface, as well as the minimum and maximum sampling height, are given.It also sets the rotation of the sampled object.
Front3DObjectSamplingChecks
# get the minimum value of all eight corners and from that the Z value
min_coord_z = np.min(dropped_object.get_bound_box(local_coords=False), axis=0)[2]
# Check if object is on surface, otherwise delete object
remove_list = []
for index, dropped_object in enumerate(dropped_object_list):
# if distance is smaller than 5 cm
print(f"Object: {dropped_object.get_name()} has a diff of: {abs(min_coord_z - surface_height_z)}m to the surface")
if abs(min_coord_z - surface_height_z) > 0.05:
print("Delete this object, distance is above 0.05m")
dropped_object.delete()
remove_list.append(index)
After running the physics we have to check if the sampled object is still on the surface.