def save_h5py(self, filename): def encode_ss_utf_8(ss): return np.void(ss.encode('utf-8')) # self = self.source_model.compute_displacement_map(self.target_model, 3) file = None try: file = h5py.File(filename, "w") file.create_dataset("points", data=self.points) file.create_dataset("missed_points", data=self.missed_points) file.attrs["points_color"] = encode_ss_utf_8(self.points_color) file.attrs["missed_points_color"] = encode_ss_utf_8( self.missed_points_color) if self.landmarks is not None: file.create_dataset("landmarks", data=self.landmarks) file.create_dataset("missed_landmarks", data=self.missed_landmarks) file.attrs["landmarks_color"] = encode_ss_utf_8( self.landmarks_color) file.attrs["missed_landmarks_color"] = encode_ss_utf_8( self.missed_landmarks_color) except Exception as ex: Logger.addRow("ERROR: Displacement map was not saved. =>" + str(ex)) finally: if file is not None: file.close() Logger.addRow(f'File {filename} saved correctly.')
def load_model(self, path_data): self.filename, self.file_extension = os.path.splitext(path_data) if os.path.exists(self.filename + ".png"): self.bgImage = self.filename + ".png" if self.file_extension == ".mat": file = h5py.File(path_data, 'r') try: self.set_points(np.transpose(np.array(file["avgModel"]))) self.set_landmarks(np.transpose(np.array(file["landmarks3D"]))) except Exception as ex: print("File is not compatible:" + ex) if self.file_extension == ".wrl": self.set_points(file3D.load_wrml(path_data)) self.set_landmarks(file3D.load_bnd(self.filename + ".bnd")) if self.bgImage is not None and os.path.exists(self.bgImage): self.bgImage = self.filename[:-3] + "F2D.png" if self.file_extension == ".off": self.set_points(file3D.load_off(path_data)) row = "Model loaded: " + str(self.points.shape[0]) + " points" if self.landmarks is not None: row += " and " + str(self.landmarks.shape[0]) + " landmarks." self.init_registration_points() Logger.addRow(row)
def write_on_file(self): with open('registration_parameters.conf', 'w+') as conf_file: conf = ConfigParser() conf['PARAMETERS'] = {} for key, value in self.params.items(): conf['PARAMETERS'][str(key)] = str(value) conf.write(conf_file) Logger.addRow("Configuration file updated")
def __init__(self, source, target_list, percentage, final_callback): Thread.__init__(self) self.source_model = source self.target_list = target_list self.perc = percentage self.finalCallback = final_callback self.should_stop = False Logger.addRow("Starting Batch Thread..")
def compute_map(cls, source_model, target_model, max_dist=2): """:param source_model :type source_model Model :param target_model :type target_model Model :param max_dist :type max_dist number """ source_points = source_model.points target_points = target_model.points hit_landmarks = None missed_landmarks = None landmarks_color = None missed_landmarks_color = None # Points KDTree tree = cKDTree(source_points) _, indices = tree.query(target_points, distance_upper_bound=max_dist, n_jobs=multiprocessing.cpu_count()) # Indices contains source's neighbors indices to target's points used for query indices = set(indices) indices.discard(source_points.shape[0]) indices = list(indices) hit_points = source_points[indices] missed_points = np.delete(source_points, indices, axis=0) # Points without a feasible neighbor missed_color = "y" points_color = "b" # LandmarksKDTree if source_model.landmarks is not None and target_model.landmarks is not None: tree = cKDTree(source_model.landmarks) _, indices = tree.query(target_model.landmarks, distance_upper_bound=max_dist, n_jobs=multiprocessing.cpu_count()) indices = set(indices) indices.discard(source_model.landmarks.shape[0]) indices = list(indices) hit_landmarks = source_model.landmarks[indices] missed_landmarks = np.delete(source_model.landmarks, indices, axis=0) landmarks_color = "r" missed_landmarks_color = "p" Logger.addRow("Displacement map created.") return cls(points=hit_points, landmarks=hit_landmarks, points_color=points_color, landmarks_color=landmarks_color, missed_points=missed_points, missed_landmarks=missed_landmarks, missed_points_color=missed_color, missed_landmarks_color=missed_landmarks_color)
def run(self): source = self.source_model.get_registration_points() try: for targ in self.target_list: Logger.addRow( "Batch %d of %d:" % (self.target_list.index(targ) + 1, len(self.target_list))) path_wrl = targ[0:len(targ) - 3] + "bnd" t = Model(targ, path_wrl) target = Model.decimate(t.points, self.perc) Logger.addRow("Points decimated.") if t.landmarks is not None: target = np.concatenate((target, t.landmarks), axis=0) reg = rigid_registration(**{'X': source, 'Y': target}) meth = "CPD Rigid" Logger.addRow("Starting registration with " + meth + ", using " + str(self.perc) + "% of points.") model = Model() reg_time = time.time() # Se si vuole visualizzare i progressi usare questa versione # data, reg_param = reg.register(partial(self.drawCallback, ax=None)) data, reg_param = reg.register(partial(self.log, ax=None)) model.set_points( reg.transform_point_cloud(self.source_model.model_data)) model.registration_params = reg_param if t.landmarks is not None: model.set_landmarks( data[target.shape[0] - t.landmarks.shape[0]:data.shape[0]]) model.filename = t.filename # model.centerData() model.compute_displacement_map(target, 3) now = datetime.datetime.now() save_filename = "RIGID_REG_{0}_{1}_{2}_{3}_{4}.mat" save_path = os.path.join( "results", save_filename.format(now.day, now.month, now.year, now.hour, now.minute)) model.save_model(save_path) model.shoot_displacement_map(save_path) Logger.addRow("Took " + str(round(time.time() - reg_time, 3)) + "s.") except Exception as ex: Logger.addRow(str(ex)) print(ex) finally: self.finalCallback()
def save_model(self, filename): model = {"model_data": self.points} if self.landmarks is not None: model["landmarks3D"] = self.landmarks if self.displacement_map is not None: model["displacement_map"] = self.displacement_map if self.registration_params is not None: for i in range(len(self.registration_params)): model[str("reg_param" + str(i))] = self.registration_params[i] file3D.save_file(filename, model) Logger.addRow(str("File saved: " + filename))
def load_model(cls, filename): try: file = h5py.File(filename, 'r') points = file.get("points").value missed_points = file.get("missed_points").value points_color = ( file.attrs["points_color"]).tostring().decode('utf-8') missed_points_color = ( file.attrs["missed_points_color"]).tostring().decode('utf-8') # If landmarks are not present a KeyError is raised landmarks = file.get("landmarks").value missed_landmarks = file.get("missed_landmarks").value landmarks_color = ( file.attrs["landmarks_color"]).tostring().decode('utf-8') missed_landmarks_color = (file.attrs["missed_landmarks_color"] ).tostring().decode('utf-8') except AttributeError: Logger.addRow("INFO: Displacement model has no landmarks.") landmarks = None landmarks_color = None missed_landmarks = None missed_landmarks_color = None except FileNotFoundError: Logger.addRow(f"ERROR: {filename} not found, check path.") except Exception as ex: Logger.addRow(f"ERROR: Problem during opening of {filename} =>" + str(ex)) finally: displacement_model = cls( points=points, landmarks=landmarks, missed_points=missed_points, missed_landmarks=missed_landmarks, points_color=points_color, landmarks_color=landmarks_color, missed_points_color=missed_points_color, missed_landmarks_color=missed_landmarks_color) Logger.addRow(f'File {filename} load correctly.') return displacement_model
def run(self): source = self.source_model.get_registration_points() target = Model.decimate(self.target_model.points, self.percentage) Logger.addRow("Points decimated.") if self.target_model.landmarks is not None: target = np.concatenate((target, self.target_model.landmarks), axis=0) Logger.addRow("Landmarks added.") ps = RegistrationParameters().get_params() if self.method == 1: # CPD - RIGID self.registration_method = rigid_registration( **{ 'X': target, 'Y': source, 'sigma2': ps['sigma2'], 'max_iterations': ps['max_iterations'], 'tolerance': ps['tolerance'], 'w': ps['w'] }) method = "CPD Rigid" if self.method == 2: # CPD - AFFINE self.registration_method = affine_registration( **{ 'X': target, 'Y': source, 'sigma2': ps['sigma2'], 'max_iterations': ps['max_iterations'], 'tolerance': ps['tolerance'], 'w': ps['w'] }) method = "CPD Affine" if self.method == 3: # CPD - DEFORMABLE self.registration_method = deformable_registration( **{ 'X': target, 'Y': source, 'sigma2': ps['sigma2'], 'max_iterations': ps['max_iterations'], 'tolerance': ps['tolerance'], 'w': ps['w'] }) method = "CPD Deformable" Logger.addRow("Starting registration with " + method + ", using " + str(self.percentage) + "% of points.") model = Model() reg_time = time.time() try: self.registration_method.register( partial(self.interruptable_wrapper, ax=None)) model = self.aligned_model(model) except InterruptedException as ex: Logger.addRow(str(ex)) model = self.aligned_model(model) except Exception as ex: Logger.addRow("Err: " + str(ex)) model = self.target_model # Fail: back with the original target model finally: Logger.addRow("Took " + str(round(time.time() - reg_time, 3)) + "s.") self.callback(model)
def log(self, iteration, error): row = "Iteration #" + str(iteration) + " error: " + str(error) Logger.addRow(row)
def load_off(file, faces_required=False): """ Reads vertices and faces from an off file. :param file: path to file to read :type file: str :param faces_required: True if the function should return faces also :type: bool :return: vertices and faces as lists of tuples :rtype: [(float)], [(int)] """ assert os.path.exists(file) with open(file, 'r') as fp: lines = fp.readlines() lines = [line.strip() for line in lines] assert (lines[0] == 'OFF'), "Invalid preambole" parts = lines[1].split(' ') assert ( len(parts) == 3 ), "Need exactly 3 parameters on 2nd line (n_vertices, n_faces, n_edges)." num_vertices = int(parts[0]) assert num_vertices > 0 num_faces = int(parts[1]) if faces_required: assert num_faces > 0 vertices = [] for i in range(num_vertices): vertex = lines[2 + i].split(' ') vertex = [float(point) for point in vertex] assert (len(vertex) == 3), str("Invalid vertex row on line " + str(i)) vertices.append(vertex) if num_vertices > len(vertices): row = "WARNING: some vertices were not loaded correctly: {0} declared vs {1} loaded." Logger.addRow(row.format(num_vertices, len(vertices))) vertices = np.asarray(vertices) if faces_required: faces = [] for i in range(num_faces): face = lines[2 + num_vertices + i].split(' ') face = [int(index) for index in face] assert face[0] == len(face) - 1 for index in face: assert 0 <= index < num_vertices assert len(face) > 1 faces.append(face) return vertices, faces return vertices
def log(self, iteration, error, X, Y, ax): sss = "Iteration #" + str(iteration) + " error: " + str(error) Logger.addRow(sss) if self.should_stop: raise Exception("Registration has been stopped")