def run(self): """ Uses the loaded .obj files and picks one randomly and loads it """ selected_obj = random.choice(self._files_with_fitting_synset) loaded_obj = Utility.import_objects(selected_obj) for obj in loaded_obj: obj["used_synset_id"] = self._used_synset_id obj["used_source_id"] = pathlib.PurePath(selected_obj).parts[-3] self._correct_materials(loaded_obj) self._set_properties(loaded_obj) if "void" in LabelIdMapping.label_id_map: # Check if using an id map for obj in loaded_obj: obj["category_id"] = LabelIdMapping.label_id_map["void"] # removes the x axis rotation found in all ShapeNet objects, this is caused by importing .obj files # the object has the same pose as before, just that the rotation_euler is now [0, 0, 0] LoaderInterface.remove_x_axis_rotation(loaded_obj) # move the origin of the object to the world origin and on top of the X-Y plane # makes it easier to place them later on, this does not change the `.location` LoaderInterface.move_obj_origin_to_bottom_mean_point(loaded_obj) bpy.ops.object.select_all(action='DESELECT')
def run(self): """ use the pose parameters to generate the mesh and loads it to the scene. """ # selected_obj = self._files_with_fitting_ids pose_body, betas = self._get_pose_parameters() # load parametric Model body_model, faces = self._load_parametric_body_model() # Generate Body representations using SMPL model body_repr = body_model(pose_body=pose_body, betas=betas) # Generate .obj file represents the selected pose generated_obj = self._write_body_mesh_to_obj_file(body_repr, faces) loaded_obj = Utility.import_objects(generated_obj) self._correct_materials(loaded_obj) self._set_properties(loaded_obj) # set the shading mode explicitly to smooth self.change_shading_mode(loaded_obj, "SMOOTH") if "void" in LabelIdMapping.label_id_map: # Check if using an id map for obj in loaded_obj: obj['category_id'] = LabelIdMapping.label_id_map["void"] # removes the x axis rotation found in all ShapeNet objects, this is caused by importing .obj files # the object has the same pose as before, just that the rotation_euler is now [0, 0, 0] LoaderInterface.remove_x_axis_rotation(loaded_obj) # move the origin of the object to the world origin and on top of the X-Y plane # makes it easier to place them later on, this does not change the `.location` LoaderInterface.move_obj_origin_to_bottom_mean_point(loaded_obj) bpy.ops.object.select_all(action='DESELECT')
def run(self): """ Load BOP data """ datasets_path = os.path.dirname(self.bop_dataset_path) dataset = os.path.basename(self.bop_dataset_path) print("bob: {}, dataset_path: {}".format(self.bop_dataset_path, datasets_path)) print("dataset: {}".format(dataset)) try: from bop_toolkit_lib import dataset_params, inout except ImportError as error: print( 'ERROR: Please download the bop_toolkit package and add it to sys_paths in config!' ) print('https://github.com/thodan/bop_toolkit') raise error model_p = dataset_params.get_model_params( datasets_path, dataset, model_type=self.model_type if self.model_type else None) cam_p = dataset_params.get_camera_params( datasets_path, dataset, cam_type=self.cam_type if self.cam_type else None) try: split_p = dataset_params.get_split_params(datasets_path, dataset, split=self.split) except ValueError: raise Exception( "Wrong path or {} split does not exist in {}.".format( self.split, dataset)) bpy.context.scene.world["category_id"] = 0 bpy.context.scene.render.resolution_x = cam_p['im_size'][0] bpy.context.scene.render.resolution_y = cam_p['im_size'][1] loaded_objects = [] # only load all/selected objects here, use other modules for setting poses # e.g. camera.CameraSampler / object.ObjectPoseSampler if self.scene_id == -1: # TLESS exception because images are cropped if self.bop_dataset_name in ['tless']: cam_p['K'][0, 2] = split_p['im_size'][0] / 2 cam_p['K'][1, 2] = split_p['im_size'][1] / 2 # set camera intrinsics CameraUtility.set_intrinsics_from_K_matrix(cam_p['K'], split_p['im_size'][0], split_p['im_size'][1]) obj_ids = self.obj_ids if self.obj_ids else model_p['obj_ids'] # if sampling is enabled if self.sample_objects: loaded_ids = {} loaded_amount = 0 if self.obj_instances_limit != -1 and len( obj_ids ) * self.obj_instances_limit < self.num_of_objs_to_sample: raise RuntimeError( "{}'s {} split contains {} objects, {} object where requested to sample with " "an instances limit of {}. Raise the limit amount or decrease the requested " "amount of objects.".format(self.bop_dataset_path, self.split, len(obj_ids), self.num_of_objs_to_sample, self.obj_instances_limit)) while loaded_amount != self.num_of_objs_to_sample: random_id = choice(obj_ids) if random_id not in loaded_ids.keys(): loaded_ids.update({random_id: 0}) # if there is no limit or if there is one, but it is not reached for this particular object if self.obj_instances_limit == -1 or loaded_ids[ random_id] < self.obj_instances_limit: cur_obj = self._load_mesh(random_id, model_p, scale=self.scale) loaded_ids[random_id] += 1 loaded_amount += 1 loaded_objects.append(cur_obj) else: print( "ID {} was loaded {} times with limit of {}. Total loaded amount {} while {} are " "being requested".format( random_id, loaded_ids[random_id], self.obj_instances_limit, loaded_amount, self.num_of_objs_to_sample)) else: for obj_id in obj_ids: cur_obj = self._load_mesh(obj_id, model_p, scale=self.scale) loaded_objects.append(cur_obj) self._set_properties(loaded_objects) # replicate scene: load scene objects, object poses, camera intrinsics and camera poses else: sc_gt = inout.load_scene_gt(split_p['scene_gt_tpath'].format( **{'scene_id': self.scene_id})) sc_camera = inout.load_json(split_p['scene_camera_tpath'].format( **{'scene_id': self.scene_id})) for i, (cam_id, insts) in enumerate(sc_gt.items()): cam_K, cam_H_m2c_ref = self._get_ref_cam_extrinsics_intrinsics( sc_camera, cam_id, insts, self.scale) if i == 0: # define world = first camera cam_H_m2w_ref = cam_H_m2c_ref.copy() cur_objs = [] # load scene objects and set their poses for inst in insts: cur_objs.append( self._load_mesh(inst['obj_id'], model_p, scale=self.scale)) self.set_object_pose(cur_objs[-1], inst, self.scale) cam_H_c2w = self._compute_camera_to_world_trafo( cam_H_m2w_ref, cam_H_m2c_ref) # set camera intrinsics CameraUtility.set_intrinsics_from_K_matrix( cam_K, split_p['im_size'][0], split_p['im_size'][1]) # set camera extrinsics as next frame frame_id = CameraUtility.add_camera_pose(cam_H_c2w) # Add key frame for camera shift, as it changes from frame to frame in the tless replication cam = bpy.context.scene.camera.data cam.keyframe_insert(data_path='shift_x', frame=frame_id) cam.keyframe_insert(data_path='shift_y', frame=frame_id) # Copy object poses to key frame (to be sure) for cur_obj in cur_objs: self._insert_key_frames(cur_obj, frame_id) # move the origin of the object to the world origin and on top of the X-Y plane # makes it easier to place them later on, this does not change the `.location` # This is only useful if the BOP objects are not used in a pose estimation scenario. move_to_origin = self.config.get_bool("move_origin_to_x_y_plane", False) if move_to_origin: LoaderInterface.move_obj_origin_to_bottom_mean_point( loaded_objects)
def run(self): """ Chooses objects based on selected type and style. If there are multiple options it picks one randomly or if style or type is None it picks one randomly. Loads the selected object via file path. """ if self._obj_categories is not None and self._obj_style is not None: object_lst = [] for obj_category in self._obj_categories: object_lst.extend([obj[0] for (key, obj) in self._obj_dict.items() \ if self._obj_style in key.lower() and obj_category in key]) if not object_lst: selected_obj = random.choice( self._obj_dict.get( random.choice(list(self._obj_dict.keys())))) warnings.warn( "Could not find object of type: {}, and style: {}. Selecting random object..." .format(self._obj_categories, self._obj_style), category=Warning) else: # Multiple objects with same type and style are possible: select randomly from list. selected_obj = random.choice(object_lst) elif self._obj_categories is not None: object_lst = [] for obj_category in self._obj_categories: object_lst.extend(self._get_object_by_type(obj_category)) selected_obj = random.choice(object_lst) elif self._obj_style is not None: object_lst = self._get_object_by_style(self._obj_style) selected_obj = random.choice(object_lst) else: random_key = random.choice(list(self._obj_dict.keys())) # One key can have multiple object files as value: select randomly from list. selected_obj = random.choice(self._obj_dict.get(random_key)) print("Selected object: ", os.path.basename(selected_obj)) loaded_obj = Utility.import_objects(selected_obj) self._set_properties(loaded_obj) # extract the name from the path: selected_dir_name = os.path.dirname(selected_obj) selected_name = "" if os.path.basename(selected_dir_name).startswith("IKEA_"): selected_name = os.path.basename(selected_dir_name) else: selected_dir_name = os.path.dirname(selected_dir_name) if os.path.basename(selected_dir_name).startswith("IKEA_"): selected_name = os.path.basename(selected_dir_name) if selected_name: for obj in loaded_obj: obj.name = selected_name # extract the file unit from the .obj file to convert every object to meters file_unit = "" with open(selected_obj, "r") as file: first_lines = [next(file) for x in range(5)] for line in first_lines: if "File units" in line: file_unit = line.strip().split(" ")[-1] if file_unit not in [ "inches", "meters", "centimeters", "millimeters" ]: raise Exception( "The file unit type could not be found, check the selected " "file: {}".format(selected_obj)) break for obj in loaded_obj: # convert all objects to meters if file_unit == "inches": scale = 0.0254 elif file_unit == "centimeters": scale = 0.01 elif file_unit == "millimeters": scale = 0.001 elif file_unit == "meters": scale = 1.0 else: raise Exception( "The file unit type: {} is not defined".format(file_unit)) if scale != 1.0: # move all object centers to the world origin and set the bounding box correctly bpy.ops.object.select_all(action='DESELECT') obj.select_set(True) bpy.context.view_layer.objects.active = obj # scale object down bpy.ops.object.mode_set(mode='EDIT') bpy.ops.transform.resize(value=(scale, scale, scale)) bpy.ops.object.mode_set(mode='OBJECT') bpy.context.view_layer.update() bpy.ops.object.select_all(action='DESELECT') # removes the x axis rotation found in all ShapeNet objects, this is caused by importing .obj files # the object has the same pose as before, just that the rotation_euler is now [0, 0, 0] LoaderInterface.remove_x_axis_rotation(loaded_obj) # move the origin of the object to the world origin and on top of the X-Y plane # makes it easier to place them later on, this does not change the `.location` LoaderInterface.move_obj_origin_to_bottom_mean_point(loaded_obj) bpy.ops.object.select_all(action='DESELECT')