Commit 00b61096 authored by Jay's avatar Jay Committed by jay
Browse files

Fixed network extract_features to take extraction parameters, not just nfeatures.

parent c4a50ff6
Loading
Loading
Loading
Loading
+35 −20
Original line number Diff line number Diff line
@@ -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
@@ -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):
        """
@@ -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']

@@ -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,
+1 −1
Original line number Diff line number Diff line
@@ -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)
+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 
@@ -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. 

@@ -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)
+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.
@@ -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)
+1 −1
Original line number Diff line number Diff line
@@ -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