def compute_fundamental_matrix(self, clean_keys=[], **kwargs): if hasattr(self, 'matches'): matches = self.matches else: raise AttributeError('Matches have not been computed for this edge') return all_source_keypoints = self.source.get_keypoint_coordinates(matches['source_idx']) all_destin_keypoints = self.destination.get_keypoint_coordinates(matches['destination_idx']) matches, mask = self._clean(clean_keys) s_keypoints = self.source.get_keypoint_coordinates(matches['source_idx']).values d_keypoints = self.destination.get_keypoint_coordinates(matches['destination_idx']).values transformation_matrix, fundam_mask = od.compute_fundamental_matrix(s_keypoints, d_keypoints, **kwargs) try: fundam_mask = fundam_mask.ravel() except: return # Convert the truncated RANSAC mask back into a full length mask mask[mask] = fundam_mask self.fundamental_matrix = FundamentalMatrix(transformation_matrix, all_source_keypoints, all_destin_keypoints, mask=mask) # Subscribe the health watcher to the fundamental matrix observable self.fundamental_matrix.subscribe(self._health.update) self.fundamental_matrix._notify_subscribers(self.fundamental_matrix) # Set the initial state of the fundamental mask in the masks self.masks = ('fundamental', mask)
def refine(self, method=ps.esda.mapclassify.Fisher_Jenks, bin_id=0, **kwargs): """ Refine the fundamental matrix by accepting some data classification method that accepts an ndarray and returns an object with a bins attribute, where bins are data breaks. Using the bin_id, mask all values greater than the selected bin. Then compute a new fundamental matrix. Parameters ---------- method : object A function that accepts and ndarray and returns an object with a bins attribute bin_id : int The index into the bins object. Data classified > this id is masked kwargs : dict Keyword args supported by the data classifier Returns ------- FundamentalMatrix : object A fundamental matrix class object mask : series A bool mask with index attribute identifying the valid data in the new fundamental matrix. """ # Perform the data classification fj = method(self.error.values.ravel(), **kwargs) bins = fj.bins # Mask the data that falls outside the provided bins mask = self.error['Reprojection Error'] <= bins[bin_id] new_x1 = self.x1.iloc[mask[mask==True].index] new_x2 = self.x2.iloc[mask[mask==True].index] fmatrix, new_mask = compute_fundamental_matrix(new_x1.values, new_x2.values) mask[mask==True] = new_mask # Update the current state self[:] = fmatrix self.mask[self.mask==True] = mask # Update the action stack try: state_package = {'arr': fmatrix.copy(), 'mask': self.mask.copy()} self._action_stack.append(state_package) self._current_action_stack = len(self._action_stack) - 1 # 0 based vs. 1 based self._clean_attrs() self._notify_subscribers(self) except: warnings.warn('Refinement outlier detection removed all observations.', UserWarning)
def compute_fundamental_matrix(self, clean_keys=[], **kwargs): if hasattr(self, 'matches'): matches = self.matches else: raise AttributeError('Matches have not been computed for this edge') all_source_keypoints = self.source.keypoints.iloc[matches['source_idx']] all_destin_keypoints = self.destination.keypoints.iloc[matches['destination_idx']] if clean_keys: matches, mask = self._clean(clean_keys) s_keypoints = self.source.keypoints.iloc[matches['source_idx'].values] d_keypoints = self.destination.keypoints.iloc[matches['destination_idx'].values] transformation_matrix, fundam_mask = od.compute_fundamental_matrix(s_keypoints[['x', 'y']].values, d_keypoints[['x', 'y']].values, **kwargs) fundam_mask = fundam_mask.ravel() # Convert the truncated RANSAC mask back into a full length mask if clean_keys: mask[mask == True] = fundam_mask else: mask = fundam_mask self.fundamental_matrix = FundamentalMatrix(transformation_matrix, all_source_keypoints[['x', 'y']], all_destin_keypoints[['x', 'y']], mask=mask) # Subscribe the health watcher to the fundamental matrix observable self.fundamental_matrix.subscribe(self._health.update) self.fundamental_matrix._notify_subscribers(self.fundamental_matrix) # Set the initial state of the fundamental mask in the masks self.masks = ('fundamental', mask)