Loading autocnet/__init__.py +0 −1 Original line number Diff line number Diff line Loading @@ -6,7 +6,6 @@ import socket from sqlalchemy import create_engine, pool, orm from sqlalchemy.event import listen import setuptools from pkg_resources import get_distribution, DistributionNotFound try: Loading autocnet/cg/cg.py +3 −10 Original line number Diff line number Diff line Loading @@ -393,11 +393,7 @@ def distribute_points_classic(geom, nspts, ewpts, **kwargs): valid : list of point coordinates in the form [(x1,y1), (x2,y2), ..., (xn, yn)] """ try: geom_coords = np.column_stack(geom.exterior.xy) except: # Multipolygon geom_coords = np.column_stack(geom.envelope.exterior.xy) coords = np.array(list(zip(*geom.envelope.exterior.xy))[:-1]) Loading Loading @@ -491,7 +487,6 @@ def distribute_points_new(geom, nspts, ewpts, Session): def distribute_points_in_geom(geom, method="classic", nspts_func=lambda x: ceil(round(x,1)*10), ewpts_func=lambda x: ceil(round(x,1)*5), proj=None, Session=None): """ Given a geometry, attempt a basic classification of the shape. Loading @@ -515,13 +510,11 @@ def distribute_points_in_geom(geom, method="classic", The geometry object nspts_func : obj Function taking a Number and returning an int, if proj is passed in, these have to be in projection coords Function taking a Number and returning an int ewpts_func : obj Function taking a Number and returning an int, if proj is passed in, these have to be in projection coords Function taking a Number and returning an int proj : pyproj.Proj pyproj Projection object used to project the polygon into before placing points Returns ------- valid : list Loading autocnet/graph/network.py +2 −2 Original line number Diff line number Diff line Loading @@ -29,9 +29,8 @@ from plio.io.io_gdal import GeoDataset from plio.io.isis_serial_number import generate_serial_number from plio.io import io_controlnetwork as cnet from plurmy import Slurm from pysis.sugar import point_info from plurmy import Slurm import autocnet from autocnet.config_parser import parse_config Loading @@ -50,6 +49,7 @@ from autocnet.matcher import cross_instrument_matcher as cim from autocnet.vis.graph_view import plot_graph, cluster_plot from autocnet.control import control from autocnet.spatial.overlap import compute_overlaps_sql from autocnet.spatial.isis import point_info from autocnet.transformation.spatial import reproject, og2oc #np.warnings.filterwarnings('ignore') Loading autocnet/graph/node.py +9 −9 Original line number Diff line number Diff line Loading @@ -514,7 +514,7 @@ class NetworkNode(Node): def populate_db(self): with self.parent.session_scope() as session: res = session.query(Images).filter(Images.path == self['image_path']).first() res = session.query(Images).filter(Images.path == kwargs['image_path']).first() if res: # Image already exists return Loading @@ -529,8 +529,8 @@ class NetworkNode(Node): warnings.warn('Unable to generate image footprint.\n{}'.format(e)) fp = None # Create the image i = Images(name=self['image_name'], path=self['image_path'], i = Images(name=kwargs['image_name'], path=kwargs['image_path'], geom=fp, keypoints=kps, #cameras=cam, Loading autocnet/matcher/cpu_extractor.py +6 −67 Original line number Diff line number Diff line Loading @@ -3,9 +3,7 @@ import warnings from cv2 import ORB_create, FastFeatureDetector_create import numpy as np import pandas as pd from autocnet.utils.utils import bytescale from autocnet.transformation import roi try: import cyvlfeat as vl Loading Loading @@ -90,8 +88,7 @@ def extract_features(array, extractor_method='sift', extractor_parameters={}): return keypoints, descriptors def extract_most_interesting(image, size=5, n=1, extractor_method='orb', extractor_parameters={'nfeatures': 15, 'edgeThreshold': 2}): def extract_most_interesting(image, extractor_method='orb', extractor_parameters={'nfeatures':10}): """ Given an image, extract the most interesting feature. Interesting is defined as the feature descriptor that has the maximum variance. By default, this func Loading @@ -102,9 +99,6 @@ def extract_most_interesting(image, size=5, n=1, extractor_method='orb', extract image : ndarray of DN values n : int Number of keypoints to return in increasing score value (1 mean return one keypoint with highest score) extractor_method : str Any valid, autocnet extractor. Default (orb) Loading @@ -117,65 +111,10 @@ def extract_most_interesting(image, size=5, n=1, extractor_method='orb', extract The keypoints row with the higest variance. The row has 'x' and 'y' columns to get the location. """ score_func = lambda r: np.var(roi.Roi(image, r.x, r.y, size, size).clip()) kps, desc = extract_features(image, extractor_method=extractor_method, extractor_parameters=extractor_parameters) kps['score'] = kps.apply(score_func, axis=1) kps = kps.sort_values(by=['score'], ascending=False).iloc[0:n] return kps def find_common_feature(roi1, roi2, thresh=5, n=10, extractor_parameters={'nfeatures': 15, 'edgeThreshold': 1, 'scaleFactor':1.2}): """ Find a single feature that is similar enough between the two images. Essentially, feature extraction and basic matching between two regions of interst that are projected on eachother. Parameters ---------- roi1 : np.array array object of image 1 used as the base roi2 : np.array array object of image 2, projected to match roi1 thresh : float distance threshold, point pairs below this threshold are rejected. n : int nuber of candidate points to attempt to extract geom : bool If true, runs roi2 through the projection step. Otherwise, uses roi1 as is. Default is True Returns ------- : pd.Series Single DF row containing the passsing point and associated metadata """ p1 = extract_most_interesting(roi1, n=n, extractor_method='orb', extractor_parameters=extractor_parameters) p2 = extract_most_interesting(roi2, n=n, extractor_method='orb', extractor_parameters=extractor_parameters) if n == 1: dist = np.linalg.norm([p1.x-p2.x, p1.y-p2.y]) return p1 if dist < thresh else None # sometimes, the extractor fails to exract enough points from either one image or the other, # so throw out the extra features to make them parrallel n_matches = min(len(p1), len(p2)) # Drop index, enabling parallel subtraction p1 = p1.iloc[:n_matches].reset_index(drop=True) p2 = p2.iloc[:n_matches].reset_index(drop=True) dist = np.linalg.norm(list(zip(p1.x-p2.x, p1.y-p2.y)), axis=1) p1['dist'] = dist # return the lower dist in the thresh p1 = p1.sort_values(by=['dist'], ascending=True).iloc[0] if p1['dist'] < thresh: return p1 # Naively assume that the maximum variance is the most unique feature vari = np.var(desc, axis=1) return kps.iloc[np.argmax(vari)] Loading
autocnet/__init__.py +0 −1 Original line number Diff line number Diff line Loading @@ -6,7 +6,6 @@ import socket from sqlalchemy import create_engine, pool, orm from sqlalchemy.event import listen import setuptools from pkg_resources import get_distribution, DistributionNotFound try: Loading
autocnet/cg/cg.py +3 −10 Original line number Diff line number Diff line Loading @@ -393,11 +393,7 @@ def distribute_points_classic(geom, nspts, ewpts, **kwargs): valid : list of point coordinates in the form [(x1,y1), (x2,y2), ..., (xn, yn)] """ try: geom_coords = np.column_stack(geom.exterior.xy) except: # Multipolygon geom_coords = np.column_stack(geom.envelope.exterior.xy) coords = np.array(list(zip(*geom.envelope.exterior.xy))[:-1]) Loading Loading @@ -491,7 +487,6 @@ def distribute_points_new(geom, nspts, ewpts, Session): def distribute_points_in_geom(geom, method="classic", nspts_func=lambda x: ceil(round(x,1)*10), ewpts_func=lambda x: ceil(round(x,1)*5), proj=None, Session=None): """ Given a geometry, attempt a basic classification of the shape. Loading @@ -515,13 +510,11 @@ def distribute_points_in_geom(geom, method="classic", The geometry object nspts_func : obj Function taking a Number and returning an int, if proj is passed in, these have to be in projection coords Function taking a Number and returning an int ewpts_func : obj Function taking a Number and returning an int, if proj is passed in, these have to be in projection coords Function taking a Number and returning an int proj : pyproj.Proj pyproj Projection object used to project the polygon into before placing points Returns ------- valid : list Loading
autocnet/graph/network.py +2 −2 Original line number Diff line number Diff line Loading @@ -29,9 +29,8 @@ from plio.io.io_gdal import GeoDataset from plio.io.isis_serial_number import generate_serial_number from plio.io import io_controlnetwork as cnet from plurmy import Slurm from pysis.sugar import point_info from plurmy import Slurm import autocnet from autocnet.config_parser import parse_config Loading @@ -50,6 +49,7 @@ from autocnet.matcher import cross_instrument_matcher as cim from autocnet.vis.graph_view import plot_graph, cluster_plot from autocnet.control import control from autocnet.spatial.overlap import compute_overlaps_sql from autocnet.spatial.isis import point_info from autocnet.transformation.spatial import reproject, og2oc #np.warnings.filterwarnings('ignore') Loading
autocnet/graph/node.py +9 −9 Original line number Diff line number Diff line Loading @@ -514,7 +514,7 @@ class NetworkNode(Node): def populate_db(self): with self.parent.session_scope() as session: res = session.query(Images).filter(Images.path == self['image_path']).first() res = session.query(Images).filter(Images.path == kwargs['image_path']).first() if res: # Image already exists return Loading @@ -529,8 +529,8 @@ class NetworkNode(Node): warnings.warn('Unable to generate image footprint.\n{}'.format(e)) fp = None # Create the image i = Images(name=self['image_name'], path=self['image_path'], i = Images(name=kwargs['image_name'], path=kwargs['image_path'], geom=fp, keypoints=kps, #cameras=cam, Loading
autocnet/matcher/cpu_extractor.py +6 −67 Original line number Diff line number Diff line Loading @@ -3,9 +3,7 @@ import warnings from cv2 import ORB_create, FastFeatureDetector_create import numpy as np import pandas as pd from autocnet.utils.utils import bytescale from autocnet.transformation import roi try: import cyvlfeat as vl Loading Loading @@ -90,8 +88,7 @@ def extract_features(array, extractor_method='sift', extractor_parameters={}): return keypoints, descriptors def extract_most_interesting(image, size=5, n=1, extractor_method='orb', extractor_parameters={'nfeatures': 15, 'edgeThreshold': 2}): def extract_most_interesting(image, extractor_method='orb', extractor_parameters={'nfeatures':10}): """ Given an image, extract the most interesting feature. Interesting is defined as the feature descriptor that has the maximum variance. By default, this func Loading @@ -102,9 +99,6 @@ def extract_most_interesting(image, size=5, n=1, extractor_method='orb', extract image : ndarray of DN values n : int Number of keypoints to return in increasing score value (1 mean return one keypoint with highest score) extractor_method : str Any valid, autocnet extractor. Default (orb) Loading @@ -117,65 +111,10 @@ def extract_most_interesting(image, size=5, n=1, extractor_method='orb', extract The keypoints row with the higest variance. The row has 'x' and 'y' columns to get the location. """ score_func = lambda r: np.var(roi.Roi(image, r.x, r.y, size, size).clip()) kps, desc = extract_features(image, extractor_method=extractor_method, extractor_parameters=extractor_parameters) kps['score'] = kps.apply(score_func, axis=1) kps = kps.sort_values(by=['score'], ascending=False).iloc[0:n] return kps def find_common_feature(roi1, roi2, thresh=5, n=10, extractor_parameters={'nfeatures': 15, 'edgeThreshold': 1, 'scaleFactor':1.2}): """ Find a single feature that is similar enough between the two images. Essentially, feature extraction and basic matching between two regions of interst that are projected on eachother. Parameters ---------- roi1 : np.array array object of image 1 used as the base roi2 : np.array array object of image 2, projected to match roi1 thresh : float distance threshold, point pairs below this threshold are rejected. n : int nuber of candidate points to attempt to extract geom : bool If true, runs roi2 through the projection step. Otherwise, uses roi1 as is. Default is True Returns ------- : pd.Series Single DF row containing the passsing point and associated metadata """ p1 = extract_most_interesting(roi1, n=n, extractor_method='orb', extractor_parameters=extractor_parameters) p2 = extract_most_interesting(roi2, n=n, extractor_method='orb', extractor_parameters=extractor_parameters) if n == 1: dist = np.linalg.norm([p1.x-p2.x, p1.y-p2.y]) return p1 if dist < thresh else None # sometimes, the extractor fails to exract enough points from either one image or the other, # so throw out the extra features to make them parrallel n_matches = min(len(p1), len(p2)) # Drop index, enabling parallel subtraction p1 = p1.iloc[:n_matches].reset_index(drop=True) p2 = p2.iloc[:n_matches].reset_index(drop=True) dist = np.linalg.norm(list(zip(p1.x-p2.x, p1.y-p2.y)), axis=1) p1['dist'] = dist # return the lower dist in the thresh p1 = p1.sort_values(by=['dist'], ascending=True).iloc[0] if p1['dist'] < thresh: return p1 # Naively assume that the maximum variance is the most unique feature vari = np.var(desc, axis=1) return kps.iloc[np.argmax(vari)]