Source code for autocnet.matcher.cpu_extractor

import warnings

from cv2 import ORB_create, FastFeatureDetector_create
import numpy as np
import pandas as pd
from autocnet.utils.utils import bytescale

try:
    import cyvlfeat as vl
    vlfeat = True
except Exception:  # pragma: no cover
    vlfeat = False
    pass

try:
    from cv2 import xfeatures2d
    SIFT = xfeatures2d.SIFT_create
    SURF = xfeatures2d.SURF_create
except Exception:  # pragma: no cover
    SIFT = None
    SURF = None
    pass


[docs]def extract_features(array, extractor_method='sift', 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 with corresponding descriptors. Parameters ---------- array : ndarray a NumPy array that represents an image extractor_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 ------- keypoints : DataFrame data frame of coordinates ('x', 'y', 'size', 'angle', and other available information) descriptors : ndarray Of descriptors """ detectors = {'fast': FastFeatureDetector_create, 'sift': SIFT, 'surf': SURF, 'orb' : ORB_create} if extractor_method == 'vlfeat' and vlfeat != True: raise ImportError('VLFeat is not available. Please install vlfeat or use a different extractor.') if extractor_method == 'vlfeat': keypoint_objs, descriptors = vl.sift.sift(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[extractor_method](**extractor_parameters) 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 hasattr(descriptors, 'dtype') and descriptors.dtype != np.float32: descriptors = descriptors.astype(np.float32) return keypoints, descriptors
[docs]def extract_most_interesting(image, extractor_method='orb', extractor_parameters={'nfeatures':10}): """ Given an image, extract the most interesting feature. Interesting is defined as the feature descriptor that has the maximum variance. By default, this func finds 10 features in the image and then selects the best. Parameters ---------- image : ndarray of DN values extractor_method : str Any valid, autocnet extractor. Default (orb) exctractor_parameters : dict of extractor parameters passed through to the feature extractor Returns ------- : pd.series The keypoints row with the higest variance. The row has 'x' and 'y' columns to get the location. """ kps, desc = extract_features(image, extractor_method=extractor_method, extractor_parameters=extractor_parameters) if len(kps) == 0: return None # Naively assume that the maximum variance is the most unique feature vari = np.var(desc, axis=1) return kps.iloc[np.argmax(vari)]