Loading autocnet/cg/cg.py +4 −4 Changes for autocnet/cg/cg.py: 4 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -70,13 +70,13 @@ def two_poly_overlap(poly1, poly2): The total area of overalap """ a_o = poly2.Intersection(poly1).GetArea() overlap_area_polygon = poly2.Intersection(poly1) overlap_area = overlap_area_polygon.GetArea() area1 = poly1.GetArea() area2 = poly2.GetArea() overlap_area = a_o overlap_percn = (a_o / (area1 + area2 - a_o)) * 100 return overlap_percn, overlap_area overlap_percn = (overlap_area / (area1 + area2 - overlap_area)) * 100 return overlap_percn, overlap_area, overlap_area_polygon def get_area(poly1, poly2): Loading autocnet/graph/edge.py +30 −8 Changes for autocnet/graph/edge.py: 30 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ from autocnet.matcher.feature import FlannMatcher from autocnet.transformation.decompose import coupled_decomposition from autocnet.transformation.transformations import FundamentalMatrix, Homography from autocnet.vis.graph_view import plot_edge from autocnet.vis.graph_view import plot_node from autocnet.cg import cg Loading Loading @@ -354,7 +355,7 @@ class Edge(dict, MutableMapping): def ratio_check(self, clean_keys=[], **kwargs): if hasattr(self, 'matches'): matches, mask = self._clean(clean_keys) matches, mask = self.clean(clean_keys) self.distance_ratio = od.DistanceRatio(matches) self.distance_ratio.compute(mask=mask, **kwargs) Loading Loading @@ -389,7 +390,7 @@ class Edge(dict, MutableMapping): if not hasattr(self, 'matches'): raise AttributeError('Matches have not been computed for this edge') return matches, mask = self._clean(clean_keys) matches, mask = self.clean(clean_keys) # TODO: Homogeneous is horribly inefficient here, use Numpy array notation s_keypoints = self.source.get_keypoint_coordinates(index=matches['source_idx'], Loading Loading @@ -440,7 +441,7 @@ class Edge(dict, MutableMapping): else: raise AttributeError('Matches have not been computed for this edge') matches, mask = self._clean(clean_keys) matches, mask = self.clean(clean_keys) s_keypoints = self.source.get_keypoint_coordinates(index=matches['source_idx']) d_keypoints = self.destination.get_keypoint_coordinates(index=matches['destination_idx']) Loading Loading @@ -498,7 +499,7 @@ class Edge(dict, MutableMapping): self.matches[column] = default # Build up a composite mask from all of the user specified masks matches, mask = self._clean(clean_keys) matches, mask = self.clean(clean_keys) # Grab the full images, or handles if tiled is True: Loading Loading @@ -568,7 +569,7 @@ class Edge(dict, MutableMapping): if not hasattr(self, 'matches'): raise AttributeError('This edge does not yet have any matches computed.') matches, mask = self._clean(clean_keys) matches, mask = self.clean(clean_keys) domain = self.source.geodata.raster_size # Massage the dataframe into the correct structure Loading @@ -589,10 +590,31 @@ class Edge(dict, MutableMapping): mask[mask] = self.suppression.mask self.masks = ('suppression', mask) def plot(self, ax=None, clean_keys=[], **kwargs): def plot_source(self, ax=None, clean_keys=[], **kwargs): # pragma: no cover matches, mask = self.clean(clean_keys=clean_keys) indices = pd.Index(matches['source_idx'].values) return plot_node(self.source, index_mask=indices, **kwargs) def plot_destination(self, ax=None, clean_keys=[], **kwargs): # pragma: no cover matches, mask = self.clean(clean_keys=clean_keys) indices = pd.Index(matches['destination_idx'].values) return plot_node(self.destination, index_mask=indices, **kwargs) def plot(self, ax=None, clean_keys=[], node=None, **kwargs): # pragma: no cover dest_keys = [0, '0', 'destination', 'd', 'dest'] source_keys = [1, '1', 'source', 's'] # If node is not none, plot a single node if node in source_keys: return self.plot_source(self, clean_keys=clean_keys, **kwargs) elif node in dest_keys: return self.plot_destination(self, clean_keys=clean_keys, **kwargs) # Else, plot the whole edge return plot_edge(self, ax=ax, clean_keys=clean_keys, **kwargs) def _clean(self, clean_keys, pid=None): def clean(self, clean_keys, pid=None): """ Given a list of clean keys and a provenance id compute the mask of valid matches Loading Loading @@ -652,7 +674,7 @@ class Edge(dict, MutableMapping): if self.matches is None: raise AttributeError('Edge needs to have features extracted and matched') return matches, mask = self._clean(clean_keys) matches, mask = self.clean(clean_keys) source_array = self.source.get_keypoint_coordinates(index=matches['source_idx']).values source_coords = self.source.geodata.latlon_corners Loading autocnet/graph/node.py +10 −3 Changes for autocnet/graph/node.py: 10 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -264,8 +264,10 @@ class Node(dict, MutableMapping): allkps = pd.DataFrame(data=clean_kps, columns=columns, index=index) if 'response' in allkps.columns: self._keypoints = allkps.sort_values(by='response', ascending=False) elif 'size' in allkps.columns: self._keypoints = allkps.sort_values(by='size', ascending=False) if isinstance(in_path, str): hdf = None Loading Loading @@ -312,7 +314,7 @@ class Node(dict, MutableMapping): if isinstance(out_path, str): hdf = None def group_correspondences(self, cg, *args, clean_keys=['fundamental'], deepen=False, **kwargs): def group_correspondences(self, cg, *args, deepen=False, **kwargs): """ Parameters Loading @@ -332,12 +334,17 @@ class Node(dict, MutableMapping): # TODO: Add dangling correspondences to control network anyway. Subgraphs handle this segmentation if req. return try: clean_keys = kwargs['clean_keys'] except: clean_keys = [] # Grab all the incident edge matches and concatenate into a group match set. # All share the same source node edge_matches = [] for e in incident_edges: edge = cg[e[0]][e[1]] matches, mask = edge._clean(clean_keys=clean_keys) matches, mask = edge.clean(clean_keys=clean_keys) # Add a depth mask that initially mirrors the fundamental mask edge_matches.append(matches) d = pd.concat(edge_matches) Loading autocnet/matcher/ciratefi.py +16 −8 Changes for autocnet/matcher/ciratefi.py: 16 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -481,8 +481,8 @@ def tefi(template, search_image, candidate_pixels, best_scales, best_angles, # check for upsampling if upsampling > 1: template = zoom(template, upsampling, order=3) search_image = zoom(search_image, upsampling, order=3) u_template = zoom(template, upsampling, order=3) u_search_image = zoom(search_image, upsampling, order=3) alpha_list = np.arange(0, 2*math.pi, alpha) candidate_pixels *= int(upsampling) Loading @@ -505,13 +505,13 @@ def tefi(template, search_image, candidate_pixels, best_scales, best_angles, max_coeff = -math.inf for j in range(scalesxalphas.shape[0]): transformed_template = imresize(template, scalesxalphas[j][0]) transformed_template = imresize(u_template, scalesxalphas[j][0]) transformed_template = rotate(transformed_template, scalesxalphas[j][1]) y_window, x_window = (math.floor(transformed_template.shape[0]/2), math.floor(transformed_template.shape[1]/2)) cropped_search = search_image[y-y_window:y+y_window+1, x-x_window:x+x_window+1] cropped_search = u_search_image[y-y_window:y+y_window+1, x-x_window:x+x_window+1] if(y < y_window or x < x_window or cropped_search.shape < transformed_template.shape or cropped_search.shape != transformed_template.shape): Loading @@ -531,16 +531,24 @@ def tefi(template, search_image, candidate_pixels, best_scales, best_angles, if use_percentile: thresh = np.percentile(tefi_coeffs, int(thresh)) candidate_pixels = candidate_pixels/upsampling result_points = candidate_pixels[np.where(tefi_coeffs >= thresh)] result_coeffs = tefi_coeffs[np.where(tefi_coeffs >= thresh)] results = candidate_pixels[np.where(tefi_coeffs >= thresh)] x = result_points[0][1] y = result_points[0][0] ideal_y = u_search_image.shape[0] / 2 ideal_x = u_search_image.shape[1] / 2 if verbose: # pragma: no cover plt.imshow(image_pixels, interpolation='none') plt.scatter(y=results[:, 0], x=results[:, 1], c='w', s=80) plt.scatter(y=y/upsampling, x=x/upsampling, c='w', s=80) plt.show() return results x = (ideal_x - x)/upsampling y = (ideal_y - y)/upsampling return x, y, result_coeffs[0] def ciratefi(template, search_image, upsampling=1, cifi_thresh=95, rafi_thresh=95, tefi_thresh=100, Loading autocnet/matcher/subpixel.py +7 −2 Changes for autocnet/matcher/subpixel.py: 7 added lines, 2 removed lines. Original line number Diff line number Diff line import numpy as np from autocnet.matcher import naive_template from autocnet.matcher import ciratefi # TODO: look into KeyPoint.size and perhaps use to determine an appropriately-sized search/template. Loading Loading @@ -49,7 +51,7 @@ def clip_roi(img, center, img_size): return clipped_img def subpixel_offset(template, search, **kwargs): def subpixel_offset(template, search, method='naive', **kwargs): """ Uses a pattern-matcher on subsets of two images determined from the passed-in keypoints and optional sizes to compute an x and y offset from the search keypoint to the template keypoint and an associated strength. Loading @@ -74,7 +76,10 @@ def subpixel_offset(template, search, **kwargs): Strength of the correspondence in the range [-1, 1] """ x_offset, y_offset, strength = naive_template.pattern_match(template, search, **kwargs) functions = { 'naive' : naive_template.pattern_match, 'ciratefi' : ciratefi.ciratefi} x_offset, y_offset, strength = functions[method](template, search, **kwargs) return x_offset, y_offset, strength ''' Loading Loading
autocnet/cg/cg.py +4 −4 Changes for autocnet/cg/cg.py: 4 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -70,13 +70,13 @@ def two_poly_overlap(poly1, poly2): The total area of overalap """ a_o = poly2.Intersection(poly1).GetArea() overlap_area_polygon = poly2.Intersection(poly1) overlap_area = overlap_area_polygon.GetArea() area1 = poly1.GetArea() area2 = poly2.GetArea() overlap_area = a_o overlap_percn = (a_o / (area1 + area2 - a_o)) * 100 return overlap_percn, overlap_area overlap_percn = (overlap_area / (area1 + area2 - overlap_area)) * 100 return overlap_percn, overlap_area, overlap_area_polygon def get_area(poly1, poly2): Loading
autocnet/graph/edge.py +30 −8 Changes for autocnet/graph/edge.py: 30 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ from autocnet.matcher.feature import FlannMatcher from autocnet.transformation.decompose import coupled_decomposition from autocnet.transformation.transformations import FundamentalMatrix, Homography from autocnet.vis.graph_view import plot_edge from autocnet.vis.graph_view import plot_node from autocnet.cg import cg Loading Loading @@ -354,7 +355,7 @@ class Edge(dict, MutableMapping): def ratio_check(self, clean_keys=[], **kwargs): if hasattr(self, 'matches'): matches, mask = self._clean(clean_keys) matches, mask = self.clean(clean_keys) self.distance_ratio = od.DistanceRatio(matches) self.distance_ratio.compute(mask=mask, **kwargs) Loading Loading @@ -389,7 +390,7 @@ class Edge(dict, MutableMapping): if not hasattr(self, 'matches'): raise AttributeError('Matches have not been computed for this edge') return matches, mask = self._clean(clean_keys) matches, mask = self.clean(clean_keys) # TODO: Homogeneous is horribly inefficient here, use Numpy array notation s_keypoints = self.source.get_keypoint_coordinates(index=matches['source_idx'], Loading Loading @@ -440,7 +441,7 @@ class Edge(dict, MutableMapping): else: raise AttributeError('Matches have not been computed for this edge') matches, mask = self._clean(clean_keys) matches, mask = self.clean(clean_keys) s_keypoints = self.source.get_keypoint_coordinates(index=matches['source_idx']) d_keypoints = self.destination.get_keypoint_coordinates(index=matches['destination_idx']) Loading Loading @@ -498,7 +499,7 @@ class Edge(dict, MutableMapping): self.matches[column] = default # Build up a composite mask from all of the user specified masks matches, mask = self._clean(clean_keys) matches, mask = self.clean(clean_keys) # Grab the full images, or handles if tiled is True: Loading Loading @@ -568,7 +569,7 @@ class Edge(dict, MutableMapping): if not hasattr(self, 'matches'): raise AttributeError('This edge does not yet have any matches computed.') matches, mask = self._clean(clean_keys) matches, mask = self.clean(clean_keys) domain = self.source.geodata.raster_size # Massage the dataframe into the correct structure Loading @@ -589,10 +590,31 @@ class Edge(dict, MutableMapping): mask[mask] = self.suppression.mask self.masks = ('suppression', mask) def plot(self, ax=None, clean_keys=[], **kwargs): def plot_source(self, ax=None, clean_keys=[], **kwargs): # pragma: no cover matches, mask = self.clean(clean_keys=clean_keys) indices = pd.Index(matches['source_idx'].values) return plot_node(self.source, index_mask=indices, **kwargs) def plot_destination(self, ax=None, clean_keys=[], **kwargs): # pragma: no cover matches, mask = self.clean(clean_keys=clean_keys) indices = pd.Index(matches['destination_idx'].values) return plot_node(self.destination, index_mask=indices, **kwargs) def plot(self, ax=None, clean_keys=[], node=None, **kwargs): # pragma: no cover dest_keys = [0, '0', 'destination', 'd', 'dest'] source_keys = [1, '1', 'source', 's'] # If node is not none, plot a single node if node in source_keys: return self.plot_source(self, clean_keys=clean_keys, **kwargs) elif node in dest_keys: return self.plot_destination(self, clean_keys=clean_keys, **kwargs) # Else, plot the whole edge return plot_edge(self, ax=ax, clean_keys=clean_keys, **kwargs) def _clean(self, clean_keys, pid=None): def clean(self, clean_keys, pid=None): """ Given a list of clean keys and a provenance id compute the mask of valid matches Loading Loading @@ -652,7 +674,7 @@ class Edge(dict, MutableMapping): if self.matches is None: raise AttributeError('Edge needs to have features extracted and matched') return matches, mask = self._clean(clean_keys) matches, mask = self.clean(clean_keys) source_array = self.source.get_keypoint_coordinates(index=matches['source_idx']).values source_coords = self.source.geodata.latlon_corners Loading
autocnet/graph/node.py +10 −3 Changes for autocnet/graph/node.py: 10 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -264,8 +264,10 @@ class Node(dict, MutableMapping): allkps = pd.DataFrame(data=clean_kps, columns=columns, index=index) if 'response' in allkps.columns: self._keypoints = allkps.sort_values(by='response', ascending=False) elif 'size' in allkps.columns: self._keypoints = allkps.sort_values(by='size', ascending=False) if isinstance(in_path, str): hdf = None Loading Loading @@ -312,7 +314,7 @@ class Node(dict, MutableMapping): if isinstance(out_path, str): hdf = None def group_correspondences(self, cg, *args, clean_keys=['fundamental'], deepen=False, **kwargs): def group_correspondences(self, cg, *args, deepen=False, **kwargs): """ Parameters Loading @@ -332,12 +334,17 @@ class Node(dict, MutableMapping): # TODO: Add dangling correspondences to control network anyway. Subgraphs handle this segmentation if req. return try: clean_keys = kwargs['clean_keys'] except: clean_keys = [] # Grab all the incident edge matches and concatenate into a group match set. # All share the same source node edge_matches = [] for e in incident_edges: edge = cg[e[0]][e[1]] matches, mask = edge._clean(clean_keys=clean_keys) matches, mask = edge.clean(clean_keys=clean_keys) # Add a depth mask that initially mirrors the fundamental mask edge_matches.append(matches) d = pd.concat(edge_matches) Loading
autocnet/matcher/ciratefi.py +16 −8 Changes for autocnet/matcher/ciratefi.py: 16 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -481,8 +481,8 @@ def tefi(template, search_image, candidate_pixels, best_scales, best_angles, # check for upsampling if upsampling > 1: template = zoom(template, upsampling, order=3) search_image = zoom(search_image, upsampling, order=3) u_template = zoom(template, upsampling, order=3) u_search_image = zoom(search_image, upsampling, order=3) alpha_list = np.arange(0, 2*math.pi, alpha) candidate_pixels *= int(upsampling) Loading @@ -505,13 +505,13 @@ def tefi(template, search_image, candidate_pixels, best_scales, best_angles, max_coeff = -math.inf for j in range(scalesxalphas.shape[0]): transformed_template = imresize(template, scalesxalphas[j][0]) transformed_template = imresize(u_template, scalesxalphas[j][0]) transformed_template = rotate(transformed_template, scalesxalphas[j][1]) y_window, x_window = (math.floor(transformed_template.shape[0]/2), math.floor(transformed_template.shape[1]/2)) cropped_search = search_image[y-y_window:y+y_window+1, x-x_window:x+x_window+1] cropped_search = u_search_image[y-y_window:y+y_window+1, x-x_window:x+x_window+1] if(y < y_window or x < x_window or cropped_search.shape < transformed_template.shape or cropped_search.shape != transformed_template.shape): Loading @@ -531,16 +531,24 @@ def tefi(template, search_image, candidate_pixels, best_scales, best_angles, if use_percentile: thresh = np.percentile(tefi_coeffs, int(thresh)) candidate_pixels = candidate_pixels/upsampling result_points = candidate_pixels[np.where(tefi_coeffs >= thresh)] result_coeffs = tefi_coeffs[np.where(tefi_coeffs >= thresh)] results = candidate_pixels[np.where(tefi_coeffs >= thresh)] x = result_points[0][1] y = result_points[0][0] ideal_y = u_search_image.shape[0] / 2 ideal_x = u_search_image.shape[1] / 2 if verbose: # pragma: no cover plt.imshow(image_pixels, interpolation='none') plt.scatter(y=results[:, 0], x=results[:, 1], c='w', s=80) plt.scatter(y=y/upsampling, x=x/upsampling, c='w', s=80) plt.show() return results x = (ideal_x - x)/upsampling y = (ideal_y - y)/upsampling return x, y, result_coeffs[0] def ciratefi(template, search_image, upsampling=1, cifi_thresh=95, rafi_thresh=95, tefi_thresh=100, Loading
autocnet/matcher/subpixel.py +7 −2 Changes for autocnet/matcher/subpixel.py: 7 added lines, 2 removed lines. Original line number Diff line number Diff line import numpy as np from autocnet.matcher import naive_template from autocnet.matcher import ciratefi # TODO: look into KeyPoint.size and perhaps use to determine an appropriately-sized search/template. Loading Loading @@ -49,7 +51,7 @@ def clip_roi(img, center, img_size): return clipped_img def subpixel_offset(template, search, **kwargs): def subpixel_offset(template, search, method='naive', **kwargs): """ Uses a pattern-matcher on subsets of two images determined from the passed-in keypoints and optional sizes to compute an x and y offset from the search keypoint to the template keypoint and an associated strength. Loading @@ -74,7 +76,10 @@ def subpixel_offset(template, search, **kwargs): Strength of the correspondence in the range [-1, 1] """ x_offset, y_offset, strength = naive_template.pattern_match(template, search, **kwargs) functions = { 'naive' : naive_template.pattern_match, 'ciratefi' : ciratefi.ciratefi} x_offset, y_offset, strength = functions[method](template, search, **kwargs) return x_offset, y_offset, strength ''' Loading