Loading autocnet/cg/cg.py +22 −0 Original line number Diff line number Diff line Loading @@ -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 autocnet/fileio/io_gdal.py +0 −1 Original line number Diff line number Diff line Loading @@ -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): Loading autocnet/graph/edge.py +39 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 autocnet/graph/tests/test_edge.py +57 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) autocnet/utils/tests/test_utils.py +14 −1 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ import unittest import numpy as np import pandas as pd from osgeo import ogr from .. import utils Loading Loading @@ -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
autocnet/cg/cg.py +22 −0 Original line number Diff line number Diff line Loading @@ -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
autocnet/fileio/io_gdal.py +0 −1 Original line number Diff line number Diff line Loading @@ -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): Loading
autocnet/graph/edge.py +39 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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
autocnet/graph/tests/test_edge.py +57 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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)
autocnet/utils/tests/test_utils.py +14 −1 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ import unittest import numpy as np import pandas as pd from osgeo import ogr from .. import utils Loading Loading @@ -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