Commit 5862ac95 authored by Kristin Berry's avatar Kristin Berry
Browse files

Merge pull request #43 from jlaura/master

Convex Hull Computations
parents bf536437 319c642d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ install:

  # Install the non-conda packages if required, requirements.txt duplicates are ignored
  - conda install -c https://conda.anaconda.org/jlaura opencv3=3.0.0
  - conda install -c https://conda.anaconda.org/anaconda gdal
  - conda install -c https://conda.anaconda.org/osgeo gdal
  - conda install -c osgeo proj4
  - conda upgrade numpy
  - pip install -r requirements.txt
+21 −5
Original line number Diff line number Diff line
import json
import ogr
from scipy.spatial import ConvexHull


def convex_hull_ratio(points, ideal_area):
    """

@@ -23,9 +25,23 @@ def convex_hull_ratio(points, ideal_area):


def overlapping_polygon_area(polys):
    intersection = ogr.CreateGeometryFromWkt(polys[0])
    for p in polys[1:]:
        geom = ogr.CreateGeometryFromWkt(p)
        intersection = intersection.Intersection(geom).ExportToWkt()
    """

    Parameters
    ----------
    polys : list
            of polygon object with a __geo_interface__

    Returns
    -------
    area : float
           The area of the intersecting polygons
    """
    geom = json.dumps(polys[0].__geo_interface__)
    intersection = ogr.CreateGeometryFromJson(geom)
    for p in polys[1:]:
        geom = json.dumps(p.__geo_interface__)
        geom = ogr.CreateGeometryFromJson(geom)
        intersection = intersection.Intersection(geom)
    area = intersection.GetArea()
    return area
+20 −0
Original line number Diff line number Diff line
import os

from pysal.cg.shapes import Polygon
import numpy as np
import gdal
import osr
@@ -206,6 +207,25 @@ class GeoDataset(object):

        return self._xy_extent

    @property
    def pixel_polygon(self):
        """
        A bounding polygon in pixel space

        Returns
        -------
        : object
          A PySAL Polygon object
        """
        if not getattr(self, '_pixel_polygon', None):
            (minx, miny), (maxx, maxy) = self.xy_extent
            ul = maxx, miny
            ll = minx, miny
            lr = minx, maxy
            ur = maxx, maxy
            self._pixel_polygon = Polygon([ul, ll, lr, ur, ul])
        return self._pixel_polygon

    @property
    def pixel_area(self):
        if not getattr(self, '_pixel_area', None):
+32 −9
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ import os
import networkx as nx
import pandas as pd
import cv2
from pysal.cg.shapes import Polygon
import numpy as np

from scipy.misc import bytescale
@@ -10,7 +11,7 @@ from scipy.misc import bytescale
from autocnet.control.control import C
from autocnet.fileio import io_json
from autocnet.fileio.io_gdal import GeoDataset
from autocnet.matcher import feature_extractor as fe # extract features from image
from autocnet.matcher import feature_extractor as fe
from autocnet.matcher import outlier_detector as od
from autocnet.matcher import subpixel as sp
from autocnet.cg.cg import convex_hull_ratio, overlapping_polygon_area
@@ -99,7 +100,7 @@ class Edge(object):
        if hasattr(self, 'matches'):
            matches = self.matches
        else:
            raise(AttributeError, 'Matches have not been computed for this edge')
            raise AttributeError('Matches have not been computed for this edge')

        if clean_keys:
            mask = np.prod([self._mask_arrays[i] for i in clean_keys], axis=0, dtype=np.bool)
@@ -192,13 +193,14 @@ class Edge(object):
                                                                             'correlation'])
        self.masks = ('subpixel', mask)

    def convex_hull_coverage(self, clean_keys=[]):
    def coverage_ratio(self, clean_keys=[]):
        """
        Compute the ratio $area_{convexhull} / area_{imageoverlap}$.

        Returns
        -------
        ratio : float
                The ratio $area_{convexhull} / area_{imageoverlap}$
        """
        if self.homography is None:
            raise AttributeError('A homography has not been computed. Unable to determine image overlap.')
@@ -214,10 +216,10 @@ class Edge(object):
        if len(keypoints) < 3:
            raise ValueError('Convex hull computation requires at least 3 measures.')

        # TODO: Ideal area is mocked in
        ideal_area = self.compute_homography_overlap()
        source_geom, proj_geom, ideal_area = self.compute_homography_overlap()

        ratio = convex_hull_ratio(keypoints, ideal_area)
        return ratio

    def compute_homography_overlap(self):
        """
@@ -226,13 +228,34 @@ class Edge(object):

        Returns
        -------
        source_geom : object
                      PySAL Polygon object of the source pixel bounding box

        projected_geom : object
                         PySAL Polygon object of the destination geom projected
                         into the source reference system using the current
                         homography

        area : float
               The estimated area
        """
        return 1.0

    def plot(self, clean_keys=[], **kwargs):
        return plot_edge(self, clean_keys=clean_keys, **kwargs)
        source_geom = self.source.handle.pixel_polygon
        destination_geom = self.destination.handle.pixel_polygon

        # Project using the homography
        vertices_to_project = destination_geom.vertices
        for i, v in enumerate(vertices_to_project):
            vertices_to_project[i] = tuple(np.array([v[0], v[1], 1]).dot(self.homography)[:2])
        projected_geom = Polygon(vertices_to_project)

        # Estimate the overlapping area
        area = overlapping_polygon_area([source_geom, projected_geom])

        return source_geom, projected_geom, area

    def plot(self, ax=None, clean_keys=[], **kwargs):
        return plot_edge(self, ax=ax, clean_keys=clean_keys, **kwargs)

    def update(self, *args):
        # Added for NetworkX
@@ -329,7 +352,7 @@ class Node(object):
        mask = od.adaptive_non_max_suppression(self.keypoints,nfeatures,robust)
        self.masks = ('anms', mask)

    def convex_hull_ratio(self, clean_keys=[]):
    def coverage_ratio(self, clean_keys=[]):
        """
        Compute the ratio $area_{convexhull} / area_{total}$

+1 −1
Original line number Diff line number Diff line
@@ -73,6 +73,6 @@ class TestNode(unittest.TestCase):
    def test_convex_hull_ratio_fail(self):
        # Convex hull computation is checked lower in the hull computation
        node = self.graph.node[0]
        self.assertRaises(AttributeError,node.convex_hull_ratio)
        self.assertRaises(AttributeError, node.coverage_ratio)

Loading