def add_random_objects(scene_struct, args, camera, idx): """ Add random objects to the current blender scene """ # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) objects = [] blender_objects = [] cob = clevr_scene[idx]['objects'] num_objects = len(cob) for i in range(num_objects): sf = cob[i] theta = sf['rotation'] obj_name_out = sf['shape'] obj_name = restore_util.get_obj_name(obj_name_out) size_name = sf['size'] r = restore_util.get_by_size(size_name) if obj_name == 'Cube': r /= math.sqrt(2) x, y = sf['3d_coords'][:2] mat_name_out = sf['material'] mat_name = restore_util.get_by_mat_name_out(mat_name_out) color_name = sf['color'] rgb = restore_util.get_by_colorname(color_name) rgba = [float(c) / 255.0 for c in rgb] + [1.0] # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta) obj = bpy.context.object blender_objects.append(obj) # Attach a random material utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords, _wh = utils.get_camera_coords(camera, obj.location) #pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) return objects, blender_objects
def add_objects(scene_struct, camera, objects): """ Add objects to the current blender scene """ blender_objects = [] for obj in objects: # Actually add the object to the scene utils.add_object(args.shape_dir, obj["shape"], obj["size"], obj["location"], theta=obj["rotation"]) bobj = bpy.context.object blender_objects.append(bobj) utils.add_material(obj["material"], Color=obj["color"]) obj["pixel_coords"] = utils.get_camera_coords(camera, bobj.location) import numpy as np loc = np.array(bobj.location) dim = np.array(bobj.dimensions) half = dim / 2 corners = [] corners.append(loc + half * [1, 1, 1]) corners.append(loc + half * [1, 1, -1]) corners.append(loc + half * [1, -1, 1]) corners.append(loc + half * [1, -1, -1]) corners.append(loc + half * [-1, 1, 1]) corners.append(loc + half * [-1, 1, -1]) corners.append(loc + half * [-1, -1, 1]) corners.append(loc + half * [-1, -1, -1]) import mathutils corners_camera_coords = np.array([ utils.get_camera_coords(camera, mathutils.Vector(tuple(corner))) for corner in corners ]) xmax = np.amax(corners_camera_coords[:, 0]) ymax = np.amax(corners_camera_coords[:, 1]) xmin = np.amin(corners_camera_coords[:, 0]) ymin = np.amin(corners_camera_coords[:, 1]) obj["bbox"] = (float(xmin), float(ymin), float(xmax), float(ymax)) return blender_objects
def transform_random_objects(scene_struct, blender_objects, camera): c = 0 objects = scene_struct['objects'] positions = [obj.location for obj in blender_objects] for obj in blender_objects: loc = obj.location x_t = min(max(loc[0] + random.uniform(-1.5, 1.5), -3), 3) y_t = min(max(loc[1] + random.uniform(-1.5, 1.5), -3), 3) obj.location = Vector((x_t, y_t, loc[2])) pixel_coords = utils.get_camera_coords(camera, obj.location) objects[c]['3d_coords'] = tuple(obj.location) objects[c]['pixel_coords'] = pixel_coords c = c + 1 scene_struct['objects'] = objects return blender_objects, scene_struct
def logical_representation(self): return { "material": self.material, "size": self.size, "shape": self.shape, "color": self.color, "rotation": self.rotation, "pixel_coords": utils.get_camera_coords(self._factory.camera, self._blender_object.location), "3d_coords": tuple(self._blender_object.location) }
def render_object(obj): obj_name_out = obj['shape'] obj_name = [k for k, v in object_mapping if v == obj_name_out][0] color_name = obj['color'] rgba = color_name_to_rgba[color_name] size_name = obj['size'] r = [v for k, v in size_mapping if k == size_name][0] if obj_name == 'Cube': r /= math.sqrt(2) theta = obj['rotation'] mat_name_out = obj['material'] mat_name = [k for k, v in material_mapping if v == mat_name_out][0] x, y, z = obj['3d_coords'] position = (x, y, r) utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta) new_blend_obj = bpy.context.object utils.add_material(mat_name, Color=rgba) new_pixel_coords = utils.get_camera_coords(camera, new_blend_obj.location) return new_blend_obj, position, new_pixel_coords
def add_random_objects(scene_struct, num_objects, args, camera, init_positions, sizes=[], inout=False): """ Add random objects to the current blender scene """ # Load the property file print(init_positions) color_name_to_rgba = {} with open(args.properties_json, 'r') as f: properties = json.load(f) for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] for i in range(num_objects): if len(sizes) == 1 and i != 0: # Choose a random size size_name, r = random.choice(size_mapping) else: size_name, r = sizes[i] x, y, z = init_positions[i] # Choose random color and shape if shape_color_combos is None: obj_name, obj_name_out = random.choice(object_mapping) color_name, rgba = random.choice(list(color_name_to_rgba.items())) if inout and i == 0: obj_name, obj_name_out = ('Tray', 'tray') color_name, rgba = ('gray', [0.5, 0.5, 0.5, 1]) # elif i == 0: # obj_name, obj_name_out = ('SmoothCube_v2', 'cube') # color_name, rgba = ('red', [0.67, 0.13, 0.13, 1]) # elif i == 1: # obj_name, obj_name_out = ('SmoothCube_v2', 'cube') # color_name, rgba = ('blue', color_name_to_rgba['blue']) # elif i == 2: # obj_name, obj_name_out = ('SmoothCylinder', 'cylinder') # color_name, rgba = ('green', color_name_to_rgba['green']) else: obj_name_out, color_choices = random.choice(shape_color_combos) color_name = random.choice(color_choices) obj_name = [k for k, v in object_mapping if v == obj_name_out][0] rgba = color_name_to_rgba[color_name] # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) theta = 0 # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y, z), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, z, r)) # Attach a random material mat_name, mat_name_out = random.choice(material_mapping) if i == 0 or i == 1: mat_name = "Rubber" elif i == 2: mat_name = "MyMetal" utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'r' : r, 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) # Check that all objects are at least partially visible in the rendered image all_visible = check_visibility(blender_objects, objects, args.min_pixels_per_object) if not all_visible: # If any of the objects are fully occluded then start over; delete all # objects from the scene and place them all again. print('Some objects are occluded; replacing objects') for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera, init_positions + np.random.uniform(low=-0.05, high=0.05, size=(np.array(init_positions).shape)), sizes=sizes, inout=inout) return objects, blender_objects
def render_scene(args, num_objects=5, num_images=0, output_split='none', image_template='render.png', scene_template='render_json', arr_template='arr', output_blendfile=None, directions={1: 'no', 2: 'no', 3: 'no', 4: 'no', 5: 'no', 6: 'no'} ): for object_name in bpy.data.objects.keys(): if 'Sphere' in object_name or\ 'Cylinder' in object_name or\ 'Cube' in object_name or\ 'Duck' in object_name or\ 'Peg' in object_name or\ 'Disk' in object_name or\ 'Bowl' in object_name: utils.delete_object_by_name(object_name) # Load materials utils.load_materials(args.material_dir) # Set render arguments so we can get pixel coordinates later. # We use functionality specific to the CYCLES renderer so BLENDER_RENDER # cannot be used. render_args = bpy.context.scene.render render_args.engine = "CYCLES" render_args.resolution_x = args.width render_args.resolution_y = args.height render_args.resolution_percentage = 100 render_args.tile_x = args.render_tile_size render_args.tile_y = args.render_tile_size if args.use_gpu == 1: # Blender changed the API for enabling CUDA at some point if bpy.app.version < (2, 78, 0): bpy.context.user_preferences.system.compute_device_type = 'CUDA' bpy.context.user_preferences.system.compute_device = 'CUDA_0' else: cycles_prefs = bpy.context.user_preferences.addons['cycles'].preferences cycles_prefs.compute_device_type = 'CUDA' # Some CYCLES-specific stuff bpy.data.worlds['World'].cycles.sample_as_light = True bpy.context.scene.cycles.blur_glossy = 2.0 bpy.context.scene.cycles.samples = args.render_num_samples bpy.context.scene.cycles.transparent_min_bounces = args.render_min_bounces bpy.context.scene.cycles.transparent_max_bounces = args.render_max_bounces if args.use_gpu == 1: bpy.context.scene.cycles.device = 'GPU' # This will give ground-truth information about the scene and its objects scene_struct = { 'split': output_split, 'objects': [], 'directions': {}, } # Put a plane on the ground so we can compute cardinal directions bpy.ops.mesh.primitive_plane_add(radius=5) plane = bpy.context.object def rand(L): return 2.0 * L * (random.random() - 0.5) # Add random jitter to camera position if args.camera_jitter > 0: for i in range(3): bpy.data.objects['Camera'].location[i] += rand(args.camera_jitter) # Figure out the left, up, and behind directions along the plane and record # them in the scene structure camera = bpy.data.objects['Camera'] plane_normal = plane.data.vertices[0].normal cam_behind = camera.matrix_world.to_quaternion() * Vector((0, 0, -1)) cam_left = camera.matrix_world.to_quaternion() * Vector((-1, 0, 0)) cam_up = camera.matrix_world.to_quaternion() * Vector((0, 1, 0)) plane_behind = (cam_behind - cam_behind.project(plane_normal)).normalized() plane_left = (cam_left - cam_left.project(plane_normal)).normalized() plane_up = cam_up.project(plane_normal).normalized() # Delete the plane; we only used it for normals anyway. The base scene file # contains the actual ground plane. utils.delete_object(plane) # Save all six axis-aligned directions in the scene struct scene_struct['directions']['behind'] = tuple(plane_behind) scene_struct['directions']['front'] = tuple(-plane_behind) scene_struct['directions']['left'] = tuple(plane_left) scene_struct['directions']['right'] = tuple(-plane_left) scene_struct['directions']['above'] = tuple(plane_up) scene_struct['directions']['below'] = tuple(-plane_up) # Add random jitter to lamp positions if args.key_light_jitter > 0: for i in range(3): bpy.data.objects['Lamp_Key'].location[i] += rand(args.key_light_jitter) if args.back_light_jitter > 0: for i in range(3): bpy.data.objects['Lamp_Back'].location[i] += rand(args.back_light_jitter) if args.fill_light_jitter > 0: for i in range(3): bpy.data.objects['Lamp_Fill'].location[i] += rand(args.fill_light_jitter) objects = [] blender_objects = [] direction_vec = [] traj = [] for scene_idx in range(num_images): image_path = image_template % (scene_idx + args.start_idx) render_args.filepath = image_path scene_path = scene_template % (scene_idx + args.start_idx) arr_path = arr_template % (scene_idx + args.start_idx) if scene_idx == 0: init_positions = [] # ref_obj_loc = np.array([0, -1, 0]) ref_obj_loc = np.array([0, 0, 0]) init_positions.append(ref_obj_loc) sizes = [('large', 0.6)] # sizes = [('small', 0.3)] inout=False for obj_idx in range(1, args.max_objects): init_position = [] for axis, movement in directions.items(): # X if axis == 1: if movement != ['no']: if movement[0] == 'front': init_position.append(-3) else: init_position.append(2) else: tmp = random.choice(np.linspace(-2, 2, 10, endpoint=True)) while np.array([abs(tmp - posit[1]) < args.margin for posit in init_positions]).any(): tmp = random.choice(np.linspace(-2, 2, 10, endpoint=True)) init_position.append(tmp) # Y if axis == 0: if movement != ['no']: if movement[0] == 'left': init_position.append(-2) else: init_position.append(2) else: tmp = random.choice(np.linspace(-2, 2, 10, endpoint=True)) while np.array([abs(tmp - posit[0]) < args.margin for posit in init_positions]).any(): tmp = random.choice(np.linspace(-2, 2, 10, endpoint=True)) init_position.append(tmp) # Z if axis == 2: if movement != ['no']: if movement[0] == 'below': init_position.append(0) else: init_position.append(2) else: tmp = random.choice(np.linspace(0, 2, 10, endpoint=True)) # while np.array([abs(tmp - posit[2]) < args.margin for posit in init_positions]).any(): while abs(tmp - init_positions[0][2]) < args.margin: tmp = random.choice(np.linspace(0, 2, 10, endpoint=True)) init_position.append(tmp) # CLOSE/FAR close_far_thresh = 3 if axis == 3: if movement != ['no']: far_sample = [] close_sample = [] while far_sample == [] or \ np.linalg.norm(far_sample - ref_obj_loc) < close_far_thresh or \ np.array([np.linalg.norm(far_sample - posit) < args.min_dist for posit in init_positions]).any(): x = random.choice(np.linspace(-2, 2, 10, endpoint=True)) y = random.choice(np.linspace(-2, 2, 10, endpoint=True)) z = random.choice(np.linspace(0.6, 2, 10, endpoint=True)) far_sample = np.array([x, y, z]) while close_sample == [] or \ np.linalg.norm(close_sample - ref_obj_loc) > close_far_thresh or \ np.linalg.norm(close_sample - ref_obj_loc) < 1: x = random.choice(np.linspace(-2, 2, 10, endpoint=True)) y = random.choice(np.linspace(-2, 2, 10, endpoint=True)) z = random.choice(np.linspace(0.6, 2, 10, endpoint=True)) close_sample = np.array([x, y, z]) if movement[0] == 'far': init_position = far_sample else: init_position = close_sample else: pass # ON/OFF close_far_thresh = 1 if axis == 4: if movement != ['no']: # size_mapping = [('small', 0.35), ('large', 0.7)] size_mapping = [('small', 0.5)] off_sample = [] on_sample = [] while off_sample == [] or \ np.linalg.norm(off_sample - ref_obj_loc) < close_far_thresh or \ np.array([np.linalg.norm(off_sample - posit) < args.min_dist for posit in init_positions]).any(): x = random.choice(np.linspace(-2, 2, 10, endpoint=True)) y = random.choice(np.linspace(-2, 2, 10, endpoint=True)) # z = random.choice(np.linspace(0.6, 2, 10, endpoint=True)) z = 0 off_sample = np.array([x, y, z]) x = init_positions[-1][0] + random.uniform(-0.2, 0.2) y = init_positions[-1][1] + random.uniform(-0.2, 0.2) size_name, r = random.choice(size_mapping) sizes.append((size_name, r)) z = init_positions[-1][2] + sizes[-1][1] * 2 on_sample = np.array([x, y, z]) if movement[0] == 'off': init_position = off_sample else: init_position = on_sample else: pass # IN/OUT close_far_thresh = 1 if axis == 5: if movement != ['no']: inout = True out_sample = [] in_sample = [] while out_sample == [] or \ np.linalg.norm(out_sample - ref_obj_loc) < close_far_thresh or \ np.array([np.linalg.norm(out_sample - posit) < args.min_dist for posit in init_positions]).any(): x = random.choice(np.linspace(-2, 2, 10, endpoint=True)) # y = random.choice(np.linspace(-2, 2, 10, endpoint=True)) y = -3 + random.uniform(-0.2, 0.2) # z = random.choice(np.linspace(0.6, 2, 10, endpoint=True)) z = 0 out_sample = np.array([x, y, z]) # if obj_idx == 1: # offset = -1 # else: # offset = 1 offsets = [[-1, -1], [-1, 1], [1, -1], [1, 1]] # x = init_positions[0][0] + offset # y = init_positions[0][1] + random.choice(np.linspace(-0.2, 0.2, 2, endpoint=True)) x, y = offsets[obj_idx - 1] x += random.uniform(-0.1, 0.1) y += random.uniform(-0.1, 0.1) sizes.append(('small', 0.3)) z = init_positions[0][2] in_sample = np.array([x, y, z]) if movement[0] == 'out': init_position = out_sample else: init_position = in_sample else: pass init_positions.append(init_position) # FACILITATE STACKING if directions[4][0] != 'no' and directions[4][0] == 'on': init_positions = init_positions[:1] + init_positions[1:][::-1] print(init_positions) # Now make some random objects objects, blender_objects = add_random_objects(scene_struct, num_objects, args, camera, \ init_positions, sizes=sizes, inout=inout) init_positions = [] for obj in blender_objects: init_positions.append(np.array(obj.location)) final_positions = [] ref_obj_loc = init_positions[0] final_positions.append(ref_obj_loc) curvy = False for obj_idx in range(1, args.max_objects): final_position = [] for axis, movement in directions.items(): # X if axis == 1: if movement != ['no']: if movement[0] == 'front': final_position.append(2) else: final_position.append(-3) else: final_position.append(np.array(blender_objects[obj_idx].location[1])) # Y if axis == 0: if movement != ['no']: if movement[0] == 'left': final_position.append(2) else: final_position.append(-2) else: final_position.append(np.array(blender_objects[obj_idx].location[0])) # Z if axis == 2: if movement != ['no']: if movement[0] == 'below': final_position.append(2) else: final_position.append(objects[obj]['r']) else: final_position.append(np.array(blender_objects[obj_idx].location[2])) # CLOSE/FAR close_far_thresh = 3 if axis == 3: if movement != ['no']: far_sample = [] close_sample = [] while far_sample == [] or \ np.linalg.norm(far_sample - ref_obj_loc) < close_far_thresh or \ np.array([np.linalg.norm(far_sample - posit) < args.min_dist for posit in final_positions]).any(): x = random.choice(np.linspace(-2, 2, 10, endpoint=True)) y = random.choice(np.linspace(-2, 2, 10, endpoint=True)) z = random.choice(np.linspace(0.6, 2, 10, endpoint=True)) far_sample = np.array([x, y, z]) while close_sample == [] or \ np.linalg.norm(close_sample - ref_obj_loc) > close_far_thresh or \ np.linalg.norm(close_sample - ref_obj_loc) < 1 or \ np.array([np.linalg.norm(close_sample - posit) < args.min_dist for posit in final_positions]).any(): x = random.choice(np.linspace(-2, 2, 10, endpoint=True)) y = random.choice(np.linspace(-2, 2, 10, endpoint=True)) z = random.choice(np.linspace(0.6, 2, 10, endpoint=True)) close_sample = np.array([x, y, z]) if movement[0] == 'far': final_position = close_sample else: final_position = far_sample else: pass # ON/OFF close_far_thresh = 1 if axis == 4: if movement != ['no']: curvy = True off_sample = [] on_sample = [] while off_sample == [] or \ np.linalg.norm(off_sample - ref_obj_loc) < close_far_thresh or \ np.array([np.linalg.norm(off_sample - posit) < args.min_dist for posit in final_positions]).any(): x = random.choice(np.linspace(-2, 2, 10, endpoint=True)) y = random.choice(np.linspace(-2, 2, 10, endpoint=True)) # z = random.choice(np.linspace(0.6, 2, 10, endpoint=True)) z = 0 off_sample = np.array([x, y, z]) x = final_positions[-1][0] + random.uniform(-0.2, 0.2) y = final_positions[-1][1] + random.uniform(-0.2, 0.2) r_prev = objects[obj_idx-1]['r'] r = objects[obj_idx]['r'] z = final_positions[-1][2] + r_prev + r on_sample = np.array([x, y, z]) if movement[0] == 'off': final_position = on_sample else: final_position = off_sample else: pass # IN/OUT close_far_thresh = 1 if axis == 5: if movement != ['no']: curvy = True out_sample = [] in_sample = [] while out_sample == [] or \ np.linalg.norm(out_sample - ref_obj_loc) < close_far_thresh or \ np.array([np.linalg.norm(out_sample - posit) < args.min_dist for posit in final_positions]).any(): x = random.choice(np.linspace(-2, 2, 10, endpoint=True)) # y = random.choice(np.linspace(-2, 2, 10, endpoint=True)) y = -3 + random.uniform(-0.2, 0.2) # z = random.choice(np.linspace(0.6, 2, 10, endpoint=True)) z = 0 out_sample = np.array([x, y, z]) # if obj_idx == 1: # offset = -1 # else: # offset = 1 # x = final_positions[0][0] + offset # y = final_positions[0][1] + random.choice(np.linspace(-0.2, 0.2, 2, endpoint=True)) #offsets = [[-1, -1], [-1, 1], [1, -1], [1, 1]] offsets = [[-0.5, -0.5], [-0.5, 0.5], [0.5, -0.5], [0.5, 0.5]] x, y = offsets[obj_idx - 1] # x, y = [0, 0] x += random.uniform(-0.1, 0.1) y += random.uniform(-0.1, 0.1) r = objects[obj_idx]['r'] z = final_positions[0][2] + r in_sample = np.array([x, y, z]) if movement[0] == 'out': final_position = in_sample else: final_position = out_sample else: pass final_positions.append(final_position) traj = calculate_trajectory(init_positions, final_positions, args, curvy=curvy) else: move_obj_idx, pos = traj[scene_idx-1] move_object(blender_objects[move_obj_idx], pos) pixel_coords = utils.get_camera_coords(camera, blender_objects[move_obj_idx].location) objects[move_obj_idx]['pixel_coords'] = pixel_coords # <Vector (-1.6002, -1.5445, 1.9500)> objects[move_obj_idx]['3d_coords'] = list(blender_objects[move_obj_idx].location) # <Euler (x=0.0000, y=0.0000, z=139.0579), order='XYZ'> objects[move_obj_idx]['rotation'] = blender_objects[move_obj_idx].rotation_euler[2] ### get b_box box_dict = get_b_box.main(bpy.context, blender_objects) for _id in box_dict: objects[_id]['bbox'] = box_dict[_id] # Render the scene and dump the scene data structure scene_struct['objects'] = objects scene_struct['relationships'] = compute_all_relationships(scene_struct) tree = bpy.context.scene.node_tree links = tree.links rl = tree.nodes['Render Layers'] v = tree.nodes['Viewer'] links.new(rl.outputs[0], v.inputs[0]) while True: try: bpy.ops.render.render(write_still=True) break except Exception as e: print(e) links.remove(links[0]) # get viewer pixels rgb_pixels = bpy.data.images['Viewer Node'].pixels rgb_pixels = np.array(rgb_pixels[:]) rgb_pixels = np.power(rgb_pixels, 1/2.2) rgb_pixels[rgb_pixels > 1] = 1 rgb_pixels = rgb_pixels.reshape(args.height, args.width, 4)[...,:3] links.new(rl.outputs[2], v.inputs[0]) render_shadeless(blender_objects, lights_off=False) links.remove(links[0]) # get viewer pixels depth_pixels = bpy.data.images['Viewer Node'].pixels depth_pixels = np.array(depth_pixels[:]) depth_pixels = depth_pixels.reshape(args.height, args.width, 4)[...,0, None] links.new(rl.outputs[0], v.inputs[0]) render_shadeless(blender_objects) links.remove(links[0]) # get viewer pixels mask_pixels = bpy.data.images['Viewer Node'].pixels mask_pixels = np.array(mask_pixels[:]) mask_pixels = mask_pixels.reshape(args.height, args.width, 4)[...,:3] pixels = np.concatenate((rgb_pixels, depth_pixels, mask_pixels), axis=2) pixels = np.flipud(pixels) utils.save_arr(pixels, arr_path) with open(scene_path, 'w') as f: json.dump(scene_struct, f, indent=2)
def replace_random_object(scene_struct, blender_objects, camera, args): num_objs = len(blender_objects) n_rand = int(random.uniform(0, 1) * num_objs) obj = blender_objects[n_rand] x, y, r = obj.location size_name = scene_struct['objects'][n_rand]['size'] old_shape = scene_struct['objects'][n_rand]['shape'] old_color = scene_struct['objects'][n_rand]['color'] utils.delete_object(obj) scene_struct['objects'].pop(n_rand) blender_objects.pop(n_rand) objects = scene_struct['objects'] positions = [obj.location for obj in blender_objects] # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) # Choose random color and shape if shape_color_combos is None: obj_name_out = old_shape color_name = old_color while obj_name_out == old_shape: obj_name, obj_name_out = random.choice(object_mapping) while color_name == old_color: color_name, rgba = random.choice(list(color_name_to_rgba.items())) else: obj_name_out = old_shape color_name = old_color while obj_name_out == old_shape: obj_name_out, color_choices = random.choice(shape_color_combos) while color_name == old_color: color_name = random.choice(color_choices) obj_name = [k for k, v in object_mapping if v == obj_name_out][0] rgba = color_name_to_rgba[color_name] # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) # Choose random orientation for the object. theta = 360.0 * random.random() # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta) obj = bpy.context.active_object blender_objects.append(obj) positions.append((x, y, r)) # Attach a random material mat_name, mat_name_out = random.choice(material_mapping) utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) bbox = camera_view_bounds_2d(bpy.context.scene, camera, obj) objects.append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'bbox': bbox.to_tuple(), 'color': color_name, }) scene_struct['objects'] = objects return blender_objects, scene_struct
def add_objects(scene_struct, blender_objects, camera, args): num_objects = 1 # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) objects = scene_struct['objects'] positions = [obj.location for obj in blender_objects] for i in range(num_objects): # Choose a random size size_name, r = random.choice(size_mapping) # Try to place the object, ensuring that we don't intersect any existing # objects and that we are more than the desired margin away from all existing # objects along all cardinal directions. num_tries = 0 while True: # If we try and fail to place an object too many times, then delete all # the objects in the scene and start over. num_tries += 1 if num_tries > args.max_retries: print("*" * 20, " Num tries reached!!") #for obj in blender_objects: # utils.delete_object(obj) #return add_random_objects(scene_struct, num_objects, args, camera) x = random.uniform(-3, 3) y = random.uniform(-3, 3) # Check to make sure the new object is further than min_dist from all # other objects, and further than margin along the four cardinal directions dists_good = True margins_good = True for (xx, yy, rr) in positions: dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) if dist - r - rr < args.min_dist: dists_good = False break for direction_name in ['left', 'right', 'front', 'behind']: direction_vec = scene_struct['directions'][direction_name] assert direction_vec[2] == 0 margin = dx * direction_vec[0] + dy * direction_vec[1] if 0 < margin < args.margin: print(margin, args.margin, direction_name) print('BROKEN MARGIN!') margins_good = False break if not margins_good: break if dists_good and margins_good: break # Choose random color and shape if shape_color_combos is None: obj_name, obj_name_out = random.choice(object_mapping) color_name, rgba = random.choice(list(color_name_to_rgba.items())) else: obj_name_out, color_choices = random.choice(shape_color_combos) color_name = random.choice(color_choices) obj_name = [k for k, v in object_mapping if v == obj_name_out][0] rgba = color_name_to_rgba[color_name] # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) # Choose random orientation for the object. theta = 360.0 * random.random() # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) # Attach a random material mat_name, mat_name_out = random.choice(material_mapping) utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) bbox = camera_view_bounds_2d( bpy.context.scene, camera, obj ) #bpy_extras.object_utils.world_to_camera_view(scene, obj, coord) #print("*"* 10, b2, pixel_coords) #break objects.append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'bbox': bbox.to_tuple(), 'color': color_name, }) scene_struct['objects'] = objects return blender_objects, scene_struct
def add_random_objects(scene_struct, num_objects, args, camera, attempts=0): """ Add random objects to the current blender scene """ if attempts > 10: print ("Tried 10 times to place {} objects and failed. Giving up hope and moving on.".format(num_objects)) return None, None # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) num_objects = [["duck",args.num_ducks],["sphere",args.num_balls]] objects_to_place = [] for obj_name, num in num_objects: for i in range(num): objects_to_place.append(obj_name) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] x_range = [-2.5,2.5] y_range = [-2.5,2.5] corners = [[x_range[0], y_range[0]], [x_range[0], y_range[1]], [x_range[1], y_range[0]], [x_range[1], y_range[1]],] i=-1 while len(objects_to_place) > 0: i+=1 #for i in range(num_objects): # Choose a random size size_name, r = random.choice(size_mapping) # Try to place the object, ensuring that we don't intersect any existing # objects and that we are more than the desired margin away from all existing # objects along all cardinal directions. num_tries = 0 while True: # If we try and fail to place an object too many times, then delete all # the objects in the scene and start over. num_tries += 1 if num_tries > args.max_retries: for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera, attempts=attempts+1) #x = corners[i][0] #y = corners[i][1] #print (x, y, "POSITION") x = random.uniform(*x_range) y = random.uniform(*y_range) # Check to make sure the new object is further than min_dist from all # other objects, and further than margin along the four cardinal directions dists_good = True margins_good = True for (xx, yy, rr) in positions: dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) if dist - r - rr < args.min_dist: dists_good = False break for direction_name in ['left', 'right', 'front', 'behind']: direction_vec = scene_struct['directions'][direction_name] assert direction_vec[2] == 0 margin = dx * direction_vec[0] + dy * direction_vec[1] if 0 < margin < args.margin: print(margin, args.margin, direction_name) print('BROKEN MARGIN!') margins_good = False break if not margins_good: break if dists_good and margins_good: break # Choose random color and shape if shape_color_combos is None: obj_name_out = objects_to_place.pop() #obj_name = object_mapping[obj_name_out] obj_name = properties["shapes"][obj_name_out] #obj_name, obj_name_out = random.choice(object_mapping) color_name, rgba = random.choice(list(color_name_to_rgba.items())) else: obj_name_out, color_choices = random.choice(shape_color_combos) color_name = random.choice(color_choices) obj_name = [k for k, v in object_mapping if v == obj_name_out][0] rgba = color_name_to_rgba[color_name] r *= args.width / 256. / 1.2 zshift=0.0 # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) if obj_name=="Sphere": zshift = -0.25*r if obj_name == 'Rubber Duck': r /= math.sqrt(2) zshift=-1.15 # Choose random orientation for the object. theta = 360.0 * random.random() # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta, zshift=zshift) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) # Attach a random material if obj_name != 'Rubber Duck': mat_name, mat_name_out = random.choice(material_mapping) utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, #'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) # Check that all objects are at least partially visible in the rendered image all_visible = check_visibility(blender_objects, args.min_pixels_per_object*(args.width/256)**2) if not all_visible: # If any of the objects are fully occluded then start over; delete all # objects from the scene and place them all again. print('Some objects are occluded; replacing objects') for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera, attempts=attempts+1) return objects, blender_objects
def add_random_objects(scene_struct, num_objects, args, camera, gen_list): """ Add random objects to the current blender scene """ # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] assert num_objects == 1, "Only Generate Single" gen_config = gen_list.split('.') gen_config = [k.split('_') for k in gen_config] for i in range(num_objects): # Choose a random size size_name, r = random.choice(size_mapping) # Try to place the object, ensuring that we don't intersect any existing # objects and that we are more than the desired margin away from all existing # objects along all cardinal directions. num_tries = 0 while True: # If we try and fail to place an object too many times, then delete all # the objects in the scene and start over. num_tries += 1 if num_tries > args.max_retries: for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera, gen_list) # if i == 0: # x = random.uniform(-2.5, -0.3) # else: # x = random.uniform(0.3, 2.5) x = random.uniform(-1.5, 1.5) # x = random.uniform(-3, 3) y = x #random.uniform(-0.2, 0.2)#random.uniform(-3, 3) rn = random.uniform(0.5 * (np.abs(x) - 0.3) - 2.1, 0.1) y += rn x -= rn # Check to make sure the new object is further than min_dist from all # other objects, and further than margin along the four cardinal directions dists_good = True margins_good = True for (xx, yy, rr) in positions: dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) if dist - r - rr < args.min_dist: dists_good = False break for direction_name in ['left', 'right', 'front', 'behind']: direction_vec = scene_struct['directions'][direction_name] assert direction_vec[2] == 0 margin = dx * direction_vec[0] + dy * direction_vec[1] if 0 < margin < args.margin: print(margin, args.margin, direction_name) print('BROKEN MARGIN!') margins_good = False break if not margins_good: break if dists_good and margins_good: break # Choose random color and shape if shape_color_combos is None: obj_name, obj_name_out = random.choice(object_mapping) color_name, rgba = random.choice(list(color_name_to_rgba.items())) else: obj_name_out, color_choices = random.choice(shape_color_combos) color_name = random.choice(color_choices) obj_name = [k for k, v in object_mapping if v == obj_name_out][0] rgba = color_name_to_rgba[color_name] # print (obj_name, obj_name_out, color_name, rgba) # abc color_name = gen_config[i][0] obj_name = properties['shapes'][gen_config[i][1]] obj_name_out = gen_config[i][1] rgba = color_name_to_rgba[color_name] print(color_name, obj_name) # abc # For cube, adjust the size a bit if obj_name == 'cube': assert False r /= math.sqrt(2) # Choose random orientation for the object. theta = 45. #360.0 * random.random() if obj_name == 'Trunk': theta = 134. # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) # Attach a random material mat_name, mat_name_out = random.choice(material_mapping) utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) # Check that all objects are at least partially visible in the rendered image all_visible = check_visibility(blender_objects, args.min_pixels_per_object) if not all_visible: # If any of the objects are fully occluded then start over; delete all # objects from the scene and place them all again. print('Some objects are occluded; replacing objects') for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera, gen_list) return objects, blender_objects
def add_random_objects(scene_struct, num_objects, args, camera): """ Add random objects to the current blender scene """ # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] for i in range(num_objects): # Choose a random size size_name, r = random.choice(size_mapping) # Try to place the object, ensuring that we don't intersect any existing # objects and that we are more than the desired margin away from all existing # objects along all cardinal directions. num_tries = 0 while True: # If we try and fail to place an object too many times, then delete all # the objects in the scene and start over. num_tries += 1 if num_tries > args.max_retries: for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera) x = random.uniform(-2.5, 2.5) y = random.uniform(-2.5, 2.5) # Check to make sure the new object is further than min_dist from all # other objects, and further than margin along the four cardinal directions dists_good = True margins_good = True for (xx, yy, rr) in positions: dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) if dist <= 0.5 and random.random() <= 0.5: x = xx y = yy dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) if dist >= 0.1 and dist - r - rr < args.min_dist: dists_good = False break for direction_name in [ 'left', 'right', 'front', 'behind', 'above', 'below' ]: direction_vec = scene_struct['directions'][direction_name] # assert direction_vec[2] == 0 margin = dx * direction_vec[0] + dy * direction_vec[1] if dist >= 0.1 and 0 < margin < args.margin: print(dist, margin, args.margin, direction_name) print('BROKEN MARGIN!') margins_good = False break if not margins_good: break num, z = height(objects, (x, y)) if dists_good and margins_good and num <= 2: break # Choose random color and shape if shape_color_combos is None: obj_name, obj_name_out = random.choice(object_mapping) color_name, rgba = random.choice(list(color_name_to_rgba.items())) else: obj_name_out, color_choices = random.choice(shape_color_combos) color_name = random.choice(color_choices) obj_name = [k for k, v in object_mapping if v == obj_name_out][0] rgba = color_name_to_rgba[color_name] # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) # Choose random orientation for the object. theta = 360.0 * random.random() # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y, z + r), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, z + r)) # Attach a random material mat_name, mat_name_out = random.choice(material_mapping) utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) import numpy as np bobj = bpy.context.object loc = np.array(bobj.location) dim = np.array(bobj.dimensions) half = dim / 2 corners = [] corners.append(loc + half * [1, 1, 1]) corners.append(loc + half * [1, 1, -1]) corners.append(loc + half * [1, -1, 1]) corners.append(loc + half * [1, -1, -1]) corners.append(loc + half * [-1, 1, 1]) corners.append(loc + half * [-1, 1, -1]) corners.append(loc + half * [-1, -1, 1]) corners.append(loc + half * [-1, -1, -1]) import mathutils corners_camera_coords = np.array([ utils.get_camera_coords(camera, mathutils.Vector(tuple(corner))) for corner in corners ]) xmax = np.amax(corners_camera_coords[:, 0]) ymax = np.amax(corners_camera_coords[:, 1]) xmin = np.amin(corners_camera_coords[:, 0]) ymin = np.amin(corners_camera_coords[:, 1]) objects.append({ 'shape': obj_name_out, 'r': r, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, 'xmin': xmin, 'ymin': ymin, 'xmax': xmax, 'ymax': ymax }) # Check that all objects are at least partially visible in the rendered image all_visible = check_visibility(blender_objects, args.min_pixels_per_object) if not all_visible: # If any of the objects are fully occluded then start over; delete all # objects from the scene and place them all again. print('Some objects are occluded; replacing objects') for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera) for obj in objects: print(obj['shape'], obj['color']) return objects, blender_objects
def add_random_objects(view_struct, num_objects, args, cams): """ Add random objects to the current blender scene """ # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = {cam.name: [] for cam in cams} blender_objects = [] texts = [] blender_texts = [] all_chars = [] for i in range(num_objects): # Choose a random size size_name, r = ('large', 0.7) #random.choice(size_mapping) # Try to place the object, ensuring that we don't intersect any existing # objects and that we are more than the desired margin away from all existing # objects along all cardinal directions. num_tries = 0 while True: # If we try and fail to place an object too many times, then delete all # the objects in the scene and start over. num_tries += 1 if num_tries > args.max_retries: for obj in blender_objects: utils.delete_object(obj) for text in blender_texts: utils.delete_object(text) return add_random_objects(view_struct, num_objects, args, cams) x = uniform(-3, 3) y = uniform(-3, 3) # Check to make sure the new object is further than min_dist from all # other objects, and further than margin along the four cardinal directions dists_good = True margins_good = True for (xx, yy, rr) in positions: dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) if dist - r - rr < args.min_dist: dists_good = False break for direction_name in ['left', 'right', 'front', 'behind']: direction_vec = view_struct['cc']['directions'][ direction_name] assert direction_vec[2] == 0 margin = dx * direction_vec[0] + dy * direction_vec[1] if 0 < margin < args.margin: __builtin__.print(margin, args.margin, direction_name) __builtin__.print('BROKEN MARGIN!') margins_good = False break if not margins_good: break if dists_good and margins_good: break # Choose random color and shape if shape_color_combos is None: obj_name, obj_name_out = choice(object_mapping) color_name, rgba = choice(list(color_name_to_rgba.items())) else: obj_name_out, color_choices = choice(shape_color_combos) color_name = choice(color_choices) obj_name = [k for k, v in object_mapping if v == obj_name_out][0] rgba = color_name_to_rgba[color_name] # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) # Choose random orientation for the object. theta = 360.0 * random() # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) __builtin__.print("added random object " + str(i)) # Attach a random material mat_name, mat_name_out = choice(material_mapping) utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure for cam in cams: pixel_coords = utils.get_camera_coords(cam, obj.location) objects[cam.name].append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) # Generate Text num_chars = 1 # random.choice(range(1, 7)) chars = choice( string.ascii_lowercase ) # "".join([random.choice(string.printable[:36]) for _ in range(num_chars)]) # Add text to Blender if args.text: try: word_bboxes, char_bboxes, chars = utils.add_text( chars, args.random_text_rotation, cams) all_chars.extend(chars) except Exception as e: return purge(blender_objects, blender_texts, view_struct, num_objects, args, cams) # Select material and color for text text = bpy.context.scene.objects.active temp_dict = color_name_to_rgba.copy() del temp_dict[color_name] mat_name, mat_name_out = choice(material_mapping) color_name, rgba = choice(list(temp_dict.items())) utils.add_material(mat_name, Color=rgba) for char in chars: bpy.context.scene.objects.active = char utils.add_material(mat_name, Color=rgba) blender_texts.append(text) __builtin__.print("added text to object " + str(i)) # Check that all objects are at least partially visible in the rendered image for cam in cams: bpy.context.scene.camera = cam all_objects_visible, visible_chars = check_visibility( blender_objects + all_chars, args.min_pixels_per_object, cams) for textid, visible_pixels in visible_chars.items(): for char_bbox in char_bboxes[cam.name]: if char_bbox['id'] == textid: char_bbox['visible_pixels'] = visible_pixels all_chars_visible = [ c['visible_pixels'] > args.min_char_pixels for c in char_bboxes['cc'] ] if args.all_chars_visible and not all(all_chars_visible): __builtin__.print( "not all characters were visible, purging and retrying...") return purge(blender_objects, blender_texts, view_struct, num_objects, args, cams) for cam in cams: x, y, _ = utils.get_camera_coords(cam, text.location) objects[cam.name][-1]['text'] = { "font": text.data.font.name, "body": text.data.body, "3d_coords": tuple(text.location), "pixel_coords": (x / bpy.context.scene.render.resolution_x, y / bpy.context.scene.render.resolution_y), "color": color_name, "char_bboxes": char_bboxes, "word_bboxes": word_bboxes } else: all_objects_visible, visible_chars = check_visibility( blender_objects + all_chars, args.min_pixels_per_object, cams) if args.enforce_obj_visibility and not all_objects_visible: __builtin__.print( "not all objects were visible, purging and retrying...") return purge(blender_objects, blender_texts, view_struct, num_objects, args, cams) return texts, blender_texts, objects, blender_objects
def add_random_objects(scene_struct, num_objects, args, camera, scene_idx=0): """ Add random objects to the current blender scene """ # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] last_obj_params = [] for i in range(num_objects): # Choose random color and shape obj_name, obj_name_out = random.choice(object_mapping) while i != 0 and obj_name_out == "tray": obj_name, obj_name_out = random.choice(object_mapping) if i == 0: if np.random.rand() > 0.5: obj_name, obj_name_out = ("Tray", "tray") if obj_name_out == "tray": color_name, rgba = "gray", [0.66, 0.66, 0.66, 1] else: color_name, rgba = random.choice(list(color_name_to_rgba.items())) # Choose a random size if obj_name_out == "tray": size_name, r = "large", 0.6 else: size_name, r = random.choice(size_mapping) # Attach a random material mat_name, mat_name_out = random.choice(material_mapping) # Try to place the object, ensuring that we don't intersect any existing # objects and that we are more than the desired margin away from all existing # objects along all cardinal directions. num_tries = 0 while True: # If we try and fail to place an object too many times, then delete all # the objects in the scene and start over. num_tries += 1 if num_tries > args.max_retries: for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera) if np.random.rand() > 0.5 and \ last_obj_params != [] and \ ("Cube" in last_obj_params[4] or "Cylinder" in last_obj_params[4]) and \ last_obj_params[2] < 1: x = last_obj_params[0] + random.uniform(-0.3, 0.3) y = last_obj_params[1] + random.uniform(-0.3, 0.3) z = last_obj_params[2] + (2 * last_obj_params[3]) min_dist = 0 directions_to_check = [] elif np.random.rand() > 0 and \ last_obj_params != [] and \ ("Tray" in last_obj_params[4]): x = last_obj_params[0] + random.uniform(-0.3, 0.3) y = last_obj_params[1] + random.uniform(-0.3, 0.3) z = last_obj_params[2] min_dist = -10 directions_to_check = [] else: x = random.choice(np.linspace(-2, 2, 25, endpoint=True)) y = random.choice(np.linspace(-2, 2, 25, endpoint=True)) z = random.choice(np.linspace(0, 2, 25, endpoint=True)) if obj_name_out == "tray": z = random.choice(np.linspace(0, 1, 25, endpoint=True)) # x = 0 # y = 0 # z = 0 min_dist = args.min_dist directions_to_check = [ x for x in scene_struct['directions'].keys() ] # Check to make sure the new object is further than min_dist from all # other objects, and further than margin along the four cardinal directions dists_good = True margins_good = True for (xx, yy, zz, rr) in positions: dx, dy, dz = x - xx, y - yy, z - zz dist = math.sqrt(dx * dx + dy * dy + dz * dz) if dist - r - rr < min_dist: # print('BROKEN DISTANCE!', dist - r - rr, min_dist) dists_good = False break for direction_name in directions_to_check: direction_vec = scene_struct['directions'][direction_name] margin = dx * direction_vec[0] + dy * direction_vec[ 1] + dz * direction_vec[2] if 0 < margin < args.margin: # print(margin, args.margin, direction_name) # print('BROKEN MARGIN!') margins_good = False break if not margins_good: break if dists_good and margins_good: break # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) # Choose random orientation for the object. # theta = 360.0 * random.random() theta = 0 # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y, z), theta=theta) last_obj_params = [x, y, z, r, obj_name] utils.add_material(mat_name, Color=rgba) obj = bpy.context.object blender_objects.append(obj) # if obj_name_out != "tray": positions.append((x, y, z, r)) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, 'r': r, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) if obj_name_out == "tray": objects[-1]["mask_color"] = [0.66, 0.66, 0.66] # Check that all objects are at least partially visible in the rendered image all_visible = check_visibility(blender_objects, objects, args.min_pixels_per_object) if not all_visible: # If any of the objects are fully occluded then start over; delete all # objects from the scene and place them all again. print('Some objects are occluded or too small; replacing objects') for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera) return objects, blender_objects
def add_random_objects(scene_struct, num_objects, args, camera): """ Add random objects to the current blender scene """ # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] # Choose between disks.blend and leaf.obj leaf_disk = False leaf_properties = properties['shapes'].copy() leaf_properties.pop('sphere') leaf_obj_mapping = [(v, k) for k, v in leaf_properties.items()] size_mapping = list(properties['sizes'].items()) print("size mapping: ", size_mapping) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] init_rot = 0 size_name, r = random.choice(size_mapping) color_name, rgba = random.choice(list(color_name_to_rgba.items())) ''' WORKFLOW: First select nb of rows - 1 being bottom-most For each row, select nb of leaves - each row has a tilt angle that's a function of the row For each leaf, select angular position of leaf around z-axis. ensure leaves don't fully overlap ''' nb_rows = random.randint(1, 3) # TEST CASE: # nb_rows = 4 size_map_sorted = sorted(size_mapping, key=lambda x: x[1]) size_map_sorted.reverse() # Position of leaves x = 0.0 y = 0.0 for row in range(nb_rows): # For each row pick nb of leaves nb_leaves_per_row = random.randint(3, 7) # TEST CASE: #nb_leaves_per_row = 4 # nb_leaves + 1 (coz sphere) --> change for i in range(nb_leaves_per_row): theta = math.pi * (random.choice( list(np.arange(row * 20, (row + 1) * 20, 0.5)))) / 180 # lower leaves are less tilted # Pick largest leaves for lowest rows, and decrease leaf size as rows increase (may need to be modified for more randomness) #size_name, r = size_map_sorted[row] size_name, r = random.choice(size_mapping) color_name, rgba = random.choice(list(color_name_to_rgba.items())) if not positions: z = r obj_name_out = str('sphere') obj_name = properties['shapes']['sphere'] else: z = 0.0 if leaf_disk == True: obj_name, obj_name_out = random.choice(leaf_obj_mapping) else: obj_name_out = str('leaf') obj_name = str('leaf') # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y, z), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) # TEST CASE: CHECK ORIENTATION print("theta: ", theta, " for obj: ", obj) # Attach a random material mat_name, mat_name_out = random.choice(material_mapping) utils.add_material(mat_name, Color=rgba) # Attach a random material mat_name, mat_name_out = random.choice(material_mapping) utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) # Rotate objects on axis of central sphere before placing next object # Create a parent and add children parent_object = blender_objects[0] bpy.context.object.rotation_mode = 'XYZ' if (len(positions) > 1 and obj.type == "MESH"): obj.select = True parent_object.select = True obj.parent = parent_object obj.matrix_parent_inverse = parent_object.matrix_world.inverted( ) rot_angle_deg = 360.0 / (float(nb_leaves_per_row - 1) ) # to have some overlap between objects rot_angle = (3.14159 * rot_angle_deg / 180) # print("Rotated by: ", rot_angle - init_rot, " & rotation angle was: ", rot_angle) init_rot = rot_angle # Info note: The axis of interest is indexed by bpy.data.objects['ObjName'].rotation_euler[2] bpy.context.scene.objects.active = bpy.data.objects[ parent_object.name] bpy.context.object.rotation_euler[ 2] = bpy.context.object.rotation_euler[2] + rot_angle parent_object.select = False obj.select = False bpy.ops.object.select_all(action='DESELECT') # Check that all objects are at least partially visible in the rendered image all_visible = check_visibility(blender_objects, args.min_pixels_per_object) return objects, blender_objects
def add_objects_from_json(scene_struct, args, camera): """ Read json created by our unity simulation tool and read object properties to add objects """ # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = sorted([ (v, k) for k, v in properties['materials'].items() ]) object_mapping = sorted([(v, k) for k, v in properties['shapes'].items()]) size_mapping = sorted(list(properties['sizes'].items()), reverse=True) with open(args.reconstructed_json, 'r') as f: scene = json.load(f) print(len(scene['objectStates'])) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) num_objects = len(scene['objectStates']) positions = [] objects = [] blender_objects = [] for i in range(num_objects): object_representation = json.loads(scene['objectStates'][i]) #get object size size_name, r = get_object_size(object_representation, size_mapping) #get object position x, y, z = get_object_position(object_representation) #get color and shape obj_name, obj_name_out, color_name, rgba = get_shape_and_color( object_representation, object_mapping, sorted(list(color_name_to_rgba.items()))) # fix this calculate orientation from Quaternion # Choose random orientation for the object. theta = 360.0 * random.random() # Actually add the object to the scene utils.add_object_to_3d(args.shape_dir, obj_name, r, (x, y, z), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) # Attach a random material mat_name, mat_name_out = get_material(object_representation, material_mapping) print(mat_name) print(mat_name_out) utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) return objects, blender_objects
def add_random_objects(scene_struct, num_objects, args, camera, output_mask="mask.png"): """ Add random objects to the current blender scene """ # Load the property file with open(args.properties_json, "r") as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties["colors"].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties["materials"].items()] object_mapping = [(v, k) for k, v in properties["shapes"].items()] size_mapping = list(properties["sizes"].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, "r") as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] for i in range(num_objects): # Choose a random size size_name, r = random.choice(size_mapping) # Try to place the object, ensuring that we don't intersect any existing # objects and that we are more than the desired margin away from all existing # objects along all cardinal directions. num_tries = 0 while True: # If we try and fail to place an object too many times, then delete all # the objects in the scene and start over. num_tries += 1 if num_tries > args.max_retries: for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera, output_mask=output_mask) x = random.uniform(-3, 3) y = random.uniform(-3, 3) # Check to make sure the new object is further than min_dist from all # other objects, and further than margin along the four cardinal directions dists_good = True margins_good = True for (xx, yy, rr) in positions: dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) if dist - r - rr < args.min_dist: dists_good = False break for direction_name in ["left", "right", "front", "behind"]: direction_vec = scene_struct["directions"][direction_name] assert direction_vec[2] == 0 margin = dx * direction_vec[0] + dy * direction_vec[1] if 0 < margin < args.margin: print(margin, args.margin, direction_name) print("BROKEN MARGIN!") margins_good = False break if not margins_good: break if dists_good and margins_good: break # Choose random color and shape if shape_color_combos is None: obj_name, obj_name_out = random.choice(object_mapping) color_name, rgba = random.choice(list(color_name_to_rgba.items())) else: obj_name_out, color_choices = random.choice(shape_color_combos) color_name = random.choice(color_choices) obj_name = [k for k, v in object_mapping if v == obj_name_out][0] rgba = color_name_to_rgba[color_name] # For cube, adjust the size a bit if obj_name == "Cube": r /= math.sqrt(2) # Choose random orientation for the object. theta = 360.0 * random.random() # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) # Attach a random material mat_name, mat_name_out = random.choice(material_mapping) utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ "shape": obj_name_out, "size": size_name, "material": mat_name_out, "3d_coords": tuple(obj.location), "rotation": theta, "pixel_coords": pixel_coords, "color": color_name, "mask_color": tuple(), }) # Check that all objects are at least partially visible in the rendered image all_visible = check_visibility(blender_objects, objects, args.min_pixels_per_object, output_mask=output_mask) if not all_visible: # If any of the objects are fully occluded then start over; delete all # objects from the scene and place them all again. print("Some objects are occluded; replacing objects") for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera, output_mask=output_mask) return objects, blender_objects
def relchange_random(scene_struct, blender_objects, camera, args): num_objs = len(blender_objects) n_rand = int(random.uniform(0, 1) * num_objs) obj = blender_objects[n_rand] loc = obj.location r = loc[2] size_name = scene_struct['objects'][n_rand]['size'] shape = scene_struct['objects'][n_rand]['shape'] color = scene_struct['objects'][n_rand]['color'] mat_name = scene_struct['objects'][n_rand]['material'] theta = scene_struct['objects'][n_rand]['rotation'] utils.delete_object(obj) scene_struct['objects'].pop(n_rand) blender_objects.pop(n_rand) objects = scene_struct['objects'] positions = [obj.location for obj in blender_objects] num_tries = 0 while True: num_tries += 1 dists_good = True margins_good = True x = random.uniform(-3, 3) y = random.uniform(-3, 3) dx_s, dy_s = x - loc[0], y - loc[1] dist = math.sqrt(dx_s * dx_s + dy_s * dy_s) if dist < 4: dists_good = False continue for (xx, yy, rr) in positions: dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) if dist - r - rr < args.min_dist: #print(dist - r - rr) dists_good = False break for direction_name in ['left', 'right', 'front', 'behind']: direction_vec = scene_struct['directions'][direction_name] assert direction_vec[2] == 0 margin = dx * direction_vec[0] + dy * direction_vec[1] if 0 < margin < args.margin: margins_good = False break if num_tries > 10 and not (dists_good and margins_good): n_rand = int(random.uniform(0, num_objs - 1)) obj = blender_objects[n_rand] loc = obj.location r = loc[2] num_tries = 0 if dists_good and margins_good: break # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) shape_name = properties['shapes'][shape] rgba = color_name_to_rgba[color] # Actually add the object to the scene utils.add_object(args.shape_dir, shape_name, r, (x, y), theta=theta) obj = bpy.context.active_object blender_objects.append(obj) positions.append((x, y, r)) utils.add_material(properties['materials'][mat_name], Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) bbox = camera_view_bounds_2d(bpy.context.scene, camera, obj) objects.append({ 'shape': shape, #obj_name_out 'size': size_name, 'material': mat_name, #_out '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'bbox': bbox.to_tuple(), 'color': color, #_name }) scene_struct['objects'] = objects return blender_objects, scene_struct
def add_random_objects(scene_struct, num_objects, args, camera): """ Add random objects to the current blender scene """ # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] if balanced_num_shapes_flag: chosen_objects = [ object_mapping[j] for j in range(NUM_SHAPES) for _ in range(num_objects[j]) ] range_num = sum(num_objects) else: range_num = num_objects for i in range(range_num): # Choose a random size size_name, r = random.choice(size_mapping) # Try to place the object, ensuring that we don't intersect any existing # objects and that we are more than the desired margin away from all existing # objects along all cardinal directions. num_tries = 0 while True: # If we try and fail to place an object too many times, then delete all # the objects in the scene and start over. num_tries += 1 if num_tries > args.max_retries: for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera) x = random.uniform(-3, 3) y = random.uniform(-3, 3) # Check to make sure the new object is further than min_dist from all # other objects, and further than margin along the four cardinal directions dists_good = True margins_good = True for (xx, yy, rr) in positions: dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) if dist - r - rr < args.min_dist: dists_good = False break for direction_name in ['left', 'right', 'front', 'behind']: direction_vec = scene_struct['directions'][direction_name] assert direction_vec[2] == 0 margin = dx * direction_vec[0] + dy * direction_vec[1] if 0 < margin < args.margin: print(margin, args.margin, direction_name) print('BROKEN MARGIN!') margins_good = False break if not margins_good: break if dists_good and margins_good: break # Choose random color and shape if shape_color_combos is None: # Need to change this line to just choose one of the pre-chosen shapes. # obj_name, obj_name_out = random.choice(object_mapping) # Here, obj_name_out is "cube", "sphere", or "cylinder" if balanced_num_shapes_flag: obj_name, obj_name_out = chosen_objects[i] else: obj_name, obj_name_out = random.choice(object_mapping) color_name, rgba = random.choice(list(color_name_to_rgba.items())) else: obj_name_out, color_choices = random.choice(shape_color_combos) color_name = random.choice(color_choices) obj_name = [k for k, v in object_mapping if v == obj_name_out][0] rgba = color_name_to_rgba[color_name] # Get a random material mat_name, mat_name_out = random.choice(material_mapping) # Here, check if any of the chosen properties are disallowed. # If so, then keep randomly selecting again until no pair is disallowed. # Unfortunately, this will remove any guarantees about the distribution of labels. while obj_has_conflict(size_name, obj_name_out, mat_name_out, color_name): size_name, r = random.choice(size_mapping) obj_name, obj_name_out = random.choice(object_mapping) mat_name, mat_name_out = random.choice(material_mapping) color_name, rgba = random.choice(list(color_name_to_rgba.items())) # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) # Choose random orientation for the object. theta = 360.0 * random.random() # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) # Attach the chosen material and color. utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) # Check that all objects are at least partially visible in the rendered image all_visible = check_visibility(blender_objects, args.min_pixels_per_object) if not all_visible: # If any of the objects are fully occluded then start over; delete all # objects from the scene and place them all again. print('Some objects are occluded; replacing objects') for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera) return objects, blender_objects
def add_specific_objects(scene_struct, object_dict, num_objects, args, camera): """ Add specific objects to the current blender scene """ # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] for i in range(num_objects): specific_object = object_dict[str(i)] size_idx = specific_object["size"] colour_idx = specific_object["colour"] material_idx = specific_object["material"] object_type_idx = specific_object["object_type"] orientation_spec = specific_object["orientation"] x_spec = specific_object["x"] y_spec = specific_object["y"] size_name, r = size_idx # Try to place the object, ensuring that we don't intersect any existing # objects and that we are more than the desired margin away from all existing # objects along all cardinal directions. num_tries = 0 while True: # If we try and fail to place an object too many times, then delete all # the objects in the scene and start over. num_tries += 1 if num_tries > args.max_retries: for obj in blender_objects: utils.delete_object(obj) #return add_random_objects(scene_struct, num_objects, args, camera) return None, None x = x_spec y = y_spec # Check to make sure the new object is further than min_dist from all # other objects, and further than margin along the four cardinal directions dists_good = True margins_good = True for (xx, yy, rr) in positions: dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) if dist - r - rr < args.min_dist: dists_good = False break for direction_name in ['left', 'right', 'front', 'behind']: direction_vec = scene_struct['directions'][direction_name] assert direction_vec[2] == 0 margin = dx * direction_vec[0] + dy * direction_vec[1] if 0 < margin < args.margin: print(margin, args.margin, direction_name) print('BROKEN MARGIN!') margins_good = False break if not margins_good: break if dists_good and margins_good: break # Choose random color and shape if shape_color_combos is None: obj_name, obj_name_out = object_type_idx color_name, rgba = colour_idx else: fdhkfhddfh # TODO: fail gracefully # obj_name_out, color_choices = random.choice(shape_color_combos) # color_name = random.choice(color_choices) # obj_name = [k for k, v in object_mapping if v == obj_name_out][0] # rgba = color_name_to_rgba[color_name] # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) # Choose random orientation for the object. theta = 360.0 * orientation_spec # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) # Attach a random material mat_name, mat_name_out = material_idx utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) # Check that all objects are at least partially visible in the rendered image all_visible = check_visibility(blender_objects, args.min_pixels_per_object) if not all_visible: # If any of the objects are fully occluded then start over; delete all # objects from the scene and place them all again. print('Some objects are occluded; replacing objects') for obj in blender_objects: utils.delete_object(obj) #return add_random_objects(scene_struct, num_objects, args, camera) return None, None return objects, blender_objects
def add_random_objects(scene_struct, num_objects, args, camera, frame): """ Add random objects to the current blender scene """ flag = 0 # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] for i in range(num_objects): # Choose a random size # size_name, r = random.choice(size_mapping) # yuji_size # size_name = "small" # r = 0.35 size_name = "big" r = args.Objsize # Try to place the object, ensuring that we don't intersect any existing # objects and that we are more than the desired margin away from all existing # objects along all cardinal directions. num_tries = 0 while True: # If we try and fail to place an object too many times, then delete all # the objects in the scene and start over. num_tries += 1 if num_tries > args.max_retries: for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera) # shana_position # x = random.uniform(-3, 3) # y = random.uniform(-3, 3) x = pos[frame][0] y = pos[frame][1] # print("(x,y) = ("+str(x)+","+str(y)+")") # Check to make sure the new object is further than min_dist from all # other objects, and further than margin along the four cardinal directions dists_good = True margins_good = True for (xx, yy, rr) in positions: dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) if dist - r - rr < args.min_dist: dists_good = False break for direction_name in ['left', 'right', 'front', 'behind']: direction_vec = scene_struct['directions'][direction_name] assert direction_vec[2] == 0 margin = dx * direction_vec[0] + dy * direction_vec[1] if 0 < margin < args.margin: print(margin, args.margin, direction_name) print('BROKEN MARGIN!') margins_good = False break if not margins_good: break if dists_good and margins_good: break # Choose random color and shape if shape_color_combos is None: # yuji # print("shana") obj_name, obj_name_out = random.choice(object_mapping) obj_name = "SmoothCube_v2" obj_name = args.Objname obj_name_out = "cube" # obj_name = "Sphere" # obj_name_out = "sphere" # print(obj_name) # print(obj_name_out) color_name, rgba = random.choice(list(color_name_to_rgba.items())) # color_name = "red" # color_name = "yellow" col = (args.Objco).split(",") rgba = [] for sh in range(0, 4): rgba.append(float(col[sh])) # if args.Objco == 0: #Red # rgba = [0.6784313725490196, 0.13725490196078433, 0.13725490196078433, 1.0] # elif args.Objco == 1: #Gray # rgba = [0.341176, 0.341176, 0.341176, 1.0] # elif args.Objco == 2: #Blue # rgba = [0.164705, 0.294117, 0.84313, 1.0] # elif args.Objco == # else:#Yellow # rgba = [1.0,0.933333,0.2,1.0] # print(color_name) # print(rgba) else: obj_name_out, color_choices = random.choice(shape_color_combos) color_name = random.choice(color_choices) obj_name = [k for k, v in object_mapping if v == obj_name_out][0] rgba = color_name_to_rgba[color_name] # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) # Choose random orientation for the object. # theta = 360.0 * random.random() theta = 348.20058907697677 # print(theta) # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) # Attach a random material # mat_name, mat_name_out = random.choice(material_mapping) mat_name = "Rubber" mat_name_out = "rubber" # print(mat_name) # print(mat_name_out) utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) # Check that all objects are at least partially visible in the rendered image # all_visible = check_visibility(blender_objects, args.min_pixels_per_object) # if not all_visible: # flag = 1 # # # If any of the objects are fully occluded then start over; delete all # # # objects from the scene and place them all again. # # print('Some objects are occluded; replacing objects') # # for obj in blender_objects: # # utils.delete_object(obj) # # return add_random_objects(scene_struct, num_objects, args, camera) return objects, blender_objects , flag
def add_random_objects(scene_struct, parameters, args, camera): """ Add random objects to the current blender scene """ #TODO: changed sigature, num_objects changed to parameters # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) # shape_color_combos = None # if args.shape_color_combos_json is not None: # with open(args.shape_color_combos_json, 'r') as f: # shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] for i in range(len(parameters)): # # Choose a random size # size_name, r = random.choice(size_mapping) # # # Try to place the object, ensuring that we don't intersect any existing # # objects and that we are more than the desired margin away from all existing # # objects along all cardinal directions. # num_tries = 0 # while True: # # If we try and fail to place an object too many times, then delete all # # the objects in the scene and start over. # num_tries += 1 # if num_tries > args.max_retries: # for obj in blender_objects: # utils.delete_object(obj) # return add_random_objects(scene_struct, num_objects, args, camera) # x = random.uniform(-3, 3) # y = random.uniform(-3, 3) # # Check to make sure the new object is further than min_dist from all # # other objects, and further than margin along the four cardinal directions # dists_good = True # margins_good = True # for (xx, yy, rr) in positions: # dx, dy = x - xx, y - yy # dist = math.sqrt(dx * dx + dy * dy) # if dist - r - rr < args.min_dist: # dists_good = False # break # for direction_name in ['left', 'right', 'front', 'behind']: # direction_vec = scene_struct['directions'][direction_name] # assert direction_vec[2] == 0 # margin = dx * direction_vec[0] + dy * direction_vec[1] # if 0 < margin < args.margin: # print(margin, args.margin, direction_name) # print('BROKEN MARGIN!') # margins_good = False # break # if not margins_good: # break # # if dists_good and margins_good: # break # # # Choose random color and shape # if shape_color_combos is None: # obj_name, obj_name_out = random.choice(object_mapping) # color_name, rgba = random.choice(list(color_name_to_rgba.items())) # else: # obj_name_out, color_choices = random.choice(shape_color_combos) # color_name = random.choice(color_choices) # obj_name = [k for k, v in object_mapping if v == obj_name_out][0] # rgba = color_name_to_rgba[color_name] # # # For cube, adjust the size a bit # if obj_name == 'Cube': # r /= math.sqrt(2) objct = parameters[i] size_name = objct["size_name"] x, y, r = objct["position"] obj_name = objct["obj_name"] obj_name_out = objct["obj_name_out"] color_name = objct["color_name"] rgba = objct["rgba"] mat_name = objct["mat_name"] mat_name_out = objct["mat_name_out"] theta = objct["theta"] # obj = {"size_name": size_name, "position": [x, y, y], "obj_name": obj_name, "obj_name_out": obj_name_out, # "color_name": color_name, "rgba": rgba, "mat_name": mat_name, "mat_name_out": mat_name_out} # Choose random orientation for the object. #theta = 360.0 * random.random() # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) # Attach a random material # mat_name, mat_name_out = random.choice(material_mapping) utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) # Check that all objects are at least partially visible in the rendered image all_visible = check_visibility(blender_objects, args.min_pixels_per_object) if not all_visible: # If any of the objects are fully occluded then start over; delete all # objects from the scene and place them all again. # print('Some objects are occluded; replacing objects') # for obj in blender_objects: # utils.delete_object(obj) # return add_random_objects(scene_struct, num_objects, args, camera) print("not all visible") return [], [], False return objects, blender_objects, True
def add_random_objects(scene_struct, num_objects, args, inp, img_config, camera): """ Add random objects to the current blender scene """ # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] for i in range(num_objects): # Choose a random size user_obj = img_config.objects[i] size_name = user_obj['size'] assert size_name in properties[ 'sizes'], "Size not defined in properties.json" r = properties['sizes'][size_name] # size_name, r = random.choice(size_mapping) # Try to place the object, ensuring that we don't intersect any existing # objects and that we are more than the desired margin away from all existing # objects along all cardinal directions. num_tries = 0 while True: # If we try and fail to place an object too many times, then delete all # the objects in the scene and start over. num_tries += 1 if num_tries > args.max_retries: for obj in blender_objects: utils.delete_object(obj) print("Failed to place objects") print(dists_good, margins_good) sys.exit( "Failed to place objects. Check `user_config.py` for image {image_index}, object {i}" .format(image_index=image_index, i=i)) dy = lambda: random.uniform(-0.45, 0.45) clamp = lambda x: min(2.95, max(-2.95, x)) x = clamp(user_obj['x']) y = clamp(user_obj['y']) z = user_obj['z'] # Check to make sure the new object is further than min_dist from all # other objects, and further than margin along the four cardinal directions dists_good = True margins_good = True for (xx, yy, rr) in positions: dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) if dist - r - rr < args.min_dist: dists_good = False break for direction_name in ['left', 'right', 'front', 'behind']: direction_vec = scene_struct['directions'][direction_name] assert direction_vec[2] == 0 margin = dx * direction_vec[0] + dy * direction_vec[1] if 0 < margin < args.margin: print(margin, args.margin, direction_name) print('BROKEN MARGIN!') margins_good = False break if not margins_good: break if dists_good and margins_good: break # Choose random color and shape if shape_color_combos is None: # obj_name, obj_name_out = random.choice(object_mapping) # color_name, rgba = random.choice(list(color_name_to_rgba.items())) obj_name_out = user_obj['shape'] color_name = user_obj['color'] assert obj_name_out in properties[ 'shapes'], "Shape not defined in properties.json" assert color_name in color_name_to_rgba, "Color not defined in properties.json" obj_name = properties['shapes'][obj_name_out] rgba = color_name_to_rgba[color_name] else: obj_name_out, color_choices = random.choice(shape_color_combos) color_name = random.choice(color_choices) obj_name = [k for k, v in object_mapping if v == obj_name_out][0] rgba = color_name_to_rgba[color_name] # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) # Choose random orientation for the object. theta = user_obj[ 'orientation'] if 'orientation' in user_obj else 360.0 * random.random( ) # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y, z), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) # Attach a random material # mat_name, mat_name_out = random.choice(material_mapping) mat_name_out = user_obj['material'] assert mat_name_out in properties[ 'materials'], "Material not defined in properties.json" mat_name = properties['materials'][mat_name_out] utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) # Check that all objects are at least partially visible in the rendered image all_visible = check_visibility(blender_objects, args.min_pixels_per_object) if not all_visible: # If any of the objects are fully occluded then start over; delete all # objects from the scene and place them all again. print('Some objects are occluded; replacing objects') for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, inp, img_config, camera) return objects, blender_objects
def add_random_objects(scene_struct, num_objects, args, camera): """ Add random objects to the current blender scene """ # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] for i in range(num_objects): if i == 0: # first element is the small shiny gold "snitch"! size_name, r = "small", 0.3 # slightly larger than small obj_name, obj_name_out = 'Spl', 'spl' color_name = "gold" rgba = [1.0, 0.843, 0.0, 1.0] mat_name, mat_name_out = "MyMetal", "metal" elif i == 1: # second element is a medium cone size_name, r = "medium", 0.5 obj_name, obj_name_out = 'Cone', 'cone' color_name, rgba = random.choice(list(color_name_to_rgba.items())) mat_name, mat_name_out = random.choice(material_mapping) elif i == 2: # third element is a large cone size_name, r = "large", 0.75 obj_name, obj_name_out = 'Cone', 'cone' color_name, rgba = random.choice(list(color_name_to_rgba.items())) mat_name, mat_name_out = random.choice(material_mapping) else: # Choose a random size size_name, r = random.choice(size_mapping) # Choose random color and shape if shape_color_combos is None: obj_name, obj_name_out = random.choice(object_mapping) color_name, rgba = random.choice( list(color_name_to_rgba.items())) else: obj_name_out, color_choices = random.choice(shape_color_combos) color_name = random.choice(color_choices) obj_name = [k for k, v in object_mapping if v == obj_name_out][0] rgba = color_name_to_rgba[color_name] # Choose a random material mat_name, mat_name_out = random.choice(material_mapping) # Try to place the object, ensuring that we don't intersect any # existing objects and that we are more than the desired margin away # from all existing objects along all cardinal directions. num_tries = 0 while True: # If we try and fail to place an object too many times, then # delete all the objects in the scene and start over. num_tries += 1 if num_tries > args.max_retries: for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera) x = random.uniform(-3, 3) y = random.uniform(-3, 3) # Check to make sure the new object is further than min_dist from # all other objects, and further than margin along the four # cardinal directions dists_good = True margins_good = True for (xx, yy, rr) in positions: dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) if dist - r - rr < args.min_dist: dists_good = False break for direction_name in ['left', 'right', 'front', 'behind']: direction_vec = scene_struct['directions'][direction_name] assert direction_vec[2] == 0 margin = dx * direction_vec[0] + dy * direction_vec[1] if 0 < margin < args.margin: logging.debug('{} {} {}'.format( margin, args.margin, direction_name)) logging.debug('BROKEN MARGIN!') margins_good = False break if not margins_good: break if dists_good and margins_good: break # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) # Choose random orientation for the object. # theta = 360.0 * random.random() theta = 2 * np.pi * random.random() # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) # Actually add material utils.add_material(mat_name, Color=rgba) # get bbox corners in world coord bbox_corners_world = np.array([ obj.matrix_world * Vector(corner) for corner in obj.bound_box ]) # 8 x 3 array T = np.average(bbox_corners_world, axis=0) # len-3, xyz coord in world system # try to create lrt l = [obj.dimensions.x, obj.dimensions.y, obj.dimensions.z] # R = eul2rot((0, 0, theta), degrees=True) # lx, ly, lz = l # xs = np.array([-lx/2., -lx/2., -lx/2., -lx/2., lx/2., lx/2., lx/2., lx/2.])[None, :] # 1 x 8 # ys = np.array([-ly/2., -ly/2., ly/2., ly/2., -ly/2., -ly/2., ly/2., ly/2.])[None, :] # zs = np.array([-lz/2., lz/2., -lz/2., lz/2., -lz/2., lz/2., -lz/2., lz/2.])[None, :] # xyzs_obj = np.concatenate([xs, ys, zs], axis=0) # 3 x 8 # xyzs_world = np.dot(R, xyzs) + T[:, None] # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, 'sized': r, 'material': mat_name_out, '3d_coords': tuple(obj.location), '3d_bbox': bbox_corners_world.tolist(), '3d_size': l, '3d_bbox_center': T.tolist(), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, 'instance': obj.name, }) return objects, blender_objects
def add_random_objects(scene_struct, num_objects, args, camera): """ Add random objects to the current blender scene """ # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] for i in range(num_objects): # Choose a random size size_name, r = random.choice(size_mapping) # Try to place the object, ensuring that we don't intersect any existing # objects and that we are more than the desired margin away from all existing # objects along all cardinal directions. num_tries = 0 while True: # If we try and fail to place an object too many times, then delete all # the objects in the scene and start over. num_tries += 1 if num_tries > args.max_retries: for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera) x = random.uniform(-3, 3) y = random.uniform(-3, 3) # Info Comment: For first loop, (x,y) as position and r as radius initialized above are placed in positions list. The for loop # below exists to ensure min dist between objects. # Maybe add code to limit spacing if nb of objects is low? (so if fewer objs and/or smaller size(?), closer together) # For first object, have anchor position. if not positions: x = 0.0 y = 0.0 # Check to make sure the new object is further than min_dist and closer than max distance (2(r+rr)) from all # other objects, and further than margin along the four cardinal directions dists_good = True margins_good = True # print('positions: ',positions) for (xx, yy, rr) in positions: # print("r, rr: ", r, " , ", rr) dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) max_dist = 2 * (r + rr) # print("x_dist, min_dist, max_dist: ", dist - r -rr, " , ", args.min_dist, " , ", max_dist) if (dist - r - rr < args.min_dist) or (dist - r - rr > (2 * (r + rr))): dists_good = False break for direction_name in ['left', 'right', 'front', 'behind']: direction_vec = scene_struct['directions'][direction_name] assert direction_vec[2] == 0 margin = dx * direction_vec[0] + dy * direction_vec[1] if 0 < margin < args.margin: print(margin, args.margin, direction_name) print('BROKEN MARGIN!') margins_good = False break if not margins_good: break if dists_good and margins_good: break # Choose random color and shape if shape_color_combos is None: obj_name, obj_name_out = random.choice( object_mapping) # obj_name_out is the key and obj_name is val color_name, rgba = random.choice(list(color_name_to_rgba.items())) else: obj_name_out, color_choices = random.choice(shape_color_combos) color_name = random.choice(color_choices) obj_name = [k for k, v in object_mapping if v == obj_name_out][0] rgba = color_name_to_rgba[color_name] # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) # Choose random orientation for the object. theta = 360.0 * random.random() # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) # Attach a random material mat_name, mat_name_out = random.choice(material_mapping) utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) # Check that all objects are at least partially visible in the rendered image all_visible = check_visibility(blender_objects, args.min_pixels_per_object) if not all_visible: # If any of the objects are fully occluded then start over; delete all # objects from the scene and place them all again. print('Some objects are occluded; replacing objects') for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera) return objects, blender_objects
def relative_transform_objects(scene_struct, blender_objects, camera, args): num_objs = len(blender_objects) n_rand = int(random.uniform(0, 1) * num_objs) #objects = scene_struct['objects'] positions = [obj.location for obj in blender_objects] #num_objs = len(objects) #curr_obj = 0#int(random.uniform(0, num_objs)) obj = blender_objects[n_rand] #sc_obj = scene_struct['objects'].pop(n_rand) objects = scene_struct['objects'] loc = obj.location r = loc[2] #loc_target = 2 * blender_objects[1].location #diff = loc_target - loc #print("diff: ", diff) #x_t = min(max(diff[0],-3),3) #y_t = min(max(diff[1],-3),3) num_tries = 0 while True: num_tries += 1 dists_good = True margins_good = True x = random.uniform(-3, 3) y = random.uniform(-3, 3) dx_s, dy_s = x - loc[0], y - loc[1] dist = math.sqrt(dx_s * dx_s + dy_s * dy_s) if dist < 4: dists_good = False continue for (xx, yy, rr) in positions: dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) if dist - r - rr < args.min_dist: #print(dist - r - rr) dists_good = False break for direction_name in ['left', 'right', 'front', 'behind']: direction_vec = scene_struct['directions'][direction_name] assert direction_vec[2] == 0 margin = dx * direction_vec[0] + dy * direction_vec[1] if 0 < margin < args.margin: margins_good = False break if num_tries > 10 and not (dists_good and margins_good): n_rand = int(random.uniform(0, 1) * num_objs) obj = blender_objects[n_rand] loc = obj.location r = loc[2] num_tries = 0 if dists_good and margins_good: break obj.location = Vector((x, y, r)) blender_objects[n_rand] = obj # Render the scene bpy.ops.render.render(write_still=False) pixel_coords = utils.get_camera_coords(camera, obj.location) bbox = camera_view_bounds_2d(bpy.context.scene, camera, obj) #print(sc_obj) objects[n_rand]['3d_coords'] = tuple(obj.location) objects[n_rand]['pixel_coords'] = pixel_coords objects[n_rand]['bbox'] = bbox.to_tuple() #print(sc_obj) #input() #sc_obj['3d_coords'] = tuple(obj.location) #sc_obj['pixel_coords'] = pixel_coords #sc_obj['bbox'] = bbox.to_tuple() #objects.append(sc_obj) scene_struct['objects'] = objects return blender_objects, scene_struct
def add_cups(scene_struct, num_objects, args, camera): """ Add random objects to the current blender scene """ # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) # shape_color_combos = None # if args.shape_color_combos_json is not None: # with open(args.shape_color_combos_json, 'r') as f: # shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] # Choose a random size, same for all cups size_name, r = size_mapping[0] first_cup_x = 0 first_cup_y = 0 # obj_name, obj_name_out = random.choice(object_mapping) obj_name, obj_name_out = [ el for el in object_mapping if el[1] == 'cylinder' ][0] color_name, rgba = random.choice(list(color_name_to_rgba.items())) # If using combos # obj_name_out, color_choices = random.choice(shape_color_combos) # color_name = random.choice(color_choices) # obj_name = [k for k, v in object_mapping if v == obj_name_out][0] # rgba = color_name_to_rgba[color_name] # Attach a random material mat_name, mat_name_out = random.choice(material_mapping) # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) # Choose random orientation for the object. # theta = 360.0 * random.random() theta = 0.0 for i in range(num_objects): x = first_cup_x + i * 1.5 y = first_cup_y # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) return objects, blender_objects
def render_scene(args, num_objects=5, num_images=0, output_split='none', image_template='render.png', scene_template='render_json', arr_template='arr', output_blendfile=None, directions={ 1: 'no', 2: 'no', 3: 'no', 4: 'no', 5: 'no' }): for object_name in bpy.data.objects.keys(): if 'Sphere' in object_name or\ 'Cylinder' in object_name or\ 'Cube' in object_name or\ 'Duck' in object_name or\ 'Peg' in object_name or\ 'Disk' in object_name or\ 'Bowl' in object_name: utils.delete_object_by_name(object_name) # Load materials utils.load_materials(args.material_dir) # Set render arguments so we can get pixel coordinates later. # We use functionality specific to the CYCLES renderer so BLENDER_RENDER # cannot be used. render_args = bpy.context.scene.render render_args.engine = "CYCLES" render_args.resolution_x = args.width render_args.resolution_y = args.height render_args.resolution_percentage = 100 render_args.tile_x = args.render_tile_size render_args.tile_y = args.render_tile_size if args.use_gpu == 1: # Blender changed the API for enabling CUDA at some point if bpy.app.version < (2, 78, 0): bpy.context.user_preferences.system.compute_device_type = 'CUDA' bpy.context.user_preferences.system.compute_device = 'CUDA_0' else: cycles_prefs = bpy.context.user_preferences.addons[ 'cycles'].preferences cycles_prefs.compute_device_type = 'CUDA' # Some CYCLES-specific stuff bpy.data.worlds['World'].cycles.sample_as_light = True bpy.context.scene.cycles.blur_glossy = 2.0 bpy.context.scene.cycles.samples = args.render_num_samples bpy.context.scene.cycles.transparent_min_bounces = args.render_min_bounces bpy.context.scene.cycles.transparent_max_bounces = args.render_max_bounces if args.use_gpu == 1: bpy.context.scene.cycles.device = 'GPU' # This will give ground-truth information about the scene and its objects scene_struct = { 'split': output_split, 'objects': [], 'directions': {}, } # Put a plane on the ground so we can compute cardinal directions bpy.ops.mesh.primitive_plane_add(radius=5) plane = bpy.context.object def rand(L): return 2.0 * L * (random.random() - 0.5) # Add random jitter to camera position if args.camera_jitter > 0: for i in range(3): bpy.data.objects['Camera'].location[i] += rand(args.camera_jitter) # Figure out the left, up, and behind directions along the plane and record # them in the scene structure camera = bpy.data.objects['Camera'] plane_normal = plane.data.vertices[0].normal cam_behind = camera.matrix_world.to_quaternion() * Vector((0, 0, -1)) cam_left = camera.matrix_world.to_quaternion() * Vector((-1, 0, 0)) cam_up = camera.matrix_world.to_quaternion() * Vector((0, 1, 0)) plane_behind = (cam_behind - cam_behind.project(plane_normal)).normalized() plane_left = (cam_left - cam_left.project(plane_normal)).normalized() plane_up = cam_up.project(plane_normal).normalized() # Delete the plane; we only used it for normals anyway. The base scene file # contains the actual ground plane. utils.delete_object(plane) # Save all six axis-aligned directions in the scene struct scene_struct['directions']['behind'] = tuple(plane_behind) scene_struct['directions']['front'] = tuple(-plane_behind) scene_struct['directions']['left'] = tuple(plane_left) scene_struct['directions']['right'] = tuple(-plane_left) scene_struct['directions']['above'] = tuple(plane_up) scene_struct['directions']['below'] = tuple(-plane_up) # Add random jitter to lamp positions if args.key_light_jitter > 0: for i in range(3): bpy.data.objects['Lamp_Key'].location[i] += rand( args.key_light_jitter) if args.back_light_jitter > 0: for i in range(3): bpy.data.objects['Lamp_Back'].location[i] += rand( args.back_light_jitter) if args.fill_light_jitter > 0: for i in range(3): bpy.data.objects['Lamp_Fill'].location[i] += rand( args.fill_light_jitter) objects = [] blender_objects = [] direction_vec = [] for scene_idx in range(num_images): image_path = image_template % (scene_idx + args.start_idx) render_args.filepath = image_path scene_path = scene_template % (scene_idx + args.start_idx) arr_path = arr_template % (scene_idx + args.start_idx) if scene_idx == 0: init_position = [] final_position = [] ref_obj_loc = np.array([0, 0, 1]) for axis, movement in directions.items(): # X if axis == 1: if movement != ['no']: if movement[0] == 'front': init_position.append(-3) final_position.append(2) else: init_position.append(2) final_position.append(-3) else: tmp = random.choice( np.linspace(-2, 2, 10, endpoint=True)) init_position.append(tmp) final_position.append(tmp) # Y if axis == 0: if movement != ['no']: if movement[0] == 'left': init_position.append(-2) final_position.append(2) else: init_position.append(2) final_position.append(-2) else: tmp = random.choice( np.linspace(-2, 2, 10, endpoint=True)) init_position.append(tmp) final_position.append(tmp) # Z if axis == 2: if movement != ['no']: if movement[0] == 'below': init_position.append(0) final_position.append(2) else: init_position.append(2) final_position.append(0) else: tmp = random.choice( np.linspace(0, 2, 10, endpoint=True)) init_position.append(tmp) final_position.append(tmp) # CLOSE/FAR close_far_thresh = 3 if axis == 3: if movement != ['no']: far_sample = [] close_sample = [] while far_sample == [] or \ np.linalg.norm(far_sample - ref_obj_loc) < close_far_thresh: x = random.choice( np.linspace(-2, 2, 10, endpoint=True)) y = random.choice( np.linspace(-2, 2, 10, endpoint=True)) z = random.choice( np.linspace(0.6, 2, 10, endpoint=True)) far_sample = np.array([x, y, z]) while close_sample == [] or \ np.linalg.norm(close_sample - ref_obj_loc) > close_far_thresh or \ np.linalg.norm(close_sample - ref_obj_loc) < 1: x = random.choice( np.linspace(-2, 2, 10, endpoint=True)) y = random.choice( np.linspace(-2, 2, 10, endpoint=True)) z = random.choice( np.linspace(0.6, 2, 10, endpoint=True)) close_sample = np.array([x, y, z]) if movement[0] == 'far': init_position = far_sample final_position = [] while final_position == [] or \ np.linalg.norm(final_position - ref_obj_loc) > close_far_thresh or \ np.linalg.norm(final_position - ref_obj_loc) < 1: final_position = init_position + random.uniform( 0.5, 1) * (ref_obj_loc - init_position) print(final_position) else: init_position = close_sample final_position = [] while final_position == [] or \ np.linalg.norm(final_position - ref_obj_loc) < close_far_thresh: final_position = init_position + random.uniform( 0.5, 1) * (init_position - ref_obj_loc) else: pass # init_position[1] = -3 # init_position[2] = 0 # final_position[2] = 0 print(init_position) print(final_position) init_positions = [] init_positions.append(init_position) init_positions.append(ref_obj_loc) for i in range(2, num_objects): x = random.choice(np.linspace(-2, 2, 10, endpoint=True)) y = random.choice(np.linspace(-2, 2, 10, endpoint=True)) z = random.choice(np.linspace(0, 2, 6, endpoint=True)) init_positions.append([x, y, z]) direction_vec = np.array(final_position) - np.array(init_position) # Now make some random objects objects, blender_objects = add_random_objects( scene_struct, num_objects, args, camera, init_positions) if scene_idx == 0: movement = directions[4] if movement != ['no']: far_sample = [] while far_sample == [] or \ np.linalg.norm(far_sample - ref_obj_loc) < close_far_thresh: x = random.choice(np.linspace(-2, 2, 10, endpoint=True)) y = random.choice(np.linspace(-2, 2, 10, endpoint=True)) z = random.choice( np.linspace(0.6, 2, 10, endpoint=True)) far_sample = np.array([x, y, z]) if movement[0] == 'off': init_position = far_sample final_position = np.array(blender_objects[1].location) final_position[0] += random.uniform( -objects[1]['r'], objects[1]['r']) final_position[1] += random.uniform( -objects[1]['r'], objects[1]['r']) final_position[2] += objects[0]['r'] + objects[1]['r'] blender_objects[0].location[0] = init_position[0] blender_objects[0].location[1] = init_position[1] blender_objects[0].location[2] = init_position[2] else: final_position = far_sample init_position = np.array(blender_objects[1].location) init_position[0] += random.uniform( -objects[1]['r'], objects[1]['r']) init_position[1] += random.uniform( -objects[1]['r'], objects[1]['r']) init_position[2] += objects[0]['r'] + objects[1]['r'] blender_objects[0].location[0] = init_position[0] blender_objects[0].location[1] = init_position[1] blender_objects[0].location[2] = init_position[2] else: pass direction_vec = np.array(final_position) - np.array(init_position) else: move_obj_idxs = [0] step = direction_vec / args.num_images for move_obj_idx in move_obj_idxs: move_object(blender_objects[move_obj_idx], step) pixel_coords = utils.get_camera_coords( camera, blender_objects[move_obj_idx].location) objects[move_obj_idx]['pixel_coords'] = pixel_coords # <Vector (-1.6002, -1.5445, 1.9500)> objects[move_obj_idx]['3d_coords'] = list( blender_objects[move_obj_idx].location) # <Euler (x=0.0000, y=0.0000, z=139.0579), order='XYZ'> objects[move_obj_idx]['rotation'] = blender_objects[ move_obj_idx].rotation_euler[2] ### get b_box box_dict = get_b_box.main(bpy.context, blender_objects) for _id in box_dict: objects[_id]['bbox'] = box_dict[_id] # Render the scene and dump the scene data structure scene_struct['objects'] = objects scene_struct['relationships'] = compute_all_relationships(scene_struct) ############ ADDED ############ tree = bpy.context.scene.node_tree links = tree.links rl = tree.nodes['Render Layers'] v = tree.nodes['Viewer'] links.new(rl.outputs[0], v.inputs[0]) while True: try: bpy.ops.render.render(write_still=True) break except Exception as e: print(e) links.remove(links[0]) # get viewer pixels rgb_pixels = bpy.data.images['Viewer Node'].pixels rgb_pixels = np.array(rgb_pixels[:]) rgb_pixels = np.power(rgb_pixels, 1 / 2.2) rgb_pixels[rgb_pixels > 1] = 1 rgb_pixels = rgb_pixels.reshape(args.height, args.width, 4)[..., :3] links.new(rl.outputs[2], v.inputs[0]) render_shadeless(blender_objects, lights_off=False) links.remove(links[0]) # get viewer pixels depth_pixels = bpy.data.images['Viewer Node'].pixels depth_pixels = np.array(depth_pixels[:]) depth_pixels = depth_pixels.reshape(args.height, args.width, 4)[..., 0, None] links.new(rl.outputs[0], v.inputs[0]) render_shadeless(blender_objects) links.remove(links[0]) # get viewer pixels mask_pixels = bpy.data.images['Viewer Node'].pixels mask_pixels = np.array(mask_pixels[:]) mask_pixels = mask_pixels.reshape(args.height, args.width, 4)[..., :3] pixels = np.concatenate((rgb_pixels, depth_pixels, mask_pixels), axis=2) pixels = np.flipud(pixels) utils.save_arr(pixels, arr_path) ############ ADDED ############ with open(scene_path, 'w') as f: json.dump(scene_struct, f, indent=2)
def add_random_objects(scene_struct, num_objects, args, camera): """ Add random objects to the current blender scene """ # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] for i in range(num_objects): # Choose a random size size_name, r = random.choice(size_mapping) # Try to place the object, ensuring that we don't intersect any existing # objects and that we are more than the desired margin away from all existing # objects along all cardinal directions. num_tries = 0 while True: # If we try and fail to place an object too many times, then delete all # the objects in the scene and start over. num_tries += 1 if num_tries > args.max_retries: for obj in blender_objects: utils.delete_object(obj) return add_random_objects(scene_struct, num_objects, args, camera) x = random.uniform(-3, 3) y = random.uniform(-3, 3) # Check to make sure the new object is further than min_dist from all # other objects, and further than margin along the four cardinal directions dists_good = True margins_good = True for (xx, yy, rr) in positions: dx, dy = x - xx, y - yy dist = math.sqrt(dx * dx + dy * dy) if dist - r - rr < args.min_dist: dists_good = False break for direction_name in ['left', 'right', 'front', 'behind']: direction_vec = scene_struct['directions'][direction_name] assert direction_vec[2] == 0 margin = dx * direction_vec[0] + dy * direction_vec[1] if 0 < margin < args.margin: print(margin, args.margin, direction_name) print('BROKEN MARGIN!') margins_good = False break if not margins_good: break if dists_good and margins_good: break # Choose random color and shape if shape_color_combos is None: obj_name, obj_name_out = random.choice(object_mapping) color_name, rgba = random.choice(list(color_name_to_rgba.items())) else: obj_name_out, color_choices = random.choice(shape_color_combos) color_name = random.choice(color_choices) obj_name = [k for k, v in object_mapping if v == obj_name_out][0] rgba = color_name_to_rgba[color_name] # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) # Choose random orientation for the object. theta = 360.0 * random.random() # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, r)) # Attach a random material mat_name, mat_name_out = random.choice(material_mapping) utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'name': obj.name, 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) # # Check that all objects are at least partially visible in the rendered image # all_visible = check_visibility(blender_objects, args.min_pixels_per_object, args.height, args.width, # args.crop_up, args.crop_down, args.crop_left, args.crop_right) # if not all_visible: # # If any of the objects are fully occluded then start over; delete all # # objects from the scene and place them all again. # print('Some objects are occluded; replacing objects') # for obj in blender_objects: # utils.delete_object(obj) # return add_random_objects(scene_struct, num_objects, args, camera) indices = [ n[0] for n in sorted(enumerate(objects), key=lambda x: x[1]['pixel_coords'][2], reverse=True) ] objects = [objects[idx] for idx in indices] blender_objects = [blender_objects[idx] for idx in indices] return objects, blender_objects
def add_random_objects(scene_struct, num_objects, args, camera, init_positions): """ Add random objects to the current blender scene """ # Load the property file with open(args.properties_json, 'r') as f: properties = json.load(f) color_name_to_rgba = {} for name, rgb in properties['colors'].items(): rgba = [float(c) / 255.0 for c in rgb] + [1.0] color_name_to_rgba[name] = rgba material_mapping = [(v, k) for k, v in properties['materials'].items()] object_mapping = [(v, k) for k, v in properties['shapes'].items()] size_mapping = list(properties['sizes'].items()) shape_color_combos = None if args.shape_color_combos_json is not None: with open(args.shape_color_combos_json, 'r') as f: shape_color_combos = list(json.load(f).items()) positions = [] objects = [] blender_objects = [] for i in range(num_objects): # Choose a random size size_name, r = random.choice(size_mapping) # size_name, r = size_mapping[0] # x = random.choice(np.linspace(-2, 2, 3, endpoint=True)) # y = random.choice(np.linspace(-2, 2, 3, endpoint=True)) # z = random.choice(np.linspace(0, 2, 3, endpoint=True)) # z = 0 x, y, z = init_positions[i] # Choose random color and shape if shape_color_combos is None: obj_name, obj_name_out = random.choice(object_mapping) color_name, rgba = random.choice(list(color_name_to_rgba.items())) # obj_name, obj_name_out = object_mapping[i] # color_name, rgba = list(color_name_to_rgba.items())[i] else: obj_name_out, color_choices = random.choice(shape_color_combos) color_name = random.choice(color_choices) obj_name = [k for k, v in object_mapping if v == obj_name_out][0] rgba = color_name_to_rgba[color_name] # For cube, adjust the size a bit if obj_name == 'Cube': r /= math.sqrt(2) # Choose random orientation for the object. # theta = 360.0 * random.random() theta = 0 # Actually add the object to the scene utils.add_object(args.shape_dir, obj_name, r, (x, y, z), theta=theta) obj = bpy.context.object blender_objects.append(obj) positions.append((x, y, z, r)) # Attach a random material mat_name, mat_name_out = random.choice(material_mapping) utils.add_material(mat_name, Color=rgba) # Record data about the object in the scene data structure pixel_coords = utils.get_camera_coords(camera, obj.location) objects.append({ 'shape': obj_name_out, 'size': size_name, 'material': mat_name_out, '3d_coords': tuple(obj.location), 'r': r, 'rotation': theta, 'pixel_coords': pixel_coords, 'color': color_name, }) # Check that all objects are at least partially visible in the rendered image all_visible = check_visibility(blender_objects, args.min_pixels_per_object) if not all_visible: # If any of the objects are fully occluded then start over; delete all # objects from the scene and place them all again. print('Some objects are occluded; replacing objects') for obj in blender_objects: utils.delete_object(obj) return add_random_objects( scene_struct, num_objects, args, camera, init_positions + np.random.uniform(low=-0.1, high=0.1, size=3)) return objects, blender_objects