Commit d47c6944 authored by Kelvin Rodriguez's avatar Kelvin Rodriguez
Browse files

Merge pull request #123 from acpaquette/image

Added coverage method to the edge.
parents 7fe6fa31 41fc1456
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -77,3 +77,25 @@ def two_poly_overlap(poly1, poly2):
    overlap_area = a_o
    overlap_percn = (a_o / (area1 + area2 - a_o)) * 100
    return overlap_percn, overlap_area


def get_area(poly1, poly2):
    """

    Parameters
    ----------
    poly1 : ogr polygon
            General ogr polygon

    poly2 : ogr polygon
            General ogr polygon

    Returns
    -------
    intersection_area : float
                        returns the intersection area
                        of two polygons

    """
    intersection_area = poly1.Intersection(poly2).GetArea()
    return intersection_area
+0 −1
Original line number Diff line number Diff line
@@ -465,7 +465,6 @@ class GeoDataset(object):
            array = band.ReadAsArray(xstart, ystart, xextent, yextent).astype(dtype)
        return array


def array_to_raster(array, file_name, projection=None,
                    geotransform=None, outformat='GTiff',
                    ndv=None):
+39 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ from collections import MutableMapping
import numpy as np
import pandas as pd

from autocnet.utils import utils
from autocnet.matcher import health
from autocnet.matcher import outlier_detector as od
from autocnet.matcher import suppression_funcs as spf
@@ -423,3 +424,41 @@ class Edge(dict, MutableMapping):
        self.weight['overlap_area'] = overlapinfo[1]
        self.weight['overlap_percn'] = overlapinfo[0]

    def coverage(self, clean_keys = []):
        """
        Acts on the edge given either the source node
        or the destination node and returns the percentage
        of overlap covered by the keypoints. Data for the
        overlap is gathered from the source node of the edge
        resulting in a maximum area difference of 2% when compared
        to the destination.

        Returns
        -------
        total_overlap_percentage : float
                                   returns the overlap area
                                   covered by the keypoints
        """
        if self.matches is None:
            raise AttributeError('Edge needs to have features extracted and matched')
            return
        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
        destination_coords = self.destination.geodata.latlon_corners

        convex_hull = cg.convex_hull(source_array)

        convex_points = [self.source.geodata.pixel_to_latlon(row[0], row[1]) for row in convex_hull.points[convex_hull.vertices]]
        convex_coords = [(x, y) for x, y in convex_points]

        source_poly = utils.array_to_poly(source_coords)
        destination_poly = utils.array_to_poly(destination_coords)
        convex_poly = utils.array_to_poly(convex_coords)

        intersection_area = cg.get_area(source_poly, destination_poly)

        total_overlap_coverage = (convex_poly.GetArea()/intersection_area)

        return total_overlap_coverage
+57 −0
Original line number Diff line number Diff line
@@ -2,7 +2,10 @@ import unittest
import ogr

from unittest.mock import Mock
from unittest.mock import MagicMock

from autocnet.examples import get_path
from autocnet.graph.network import CandidateGraph
from autocnet.fileio import io_gdal
import pandas as pd

@@ -72,3 +75,57 @@ class TestEdge(unittest.TestCase):
        e.overlap()
        self.assertEqual(e.weight['overlap_area'], 400)
        self.assertAlmostEqual(e.weight['overlap_percn'], 14.285714285)

    def test_coverage(self):
        adjacency = get_path('two_image_adjacency.json')
        basepath = get_path('Apollo15')
        cg = CandidateGraph.from_adjacency(adjacency, basepath=basepath)
        keypoint_df = pd.DataFrame({'x': (15, 18, 18, 12, 12), 'y': (5, 10, 15, 15, 10)})
        keypoint_matches = [[0, 0, 1, 0],
                            [0, 1, 1, 1],
                            [0, 2, 1, 2],
                            [0, 3, 1, 3],
                            [0, 4, 1, 4]]

        matches_df = pd.DataFrame(data = keypoint_matches, columns = ['source_image', 'source_idx', 'destination_image', 'destination_idx'])
        e = edge.Edge()
        source_node = MagicMock(spec = node.Node())
        destination_node = MagicMock(spec = node.Node())

        source_node.get_keypoint_coordinates = MagicMock(return_value=keypoint_df)
        destination_node.get_keypoint_coordinates = MagicMock(return_value=keypoint_df)

        e.source = source_node
        e.destination = destination_node

        source_geodata = Mock(spec = io_gdal.GeoDataset)
        destination_geodata = Mock(spec = io_gdal.GeoDataset)

        e.source.geodata = source_geodata
        e.destination.geodata = destination_geodata

        source_corners = [(0, 0),
                          (20, 0),
                          (20, 20),
                          (0, 20)]

        destination_corners = [(10, 5),
                               (30, 5),
                               (30, 25),
                               (10, 25)]

        e.source.geodata.latlon_corners = source_corners
        e.destination.geodata.latlon_corners = destination_corners

        vals = {(15, 5):(15, 5), (18, 10):(18, 10), (18, 15):(18, 15), (12, 15):(12, 15), (12, 10):(12, 10)}

        def pixel_to_latlon(i, j):
            return vals[(i, j)]

        e.source.geodata.pixel_to_latlon = MagicMock(side_effect = pixel_to_latlon)
        e.destination.geodata.pixel_to_latlon = MagicMock(side_effect = pixel_to_latlon)

        e.matches = matches_df

        self.assertRaises(AttributeError, cg.edge[0][1].coverage)
        self.assertEqual(e.coverage(), 0.3)
+14 −1
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ import unittest
import numpy as np
import pandas as pd

from osgeo import ogr
from .. import utils


@@ -127,3 +128,15 @@ class TestUtils(unittest.TestCase):

        slope = utils.calculate_slope(x1, x2)
        self.assertEqual(slope[0], 2)

    def test_array_to_poly(self):
        array1 = np.array([[1, 2],
                           [3, 4],
                           [5, 6]])
        array2 = np.array([[1, 2, 3],
                           [4, 5, 6],
                           [7, 8, 9]])
        geom1 = utils.array_to_poly(array1)

        self.assertIsInstance(geom1, ogr.Geometry)
        self.assertRaises(ValueError, utils.array_to_poly, array2)
 No newline at end of file
Loading