Commit da3cfdb8 authored by Kelvin Rodriguez's avatar Kelvin Rodriguez Committed by GitHub
Browse files

Merge pull request #229 from jlaura/control

Control
parents 4fe32abb aa0fc51b
Loading
Loading
Loading
Loading
+1 −11
Original line number Diff line number Diff line
language: generic  # Since we use conda, just go generic
sudo: false

branches:
@@ -7,8 +8,6 @@ only:
env:
  global:
    - BINSTAR_USER: jlaura
  matrix:
    - PYTHON_VERSION: 3.5

os:
  - linux
@@ -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
@@ -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
+6 −0
Original line number Diff line number Diff line
@@ -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
@@ -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()
+1 −1
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ try:
except:
    cv2 = None


def compute_epipoles(f):
    """
    Compute the epipole and epipolar prime
@@ -28,7 +29,6 @@ def compute_epipoles(f):

    return e, e1


def idealized_camera():
    """
    Create an idealized camera transformation matrix
+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):
    """
@@ -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
@@ -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.
@@ -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.
@@ -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
+4 −4
Original line number Diff line number Diff line
@@ -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()
@@ -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