Loading autocnet/graph/network.py +35 −20 Original line number Diff line number Diff line Loading @@ -5,7 +5,8 @@ import pandas as pd import cv2 import numpy as np from scipy.misc import bytescale # store image array from scipy.misc import bytescale, imresize from autocnet.control.control import C from autocnet.fileio import io_json Loading Loading @@ -151,41 +152,59 @@ class CandidateGraph(nx.Graph): #self.node_labels[self.node[self.node_counter]['image_name']] = self.node_counter self.node_counter += 1 def get_geodataset(self, nodeIndex): def get_geodataset(self, nodeindex): """ Constructs a GeoDataset object from the given node image and assigns the dataset and its NumPy array to the 'handle' and 'image' node attributes. Parameters ---------- nodeIndex : int nodeindex : int The index of the node. """ self.node[nodeIndex]['handle'] = GeoDataset(self.node[nodeIndex]['image_path']) self.node[nodeIndex]['image'] = bytescale(self.node[nodeIndex]['handle'].read_array()) self.node[nodeindex]['handle'] = GeoDataset(self.node[nodeindex]['image_path']) def get_array(self, nodeindex, downsampling=1): """ Downsample the input image file by some amount using bicubic interpolation in order to reduce data sizes for visualization and analysis, e.g. feature detection Parameters ---------- nodeindex : hashable The index into the node containing a geodataset object def extract_features(self, nfeatures) : downsampling : int [1, infinity] downsampling """ array = self.node[nodeindex]['handle'].read_array() newx_size = int(array.shape[0] / downsampling) newy_size = int(array.shape[1] / downsampling) resized_array = imresize(array, (newx_size, newy_size), interp='bicubic') self.node[nodeindex]['image'] = bytescale(resized_array) self.node[nodeindex]['image_downsampling'] = downsampling def extract_features(self, extractor_parameters={}, downsampling=1): """ Extracts features from each image in the graph and uses the result to assign the node attributes for 'handle', 'image', 'keypoints', and 'descriptors'. Parameters ---------- nfeatures : int The number of features to be extracted. extractor_parameters : dict A dictionary containing OpenCV SIFT parameters names and values. downsampling : int The divisor to image_size to down sample the input image. """ # Loop through the nodes (i.e. images) on the graph and fill in their attributes. # These attributes are... # geo dataset (handle and image) # features (keypoints and descriptors) for node, attributes in self.nodes_iter(data=True): self.get_geodataset(node) extraction_params = {'nfeatures' : nfeatures} self.get_array(node, downsampling=downsampling) attributes['keypoints'], attributes['descriptors'] = fe.extract_features(attributes['image'], extraction_params) extractor_parameters) def add_matches(self, matches): """ Loading Loading @@ -394,7 +413,6 @@ class CandidateGraph(nx.Graph): if 'subpixel' in clean_keys: offsets = attributes['subpixel_offsets'][attributes['subpixel']] print(offsets) kp1 = self.node[source]['keypoints'] kp2 = self.node[destination]['keypoints'] Loading @@ -415,11 +433,8 @@ class CandidateGraph(nx.Graph): kp2y = kp2[m2[1]].pt[1] if 'subpixel' in clean_keys: print(idx) print(kp2x, kp2y) kp2x += offsets['x_offset'].values[i] kp2y += offsets['y_offset'].values[i] print(kp2x, kp2y) values.append([kp2x, kp2y, m2, Loading autocnet/graph/tests/test_network.py +1 −1 Original line number Diff line number Diff line Loading @@ -36,7 +36,7 @@ class TestCandidateGraph(unittest.TestCase): def test_extract_features(self): # also tests get_geodataset() and get_keypoints self.graph.extract_features(10) self.graph.extract_features(extractor_parameters={'nfeatures':10}) node_number = self.graph.node_name_map['AS15-M-0297_SML.png'] node = self.graph.node[node_number] self.assertEquals(len(node['image']), 1012) Loading autocnet/matcher/feature_extractor.py +5 −7 Original line number Diff line number Diff line import cv2 from scipy import misc def extract_features(image_array, extractor_parameters): def extract_features(array, extractor_parameters): """ This method finds and extracts features from an image using the given dictionary of keyword arguments. The input image is represented as NumPy array and the output features are represented as keypoint IDs Loading @@ -10,8 +9,9 @@ def extract_features(image_array, extractor_parameters): Parameters ---------- image_array : ndarray array : ndarray a NumPy array that represents an image extractor_parameters : dict A dictionary containing OpenCV SIFT parameters names and values. Loading @@ -22,6 +22,4 @@ def extract_features(image_array, extractor_parameters): """ sift = cv2.xfeatures2d.SIFT_create(**extractor_parameters) converted_array = misc.bytescale(image_array) return sift.detectAndCompute(converted_array, None) return sift.detectAndCompute(array, None) autocnet/matcher/subpixel.py +13 −13 Original line number Diff line number Diff line import pandas as pd from autocnet.matcher import matcher from scipy.misc import imresize # TODO: look into KeyPoint.size and perhaps use to determine an appropriately-sized search/template. # TODO: do not allow even sizes def subpixel_offset(template_kp, search_kp, template_img, search_img, template_size=9, search_size=27, upsampling=10): """ Uses a pattern-matcher on subsets of two images determined from the passed-in keypoints and optional sizes to compute an x and y offset from the search keypoint to the template keypoint and an associated strength. Loading Loading @@ -33,7 +32,8 @@ Parameters The returned tuple is of form: (x_offset, y_offset, strength). The offsets are from the search to the template keypoint. """ def subpixel_offset(template_kp, search_kp, template_img, search_img, template_size=9, search_size=27, upsampling=10): if template_size % 2 == 0 or search_size %2 == 0: raise ValueError('The search and template images must have an odd number of lines and samples') # Get the x,y coordinates temp_x, temp_y = map(int, template_kp.pt) search_x, search_y = map(int, search_kp.pt) Loading autocnet/matcher/tests/test_feature_extractor.py +1 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ class TestFeatureExtractor(unittest.TestCase): @classmethod def setUpClass(self): self.dataset = io_gdal.GeoDataset(get_path('AS15-M-0295_SML.png')) self.data_array = self.dataset.read_array() self.data_array = self.dataset.read_array(dtype='uint8') self.parameters = {"nfeatures" : 10, "nOctaveLayers" : 3, "contrastThreshold" : 0.02, Loading Loading
autocnet/graph/network.py +35 −20 Original line number Diff line number Diff line Loading @@ -5,7 +5,8 @@ import pandas as pd import cv2 import numpy as np from scipy.misc import bytescale # store image array from scipy.misc import bytescale, imresize from autocnet.control.control import C from autocnet.fileio import io_json Loading Loading @@ -151,41 +152,59 @@ class CandidateGraph(nx.Graph): #self.node_labels[self.node[self.node_counter]['image_name']] = self.node_counter self.node_counter += 1 def get_geodataset(self, nodeIndex): def get_geodataset(self, nodeindex): """ Constructs a GeoDataset object from the given node image and assigns the dataset and its NumPy array to the 'handle' and 'image' node attributes. Parameters ---------- nodeIndex : int nodeindex : int The index of the node. """ self.node[nodeIndex]['handle'] = GeoDataset(self.node[nodeIndex]['image_path']) self.node[nodeIndex]['image'] = bytescale(self.node[nodeIndex]['handle'].read_array()) self.node[nodeindex]['handle'] = GeoDataset(self.node[nodeindex]['image_path']) def get_array(self, nodeindex, downsampling=1): """ Downsample the input image file by some amount using bicubic interpolation in order to reduce data sizes for visualization and analysis, e.g. feature detection Parameters ---------- nodeindex : hashable The index into the node containing a geodataset object def extract_features(self, nfeatures) : downsampling : int [1, infinity] downsampling """ array = self.node[nodeindex]['handle'].read_array() newx_size = int(array.shape[0] / downsampling) newy_size = int(array.shape[1] / downsampling) resized_array = imresize(array, (newx_size, newy_size), interp='bicubic') self.node[nodeindex]['image'] = bytescale(resized_array) self.node[nodeindex]['image_downsampling'] = downsampling def extract_features(self, extractor_parameters={}, downsampling=1): """ Extracts features from each image in the graph and uses the result to assign the node attributes for 'handle', 'image', 'keypoints', and 'descriptors'. Parameters ---------- nfeatures : int The number of features to be extracted. extractor_parameters : dict A dictionary containing OpenCV SIFT parameters names and values. downsampling : int The divisor to image_size to down sample the input image. """ # Loop through the nodes (i.e. images) on the graph and fill in their attributes. # These attributes are... # geo dataset (handle and image) # features (keypoints and descriptors) for node, attributes in self.nodes_iter(data=True): self.get_geodataset(node) extraction_params = {'nfeatures' : nfeatures} self.get_array(node, downsampling=downsampling) attributes['keypoints'], attributes['descriptors'] = fe.extract_features(attributes['image'], extraction_params) extractor_parameters) def add_matches(self, matches): """ Loading Loading @@ -394,7 +413,6 @@ class CandidateGraph(nx.Graph): if 'subpixel' in clean_keys: offsets = attributes['subpixel_offsets'][attributes['subpixel']] print(offsets) kp1 = self.node[source]['keypoints'] kp2 = self.node[destination]['keypoints'] Loading @@ -415,11 +433,8 @@ class CandidateGraph(nx.Graph): kp2y = kp2[m2[1]].pt[1] if 'subpixel' in clean_keys: print(idx) print(kp2x, kp2y) kp2x += offsets['x_offset'].values[i] kp2y += offsets['y_offset'].values[i] print(kp2x, kp2y) values.append([kp2x, kp2y, m2, Loading
autocnet/graph/tests/test_network.py +1 −1 Original line number Diff line number Diff line Loading @@ -36,7 +36,7 @@ class TestCandidateGraph(unittest.TestCase): def test_extract_features(self): # also tests get_geodataset() and get_keypoints self.graph.extract_features(10) self.graph.extract_features(extractor_parameters={'nfeatures':10}) node_number = self.graph.node_name_map['AS15-M-0297_SML.png'] node = self.graph.node[node_number] self.assertEquals(len(node['image']), 1012) Loading
autocnet/matcher/feature_extractor.py +5 −7 Original line number Diff line number Diff line import cv2 from scipy import misc def extract_features(image_array, extractor_parameters): def extract_features(array, extractor_parameters): """ This method finds and extracts features from an image using the given dictionary of keyword arguments. The input image is represented as NumPy array and the output features are represented as keypoint IDs Loading @@ -10,8 +9,9 @@ def extract_features(image_array, extractor_parameters): Parameters ---------- image_array : ndarray array : ndarray a NumPy array that represents an image extractor_parameters : dict A dictionary containing OpenCV SIFT parameters names and values. Loading @@ -22,6 +22,4 @@ def extract_features(image_array, extractor_parameters): """ sift = cv2.xfeatures2d.SIFT_create(**extractor_parameters) converted_array = misc.bytescale(image_array) return sift.detectAndCompute(converted_array, None) return sift.detectAndCompute(array, None)
autocnet/matcher/subpixel.py +13 −13 Original line number Diff line number Diff line import pandas as pd from autocnet.matcher import matcher from scipy.misc import imresize # TODO: look into KeyPoint.size and perhaps use to determine an appropriately-sized search/template. # TODO: do not allow even sizes def subpixel_offset(template_kp, search_kp, template_img, search_img, template_size=9, search_size=27, upsampling=10): """ Uses a pattern-matcher on subsets of two images determined from the passed-in keypoints and optional sizes to compute an x and y offset from the search keypoint to the template keypoint and an associated strength. Loading Loading @@ -33,7 +32,8 @@ Parameters The returned tuple is of form: (x_offset, y_offset, strength). The offsets are from the search to the template keypoint. """ def subpixel_offset(template_kp, search_kp, template_img, search_img, template_size=9, search_size=27, upsampling=10): if template_size % 2 == 0 or search_size %2 == 0: raise ValueError('The search and template images must have an odd number of lines and samples') # Get the x,y coordinates temp_x, temp_y = map(int, template_kp.pt) search_x, search_y = map(int, search_kp.pt) Loading
autocnet/matcher/tests/test_feature_extractor.py +1 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ class TestFeatureExtractor(unittest.TestCase): @classmethod def setUpClass(self): self.dataset = io_gdal.GeoDataset(get_path('AS15-M-0295_SML.png')) self.data_array = self.dataset.read_array() self.data_array = self.dataset.read_array(dtype='uint8') self.parameters = {"nfeatures" : 10, "nOctaveLayers" : 3, "contrastThreshold" : 0.02, Loading