Loading .travis.yml +1 −11 Original line number Diff line number Diff line language: generic # Since we use conda, just go generic sudo: false branches: Loading @@ -7,8 +8,6 @@ only: env: global: - BINSTAR_USER: jlaura matrix: - PYTHON_VERSION: 3.5 os: - linux Loading @@ -18,18 +17,10 @@ install: # We do this conditionally because it saves us some downloading if the # version is the same. - if [ "$TRAVIS_OS_NAME" == "linux" ]; then if [ "$PYTHON_VERSION" == 2.7 ]; then wget https://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh; else wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; fi else if ["$PYTHON_VERSION" == 2.7]; then curl -o miniconda.sh https://repo.continuum.io/miniconda/Miniconda-latest-MacOSX-x86_64.sh; else curl -o miniconda.sh https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh; fi fi - bash miniconda.sh -b -p $HOME/miniconda - export PATH="$HOME/miniconda/bin:$PATH" - hash -r Loading @@ -43,7 +34,6 @@ install: - conda config --add channels menpo - conda config --add channels jlaura - conda config --set ssl_verify false - conda install python=$PYTHON_VERSION - conda install -c conda-forge numpy opencv - conda install -c jlaura plio - conda install -c conda-forge vlfeat Loading autocnet/__init__.py +6 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,9 @@ def cuda(enable=False, gpu=0): from autocnet.matcher.cuda_decompose import decompose_and_match Edge.decompose_and_match = decompose_and_match from autocnet.matcher.cuda_outlier_detector import distance_ratio Edge._ratio_check = staticmethod(distance_ratio) except Exception: warnings.warn('Failed to enable Cuda') return Loading @@ -57,4 +60,7 @@ def cuda(enable=False, gpu=0): from autocnet.matcher.cpu_decompose import decompose_and_match Edge.decompose_and_match = decompose_and_match from autocnet.matcher.cpu_outlier_detector import distance_ratio Edge._ratio_check = staticmethod(distance_ratio) cuda() autocnet/camera/camera.py +1 −1 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ try: except: cv2 = None def compute_epipoles(f): """ Compute the epipole and epipolar prime Loading @@ -28,7 +29,6 @@ def compute_epipoles(f): return e, e1 def idealized_camera(): """ Create an idealized camera transformation matrix Loading autocnet/control/control.py +54 −6 Original line number Diff line number Diff line import warnings import networkx as nx import numpy as np import pandas as pd import geopandas as gpd from shapely.geometry import Point from autocnet.matcher import subpixel as sp from plio.io.io_controlnetwork import to_isis, write_filelist def subpixel_match(cg, cn,threshold=0.9, template_size=19, search_size=53, max_x_shift=1.0,max_y_shift=1.0, **kwargs): def subpixel_group(group, threshold=0.9, template_size=19, search_size=53, max_x_shift=1.0,max_y_shift=1.0, **kwargs): offs = [] for i,(idx, r) in enumerate(group.iterrows()): if i == 0: x = r.x y = r.y offs.append([0,0, np.inf]) continue e = r.edge s_img = cg.edge[e[0]][e[1]].source.geodata s_template = sp.clip_roi(s_img, (x, y), template_size) #s_template = cv2.Canny(bytescale(s_template), 50,100) # Canny - bad idea d_img = cg.edge[e[0]][e[1]].destination.geodata d_search = sp.clip_roi(d_img, (r.x, r.y), search_size) #d_search = cv2.Canny(bytescale(d_search), 50,100) xoff,yoff,corr = sp.subpixel_offset(s_template, d_search, **kwargs) offs.append([xoff,yoff,corr]) df = pd.DataFrame(offs, columns=['x_off', 'y_off', 'corr'], index=group.index) return df gps = cn.data.groupby('point_id').apply(subpixel_group,threshold=0.9,max_x_shift=5, max_y_shift=5,template_size=template_size, search_size=search_size,**kwargs) cn.data[['x_off', 'y_off', 'corr']] = gps.reset_index()[['x_off', 'y_off', 'corr']] def identify_potential_overlaps(cg, cn, overlap=True): """ Loading Loading @@ -94,7 +122,7 @@ def deepen_correspondences(cg, cn): pass class ControlNetwork(object): measures_keys = ['point_id', 'image_index', 'keypoint_index', 'edge', 'match_idx', 'x', 'y'] measures_keys = ['point_id', 'image_index', 'keypoint_index', 'edge', 'match_idx', 'x', 'y', 'x_off', 'y_off', 'corr', 'valid'] def __init__(self): self._point_id = 0 Loading Loading @@ -150,9 +178,14 @@ class ControlNetwork(object): # The node_id is a composite key (image_id, correspondence_id), so just grab the image image_id = key[0] match_id = key[1] self.data.loc[self._measure_id] = [point_id, image_id, match_id, edge, match_idx, *fields] self.data.loc[self._measure_id] = [point_id, image_id, match_id, edge, match_idx, *fields, 0, 0, np.inf, True] self._measure_id += 1 def remove_measure(self, idx): self.data = self.data.drop(self.data.index[idx]) for r in idx: self.measure_to_point.pop(r, None) def validate_points(self): """ Ensure that all control points currently in the nework are valid. Loading @@ -168,14 +201,20 @@ class ControlNetwork(object): """ def func(g): print(g) # One and only one measure constraint if not g.image_index.duplicated().any(): if g.image_index.duplicated().any(): return True else: return False return self.data.groupby('point_id').apply(func) def clean_singles(self): """ Take the `data` dataframe and return only those points with at least two measures. This is automatically called before writing as functions such as subpixel matching can result in orphaned measures. """ return self.data.groupby('point_id').apply(lambda g: g if len(g) > 1 else None) def to_isis(self, outname, serials, olist, *args, **kwargs): #pragma: no cover """ Write the control network out to the ISIS3 control network format. Loading @@ -185,9 +224,18 @@ class ControlNetwork(object): warnings.warn('Control Network is not ISIS3 compliant. Please run the validate_points method on the control network.') return to_isis(outname + '.net', self.data, serials, *args, **kwargs) # Apply the subpixel shift self.data.x += self.data.x_off self.data.y += self.data.y_off to_isis(outname + '.net', self.data.query('valid == True'), serials, *args, **kwargs) write_filelist(olist, outname + '.lis') # Back out the subpixel shift self.data.x -= self.data.x_off self.data.y -= self.data.y_off def to_bal(self): """ Write the control network out to the Bundle Adjustment in the Large Loading autocnet/control/tests/test_control.py +4 −4 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ from .. import control def test_fromcandidategraph(candidategraph, controlnetwork_data):#, controlnetwork): matches = candidategraph.get_matches() cn = control.ControlNetwork.from_candidategraph(matches) assert cn.data.equals(controlnetwork_data) assert cn.data[['point_id', 'image_index']].equals(controlnetwork_data[['point_id', 'image_index']]) def test_add_measure(): cn = control.ControlNetwork() Loading @@ -36,11 +36,11 @@ def test_add_measure(): assert cn.measure_to_point[key] == 0 def test_validate_points(controlnetwork): assert controlnetwork.validate_points().any() assert not controlnetwork.validate_points().any() def test_bad_validate_points(bad_controlnetwork): assert bad_controlnetwork.validate_points().iloc[0] == False assert bad_controlnetwork.validate_points().iloc[1:].all() assert bad_controlnetwork.validate_points().iloc[0] == True assert not bad_controlnetwork.validate_points().iloc[1:].all() def test_identify_potential_overlaps(controlnetwork, candidategraph): res = control.identify_potential_overlaps(candidategraph, Loading Loading
.travis.yml +1 −11 Original line number Diff line number Diff line language: generic # Since we use conda, just go generic sudo: false branches: Loading @@ -7,8 +8,6 @@ only: env: global: - BINSTAR_USER: jlaura matrix: - PYTHON_VERSION: 3.5 os: - linux Loading @@ -18,18 +17,10 @@ install: # We do this conditionally because it saves us some downloading if the # version is the same. - if [ "$TRAVIS_OS_NAME" == "linux" ]; then if [ "$PYTHON_VERSION" == 2.7 ]; then wget https://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh; else wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; fi else if ["$PYTHON_VERSION" == 2.7]; then curl -o miniconda.sh https://repo.continuum.io/miniconda/Miniconda-latest-MacOSX-x86_64.sh; else curl -o miniconda.sh https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh; fi fi - bash miniconda.sh -b -p $HOME/miniconda - export PATH="$HOME/miniconda/bin:$PATH" - hash -r Loading @@ -43,7 +34,6 @@ install: - conda config --add channels menpo - conda config --add channels jlaura - conda config --set ssl_verify false - conda install python=$PYTHON_VERSION - conda install -c conda-forge numpy opencv - conda install -c jlaura plio - conda install -c conda-forge vlfeat Loading
autocnet/__init__.py +6 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,9 @@ def cuda(enable=False, gpu=0): from autocnet.matcher.cuda_decompose import decompose_and_match Edge.decompose_and_match = decompose_and_match from autocnet.matcher.cuda_outlier_detector import distance_ratio Edge._ratio_check = staticmethod(distance_ratio) except Exception: warnings.warn('Failed to enable Cuda') return Loading @@ -57,4 +60,7 @@ def cuda(enable=False, gpu=0): from autocnet.matcher.cpu_decompose import decompose_and_match Edge.decompose_and_match = decompose_and_match from autocnet.matcher.cpu_outlier_detector import distance_ratio Edge._ratio_check = staticmethod(distance_ratio) cuda()
autocnet/camera/camera.py +1 −1 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ try: except: cv2 = None def compute_epipoles(f): """ Compute the epipole and epipolar prime Loading @@ -28,7 +29,6 @@ def compute_epipoles(f): return e, e1 def idealized_camera(): """ Create an idealized camera transformation matrix Loading
autocnet/control/control.py +54 −6 Original line number Diff line number Diff line import warnings import networkx as nx import numpy as np import pandas as pd import geopandas as gpd from shapely.geometry import Point from autocnet.matcher import subpixel as sp from plio.io.io_controlnetwork import to_isis, write_filelist def subpixel_match(cg, cn,threshold=0.9, template_size=19, search_size=53, max_x_shift=1.0,max_y_shift=1.0, **kwargs): def subpixel_group(group, threshold=0.9, template_size=19, search_size=53, max_x_shift=1.0,max_y_shift=1.0, **kwargs): offs = [] for i,(idx, r) in enumerate(group.iterrows()): if i == 0: x = r.x y = r.y offs.append([0,0, np.inf]) continue e = r.edge s_img = cg.edge[e[0]][e[1]].source.geodata s_template = sp.clip_roi(s_img, (x, y), template_size) #s_template = cv2.Canny(bytescale(s_template), 50,100) # Canny - bad idea d_img = cg.edge[e[0]][e[1]].destination.geodata d_search = sp.clip_roi(d_img, (r.x, r.y), search_size) #d_search = cv2.Canny(bytescale(d_search), 50,100) xoff,yoff,corr = sp.subpixel_offset(s_template, d_search, **kwargs) offs.append([xoff,yoff,corr]) df = pd.DataFrame(offs, columns=['x_off', 'y_off', 'corr'], index=group.index) return df gps = cn.data.groupby('point_id').apply(subpixel_group,threshold=0.9,max_x_shift=5, max_y_shift=5,template_size=template_size, search_size=search_size,**kwargs) cn.data[['x_off', 'y_off', 'corr']] = gps.reset_index()[['x_off', 'y_off', 'corr']] def identify_potential_overlaps(cg, cn, overlap=True): """ Loading Loading @@ -94,7 +122,7 @@ def deepen_correspondences(cg, cn): pass class ControlNetwork(object): measures_keys = ['point_id', 'image_index', 'keypoint_index', 'edge', 'match_idx', 'x', 'y'] measures_keys = ['point_id', 'image_index', 'keypoint_index', 'edge', 'match_idx', 'x', 'y', 'x_off', 'y_off', 'corr', 'valid'] def __init__(self): self._point_id = 0 Loading Loading @@ -150,9 +178,14 @@ class ControlNetwork(object): # The node_id is a composite key (image_id, correspondence_id), so just grab the image image_id = key[0] match_id = key[1] self.data.loc[self._measure_id] = [point_id, image_id, match_id, edge, match_idx, *fields] self.data.loc[self._measure_id] = [point_id, image_id, match_id, edge, match_idx, *fields, 0, 0, np.inf, True] self._measure_id += 1 def remove_measure(self, idx): self.data = self.data.drop(self.data.index[idx]) for r in idx: self.measure_to_point.pop(r, None) def validate_points(self): """ Ensure that all control points currently in the nework are valid. Loading @@ -168,14 +201,20 @@ class ControlNetwork(object): """ def func(g): print(g) # One and only one measure constraint if not g.image_index.duplicated().any(): if g.image_index.duplicated().any(): return True else: return False return self.data.groupby('point_id').apply(func) def clean_singles(self): """ Take the `data` dataframe and return only those points with at least two measures. This is automatically called before writing as functions such as subpixel matching can result in orphaned measures. """ return self.data.groupby('point_id').apply(lambda g: g if len(g) > 1 else None) def to_isis(self, outname, serials, olist, *args, **kwargs): #pragma: no cover """ Write the control network out to the ISIS3 control network format. Loading @@ -185,9 +224,18 @@ class ControlNetwork(object): warnings.warn('Control Network is not ISIS3 compliant. Please run the validate_points method on the control network.') return to_isis(outname + '.net', self.data, serials, *args, **kwargs) # Apply the subpixel shift self.data.x += self.data.x_off self.data.y += self.data.y_off to_isis(outname + '.net', self.data.query('valid == True'), serials, *args, **kwargs) write_filelist(olist, outname + '.lis') # Back out the subpixel shift self.data.x -= self.data.x_off self.data.y -= self.data.y_off def to_bal(self): """ Write the control network out to the Bundle Adjustment in the Large Loading
autocnet/control/tests/test_control.py +4 −4 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ from .. import control def test_fromcandidategraph(candidategraph, controlnetwork_data):#, controlnetwork): matches = candidategraph.get_matches() cn = control.ControlNetwork.from_candidategraph(matches) assert cn.data.equals(controlnetwork_data) assert cn.data[['point_id', 'image_index']].equals(controlnetwork_data[['point_id', 'image_index']]) def test_add_measure(): cn = control.ControlNetwork() Loading @@ -36,11 +36,11 @@ def test_add_measure(): assert cn.measure_to_point[key] == 0 def test_validate_points(controlnetwork): assert controlnetwork.validate_points().any() assert not controlnetwork.validate_points().any() def test_bad_validate_points(bad_controlnetwork): assert bad_controlnetwork.validate_points().iloc[0] == False assert bad_controlnetwork.validate_points().iloc[1:].all() assert bad_controlnetwork.validate_points().iloc[0] == True assert not bad_controlnetwork.validate_points().iloc[1:].all() def test_identify_potential_overlaps(controlnetwork, candidategraph): res = control.identify_potential_overlaps(candidategraph, Loading