Commit d1565d58 authored by jlaura's avatar jlaura Committed by GitHub
Browse files

Merge pull request #129 from jlaura/master

Generalize the feature extractor
parents b7c64e3b e13d668a
Loading
Loading
Loading
Loading
+1 −23
Changes for autocnet/graph/node.py: 1 added line, 23 removed lines.
Original line number Diff line number Diff line
@@ -226,29 +226,7 @@ class Node(dict, MutableMapping):
                 kwargs passed to autocnet.feature_extractor.extract_features

        """
        keypoint_objs, self.descriptors = fe.extract_features(array, **kwargs)
        if self.descriptors.dtype != np.float32:
            self.descriptors = self.descriptors.astype(np.float32)

        # OpenCV returned keypoint objects
        if isinstance(keypoint_objs, list):
            keypoints = np.empty((len(keypoint_objs), 7), dtype=np.float32)
            for i, kpt in enumerate(keypoint_objs):
                octave = kpt.octave & 8
                layer = (kpt.octave >> 8) & 255
                if octave < 128:
                    octave = octave
                else:
                    octave = (-128 | octave)
                keypoints[i] = kpt.pt[0], kpt.pt[1], kpt.response, kpt.size, kpt.angle, octave, layer  # y, x
            self._keypoints = pd.DataFrame(keypoints, columns=['x', 'y', 'response', 'size',
                                                               'angle', 'octave', 'layer'])

        # VLFeat returned keypoint objects
        elif isinstance(keypoint_objs, np.ndarray):
            # Swap columns for value style access, vl_feat returns y, x
            keypoint_objs[:, 0], keypoint_objs[:, 1] = keypoint_objs[:, 1], keypoint_objs[:, 0].copy()
            self._keypoints = pd.DataFrame(keypoint_objs, columns=['x', 'y', 'size', 'angle'])
        self._keypoints, self.descriptors = fe.extract_features(array, **kwargs)

    def load_features(self, in_path):
        """
+42 −7
Changes for autocnet/matcher/feature_extractor.py: 42 added lines, 7 removed lines.
Original line number Diff line number Diff line
import cv2
import numpy as np
import pandas as pd

from scipy.misc import bytescale

try:
    import cyvlfeat as vl
@@ -8,7 +12,7 @@ except:
    pass


def extract_features(array, method='orb', extractor_parameters=None):
def extract_features(array, method='orb', 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
@@ -19,16 +23,20 @@ def extract_features(array, method='orb', extractor_parameters=None):
    array : ndarray
            a NumPy array that represents an image

    detector : {'orb', 'sift', 'fast', 'surf'}
              The detector method to be used
    method : {'orb', 'sift', 'fast', 'surf', 'vl_sift'}
              The detector method to be used.  Note that vl_sift requires that
              vlfeat and cyvlfeat dependencies be installed.

    extractor_parameters : dict
                           A dictionary containing OpenCV SIFT parameters names and values.

    Returns
    -------
    : tuple
      in the form ([list of OpenCV KeyPoints], [NumPy array of descriptors as geometric vectors])
    keypoints : DataFrame
                data frame of coordinates ('x', 'y', 'size', 'angle', and other available information)

    descriptors : ndarray
                  Of descriptors
    """

    detectors = {'fast': cv2.FastFeatureDetector_create,
@@ -39,7 +47,34 @@ def extract_features(array, method='orb', extractor_parameters=None):
        detectors['vl_sift'] = vl.sift.sift

    if 'vl_' in method:
        return detectors[method](array, compute_descriptor=True, float_descriptors=True, **extractor_parameters)
        keypoint_objs, descriptors = detectors[method](array,
                                                       compute_descriptor=True,
                                                       float_descriptors=True,
                                                       **extractor_parameters)
        # Swap columns for value style access, vl_feat returns y, x
        keypoint_objs[:, 0], keypoint_objs[:, 1] = keypoint_objs[:, 1], keypoint_objs[:, 0].copy()
        keypoints = pd.DataFrame(keypoint_objs, columns=['x', 'y', 'size', 'angle'])

    else:
        # OpenCV requires the input images to be 8-bit
        if not array.dtype == 'int8':
            array = bytescale(array)
        detector = detectors[method](**extractor_parameters)
        return detector.detectAndCompute(array, None)
        keypoint_objs, descriptors = detector.detectAndCompute(array, None)

        keypoints = np.empty((len(keypoint_objs), 7), dtype=np.float32)
        for i, kpt in enumerate(keypoint_objs):
            octave = kpt.octave & 8
            layer = (kpt.octave >> 8) & 255
            if octave < 128:
                octave = octave
            else:
                octave = (-128 | octave)
            keypoints[i] = kpt.pt[0], kpt.pt[1], kpt.response, kpt.size, kpt.angle, octave, layer  # y, x
        keypoints = pd.DataFrame(keypoints, columns=['x', 'y', 'response', 'size',
                                                     'angle', 'octave', 'layer'])

        if descriptors.dtype != np.float32:
            descriptors = descriptors.astype(np.float32)

    return keypoints, descriptors
 No newline at end of file
+4 −6
Changes for autocnet/matcher/tests/test_feature_extractor.py: 4 added lines, 6 removed lines.
Original line number Diff line number Diff line
import os
import numpy as np
import pandas as pd
import unittest
from autocnet.examples import get_path
import cv2
@@ -25,17 +26,14 @@ class TestFeatureExtractor(unittest.TestCase):
                          "sigma": 1.6}

    def test_extract_features(self):
        features = feature_extractor.extract_features(self.data_array,
        features, descriptors = feature_extractor.extract_features(self.data_array,
                                                                   method='sift',
                                                                   extractor_parameters=self.parameters)
        self.assertEquals(len(features), 2)
        self.assertIn(len(features[0]), range(8, 12))
        self.assertIsInstance(features[0][0], type(cv2.KeyPoint()))
        self.assertIsInstance(features[1][0], np.ndarray)
        self.assertEquals(len(features), 10)

    def test_extract_vlfeat(self):
        kps, descriptors = feature_extractor.extract_features(self.data_array,
                                                              method='vl_sift',
                                                              extractor_parameters={})
        self.assertIsInstance(kps, np.ndarray)
        self.assertIsInstance(kps, pd.DataFrame)
        self.assertEqual(descriptors.dtype, np.float32)