mirror of
https://github.com/wassname/scikit-image.git
synced 2026-08-12 12:30:16 +08:00
Implement object oriented interface for BRIEF
This commit is contained in:
@@ -9,9 +9,9 @@ from .corner import (corner_kitchen_rosenfeld, corner_harris,
|
||||
hessian_matrix_eigvals)
|
||||
from .corner_cy import corner_moravec, corner_orientations
|
||||
from .template import match_template
|
||||
from ._brief import descriptor_brief
|
||||
from ._brief import BRIEF
|
||||
from .match import match_binary_descriptors
|
||||
from .util import pairwise_hamming_distance, create_keypoint_recarray
|
||||
from .util import pairwise_hamming_distance
|
||||
from .censure import keypoints_censure
|
||||
from .orb import keypoints_orb, descriptor_orb
|
||||
|
||||
@@ -29,9 +29,8 @@ __all__ = ['daisy',
|
||||
'corner_peaks',
|
||||
'corner_moravec',
|
||||
'match_template',
|
||||
'descriptor_brief',
|
||||
'BRIEF',
|
||||
'pairwise_hamming_distance',
|
||||
'create_keypoint_recarray',
|
||||
'match_binary_descriptors',
|
||||
'keypoints_censure',
|
||||
'corner_fast',
|
||||
|
||||
+97
-105
@@ -1,15 +1,15 @@
|
||||
import numpy as np
|
||||
from scipy.ndimage.filters import gaussian_filter
|
||||
|
||||
from .util import (_mask_border_keypoints, pairwise_hamming_distance,
|
||||
from .util import (DescriptorExtractor, _mask_border_keypoints,
|
||||
_prepare_grayscale_input_2D)
|
||||
|
||||
from ._brief_cy import _brief_loop
|
||||
|
||||
|
||||
def descriptor_brief(image, keypoints, descriptor_size=256, mode='normal',
|
||||
patch_size=49, sample_seed=1, variance=2):
|
||||
"""Extract BRIEF binary descriptors for given keypoints in an image.
|
||||
class BRIEF(DescriptorExtractor):
|
||||
|
||||
"""BRIEF binary descriptor extractor.
|
||||
|
||||
BRIEF (Binary Robust Independent Elementary Features) is an efficient
|
||||
feature point descriptor. It it is highly discriminative even when using
|
||||
@@ -24,58 +24,34 @@ def descriptor_brief(image, keypoints, descriptor_size=256, mode='normal',
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : 2D ndarray
|
||||
Input image.
|
||||
keypoints : (P, ...) recarray
|
||||
Record array as returned by `skimage.feature.create_keypoint_recarray`
|
||||
with the fields: `row`, `col`, `scale`, `orientation` and `response`.
|
||||
descriptor_size : int
|
||||
Size of BRIEF descriptor for each keypoint. Sizes 128, 256 and 512
|
||||
recommended by the authors. Default is 256.
|
||||
mode : {'normal', 'uniform'}
|
||||
Probability distribution for sampling location of decision pixel-pairs
|
||||
around keypoints.
|
||||
patch_size : int
|
||||
Length of the two dimensional square patch sampling region around
|
||||
the keypoints. Default is 49.
|
||||
mode : {'normal', 'uniform'}
|
||||
Probability distribution for sampling location of decision pixel-pairs
|
||||
around keypoints.
|
||||
sample_seed : int
|
||||
Seed for the random sampling of the decision pixel-pairs. From a square
|
||||
window with length patch_size, pixel pairs are sampled using the `mode`
|
||||
parameter to build the descriptors using intensity comparison. The
|
||||
value of `sample_seed` must be the same for the images to be matched
|
||||
while building the descriptors.
|
||||
variance : float
|
||||
Variance of the Gaussian low pass filter applied to the image to
|
||||
alleviate noise sensitivity, which is strongly recommended to obtain
|
||||
sigma : float
|
||||
Standard deviation of the Gaussian low pass filter applied to the image
|
||||
to alleviate noise sensitivity, which is strongly recommended to obtain
|
||||
discriminative and good descriptors.
|
||||
|
||||
Returns
|
||||
-------
|
||||
descriptors : (Q, `descriptor_size`) ndarray of dtype bool
|
||||
2D ndarray of binary descriptors of size `descriptor_size` for Q
|
||||
keypoints after filtering out border keypoints with value at an index
|
||||
``(i, j)`` either being `True` or `False` representing the outcome
|
||||
of the intensity comparison for i-th keypoint on j-th decision
|
||||
pixel-pair.
|
||||
keypoints : (Q, ...) recarray
|
||||
Record array as returned by `skimage.feature.create_keypoint_recarray`
|
||||
with the fields: `row`, `col`, `scale`, `orientation` and `response`.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] Michael Calonder, Vincent Lepetit, Christoph Strecha and Pascal Fua
|
||||
"BRIEF : Binary robust independent elementary features", 2010
|
||||
http://cvlabwww.epfl.ch/~lepetit/papers/calonder_eccv10.pdf
|
||||
|
||||
Examples
|
||||
--------
|
||||
>> from skimage.feature.corner import corner_peaks, corner_harris
|
||||
>> from skimage.feature import (pairwise_hamming_distance, descriptor_brief,
|
||||
... match_binary_descriptors,
|
||||
... create_keypoint_recarray)
|
||||
>> square1 = np.zeros([8, 8], dtype=np.int32)
|
||||
>> square1[2:6, 2:6] = 1
|
||||
>> square1
|
||||
>>> from skimage.feature import (corner_harris, corner_peaks, BRIEF,
|
||||
... match_binary_descriptors)
|
||||
>>> import numpy as np
|
||||
>>> square1 = np.zeros((8, 8), dtype=np.int32)
|
||||
>>> square1[2:6, 2:6] = 1
|
||||
>>> square1
|
||||
array([[0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 0, 0],
|
||||
@@ -84,17 +60,9 @@ def descriptor_brief(image, keypoints, descriptor_size=256, mode='normal',
|
||||
[0, 0, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32)
|
||||
>> keypoints1 = corner_peaks(corner_harris(square1), min_distance=1)
|
||||
>> keypoints1 = create_keypoint_recarray(keypoints1[:, 0], keypoints1[:, 1])
|
||||
>> descriptors1, keypoints1 = descriptor_brief(square1, keypoints1, patch_size=5)
|
||||
>> keypoints1
|
||||
rec.array([(2.0, 2.0, nan, nan, nan), (2.0, 5.0, nan, nan, nan),
|
||||
(5.0, 2.0, nan, nan, nan), (5.0, 5.0, nan, nan, nan)],
|
||||
dtype=[('row', '<f8'), ('col', '<f8'), ('octave', '<f8'),
|
||||
('orientation', '<f8'), ('response', '<f8')])
|
||||
>> square2 = np.zeros([9, 9], dtype=np.int32)
|
||||
>> square2[2:7, 2:7] = 1
|
||||
>> square2
|
||||
>>> square2 = np.zeros((9, 9), dtype=np.int32)
|
||||
>>> square2[2:7, 2:7] = 1
|
||||
>>> square2
|
||||
array([[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 0, 0],
|
||||
@@ -104,24 +72,14 @@ def descriptor_brief(image, keypoints, descriptor_size=256, mode='normal',
|
||||
[0, 0, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32)
|
||||
>> keypoints2 = corner_peaks(corner_harris(square2), min_distance=1)
|
||||
>> keypoints2 = create_keypoint_recarray(keypoints2[:, 0], keypoints2[:, 1])
|
||||
>> keypoints2
|
||||
rec.array([(2.0, 2.0, nan, nan, nan), (2.0, 6.0, nan, nan, nan),
|
||||
(6.0, 2.0, nan, nan, nan), (6.0, 6.0, nan, nan, nan)],
|
||||
dtype=[('row', '<f8'), ('col', '<f8'), ('octave', '<f8'),
|
||||
('orientation', '<f8'), ('response', '<f8')])
|
||||
>> descriptors2, keypoints2 = descriptor_brief(square2, keypoints2, patch_size=5)
|
||||
>> pairwise_hamming_distance(descriptors1, descriptors2)
|
||||
array([[ 0.03125 , 0.3203125, 0.3671875, 0.6171875],
|
||||
[ 0.3203125, 0.03125 , 0.640625 , 0.375 ],
|
||||
[ 0.375 , 0.6328125, 0.0390625, 0.328125 ],
|
||||
[ 0.625 , 0.3671875, 0.34375 , 0.0234375]])
|
||||
>> matched_kpts, mask1, mask2 = match_binary_descriptors(keypoints1,
|
||||
... descriptors1,
|
||||
... keypoints2,
|
||||
... descriptors2)
|
||||
>> matched_kpts
|
||||
>>> keypoints1 = corner_peaks(corner_harris(square1), min_distance=1)
|
||||
>>> keypoints2 = corner_peaks(corner_harris(square2), min_distance=1)
|
||||
>>> extractor = BRIEF(patch_size=5)
|
||||
>>> descs1, _ = extractor.extract(square1, keypoints1)
|
||||
>>> descs2, _ = extractor.extract(square2, keypoints2)
|
||||
>>> matches, idxs1, idxs2 = match_binary_descriptors(keypoints1, descs1,
|
||||
... keypoints2, descs2)
|
||||
>>> matches
|
||||
array([[[2, 2],
|
||||
[2, 2]],
|
||||
|
||||
@@ -133,53 +91,87 @@ def descriptor_brief(image, keypoints, descriptor_size=256, mode='normal',
|
||||
|
||||
[[5, 5],
|
||||
[6, 6]]])
|
||||
>>> mask1
|
||||
array([0, 1, 2, 3])
|
||||
>>> mask2
|
||||
array([0, 1, 2, 3])
|
||||
|
||||
"""
|
||||
|
||||
if mode not in ('normal', 'uniform'):
|
||||
raise ValueError("`mode` must be one of 'normal' or 'uniform'.")
|
||||
def __init__(self, descriptor_size=256, patch_size=49,
|
||||
mode='normal', sigma=1, sample_seed=1):
|
||||
|
||||
np.random.seed(sample_seed)
|
||||
if mode not in ('normal', 'uniform'):
|
||||
raise ValueError("`mode` must be 'normal' or 'uniform'.")
|
||||
|
||||
image = _prepare_grayscale_input_2D(image)
|
||||
self.descriptor_size = descriptor_size
|
||||
self.patch_size = patch_size
|
||||
self.mode = mode
|
||||
self.sigma = sigma
|
||||
self.sample_seed = sample_seed
|
||||
|
||||
# Gaussian Low pass filtering to alleviate noise sensitivity
|
||||
image = gaussian_filter(image, variance)
|
||||
image = np.ascontiguousarray(image)
|
||||
def extract(self, image, keypoints):
|
||||
"""Extract BRIEF binary descriptors for given keypoints in image.
|
||||
|
||||
# Sampling pairs of decision pixels in patch_size x patch_size window
|
||||
if mode == 'normal':
|
||||
samples = (patch_size / 5.0) * np.random.randn(descriptor_size * 8)
|
||||
samples = np.array(samples, dtype=np.int32)
|
||||
samples = samples[(samples < (patch_size // 2))
|
||||
& (samples > - (patch_size - 2) // 2)]
|
||||
Parameters
|
||||
----------
|
||||
image : 2D array
|
||||
Input image.
|
||||
keypoints : (N, 2) array
|
||||
Keypoint coordinates as ``(row, col)``.
|
||||
|
||||
pos1 = samples[:descriptor_size * 2]
|
||||
pos1 = pos1.reshape(descriptor_size, 2)
|
||||
pos2 = samples[descriptor_size * 2:descriptor_size * 4]
|
||||
pos2 = pos2.reshape(descriptor_size, 2)
|
||||
elif mode == 'uniform':
|
||||
samples = np.random.randint(-(patch_size - 2) // 2,
|
||||
(patch_size // 2) + 1,
|
||||
(descriptor_size * 2, 2))
|
||||
samples = np.array(samples, dtype=np.int32)
|
||||
pos1, pos2 = np.split(samples, 2)
|
||||
Returns
|
||||
-------
|
||||
descriptors : (Q, `descriptor_size`) array of dtype bool
|
||||
2D ndarray of binary descriptors of size `descriptor_size` for Q
|
||||
keypoints after filtering out border keypoints with value at an
|
||||
index ``(i, j)`` either being ``True`` or ``False`` representing
|
||||
the outcome of the intensity comparison for i-th keypoint on j-th
|
||||
decision pixel-pair. It is ``Q == np.sum(mask)``.
|
||||
mask : (N, ) array of dtype bool
|
||||
Mask indicating whether a keypoint has been filtered out
|
||||
(``False``) or is described in the `descriptors` array (``True``).
|
||||
|
||||
pos1 = np.ascontiguousarray(pos1)
|
||||
pos2 = np.ascontiguousarray(pos2)
|
||||
"""
|
||||
|
||||
# Removing keypoints that are within (patch_size / 2) distance from the
|
||||
# image border
|
||||
border_mask = _mask_border_keypoints(image.shape, keypoints.row,
|
||||
keypoints.col, patch_size // 2)
|
||||
np.random.seed(self.sample_seed)
|
||||
|
||||
keypoints_row = keypoints.row[border_mask].astype(np.intp)
|
||||
keypoints_col = keypoints.col[border_mask].astype(np.intp)
|
||||
image = _prepare_grayscale_input_2D(image)
|
||||
|
||||
descriptors = np.zeros((keypoints_row.shape[0], descriptor_size),
|
||||
dtype=bool, order='C')
|
||||
# Gaussian Low pass filtering to alleviate noise sensitivity
|
||||
image = np.ascontiguousarray(gaussian_filter(image, self.sigma))
|
||||
|
||||
_brief_loop(image, descriptors.view(np.uint8),
|
||||
keypoints_row, keypoints_col, pos1, pos2)
|
||||
# Sampling pairs of decision pixels in patch_size x patch_size window
|
||||
desc_size = self.descriptor_size
|
||||
patch_size = self.patch_size
|
||||
if self.mode == 'normal':
|
||||
samples = (patch_size / 5.0) * np.random.randn(desc_size * 8)
|
||||
samples = np.array(samples, dtype=np.int32)
|
||||
samples = samples[(samples < (patch_size // 2))
|
||||
& (samples > - (patch_size - 2) // 2)]
|
||||
|
||||
return descriptors, keypoints
|
||||
pos1 = samples[:desc_size * 2].reshape(desc_size, 2)
|
||||
pos2 = samples[desc_size * 2:desc_size * 4].reshape(desc_size, 2)
|
||||
elif self.mode == 'uniform':
|
||||
samples = np.random.randint(-(patch_size - 2) // 2,
|
||||
(patch_size // 2) + 1,
|
||||
(desc_size * 2, 2))
|
||||
samples = np.array(samples, dtype=np.int32)
|
||||
pos1, pos2 = np.split(samples, 2)
|
||||
|
||||
pos1 = np.ascontiguousarray(pos1)
|
||||
pos2 = np.ascontiguousarray(pos2)
|
||||
|
||||
# Removing keypoints that are within (patch_size / 2) distance from the
|
||||
# image border
|
||||
mask = _mask_border_keypoints(image.shape, keypoints, patch_size // 2)
|
||||
|
||||
keypoints = np.array(keypoints[mask, :], dtype=np.intp, order='C',
|
||||
copy=False)
|
||||
|
||||
descriptors = np.zeros((keypoints.shape[0], desc_size),
|
||||
dtype=bool, order='C')
|
||||
|
||||
_brief_loop(image, descriptors.view(np.uint8), keypoints, pos1, pos2)
|
||||
|
||||
return descriptors, mask
|
||||
|
||||
@@ -7,7 +7,7 @@ cimport numpy as cnp
|
||||
|
||||
|
||||
def _brief_loop(double[:, ::1] image, unsigned char[:, ::1] descriptors,
|
||||
Py_ssize_t[::1] keypoints_row, Py_ssize_t[::1] keypoints_col,
|
||||
Py_ssize_t[:, ::1] keypoints,
|
||||
int[:, ::1] pos0, int[:, ::1] pos1):
|
||||
|
||||
cdef Py_ssize_t k, d, kr, kc, pr0, pr1, pc0, pc1
|
||||
@@ -17,8 +17,8 @@ def _brief_loop(double[:, ::1] image, unsigned char[:, ::1] descriptors,
|
||||
pc0 = pos0[p, 1]
|
||||
pr1 = pos1[p, 0]
|
||||
pc1 = pos1[p, 1]
|
||||
for k in range(keypoints_row.shape[0]):
|
||||
kr = keypoints_row[k]
|
||||
kc = keypoints_col[k]
|
||||
for k in range(keypoints.shape[0]):
|
||||
kr = keypoints[k, 0]
|
||||
kc = keypoints[k, 1]
|
||||
if image[kr + pr0, kc + pc0] < image[kr + pr1, kc + pc1]:
|
||||
descriptors[k, p] = True
|
||||
|
||||
+12
-14
@@ -34,9 +34,9 @@ def match_binary_descriptors(keypoints1, descriptors1, keypoints2,
|
||||
-------
|
||||
matches : (Q, 2, 2) ndarray
|
||||
Location of Q matched keypoint pairs from two images.
|
||||
mask1 : (Q,) ndarray
|
||||
idxs1 : (Q,) ndarray
|
||||
Indices of keypoints in keypoints1 that have been matched.
|
||||
mask2 : (Q,) ndarray
|
||||
idxs2 : (Q,) ndarray
|
||||
Indices of keypoints in keypoints2 that have been matched.
|
||||
|
||||
"""
|
||||
@@ -51,33 +51,31 @@ def match_binary_descriptors(keypoints1, descriptors1, keypoints2,
|
||||
|
||||
# Get hamming distances between keypoints1 and keypoints2
|
||||
distance = pairwise_hamming_distance(descriptors1, descriptors2)
|
||||
kp1 = np.squeeze(np.dstack((keypoints1.row, keypoints1.col)))
|
||||
kp2 = np.squeeze(np.dstack((keypoints2.row, keypoints2.col)))
|
||||
|
||||
if cross_check:
|
||||
matched_keypoints1_index = np.argmin(distance, axis=1)
|
||||
matched_keypoints2_index = np.argmin(distance, axis=0)
|
||||
|
||||
matched_index = _binary_cross_check_loop(matched_keypoints1_index,
|
||||
matched_idxs = _binary_cross_check_loop(matched_keypoints1_index,
|
||||
matched_keypoints2_index,
|
||||
distance, threshold)
|
||||
|
||||
matches = np.zeros((matched_index.shape[0], 2, 2),
|
||||
matches = np.zeros((matched_idxs.shape[0], 2, 2),
|
||||
dtype=np.intp)
|
||||
mask1 = matched_index[:, 0]
|
||||
mask2 = matched_index[:, 1]
|
||||
matches[:, 0, :] = kp1[mask1]
|
||||
matches[:, 1, :] = kp2[mask2]
|
||||
idxs1 = matched_idxs[:, 0]
|
||||
idxs2 = matched_idxs[:, 1]
|
||||
matches[:, 0, :] = keypoints1[idxs1]
|
||||
matches[:, 1, :] = keypoints2[idxs2]
|
||||
|
||||
else:
|
||||
temp = distance > threshold
|
||||
row_check = np.any(~temp, axis=1)
|
||||
matched_keypoints2 = kp2[np.argmin(distance, axis=1)]
|
||||
matched_keypoints2 = keypoints2[np.argmin(distance, axis=1)]
|
||||
matches = np.zeros((np.sum(row_check), 2, 2),
|
||||
dtype=np.intp)
|
||||
matches[:, 0, :] = kp1[row_check]
|
||||
matches[:, 0, :] = keypoints1[row_check]
|
||||
matches[:, 1, :] = matched_keypoints2[row_check]
|
||||
mask1 = np.where(row_check == True)[0]
|
||||
mask2 = np.argmin(distance, axis=1)[row_check]
|
||||
idxs1 = np.where(row_check == True)[0]
|
||||
idxs2 = np.argmin(distance, axis=1)[row_check]
|
||||
|
||||
return matches, mask1, mask2
|
||||
|
||||
@@ -3,30 +3,26 @@ from numpy.testing import assert_array_equal, assert_raises
|
||||
from skimage import data
|
||||
from skimage import transform as tf
|
||||
from skimage.color import rgb2gray
|
||||
from skimage.feature import (descriptor_brief, match_binary_descriptors,
|
||||
corner_peaks, corner_harris,
|
||||
create_keypoint_recarray)
|
||||
from skimage.feature import (BRIEF, match_binary_descriptors,
|
||||
corner_peaks, corner_harris)
|
||||
|
||||
|
||||
def test_descriptor_brief_color_image_unsupported_error():
|
||||
"""Brief descriptors can be evaluated on gray-scale images only."""
|
||||
img = np.zeros((20, 20, 3))
|
||||
keypoints_loc = np.asarray([[7, 5], [11, 13]])
|
||||
keypoints = create_keypoint_recarray(keypoints_loc[:, 0],
|
||||
keypoints_loc[:, 1])
|
||||
assert_raises(ValueError, descriptor_brief, img, keypoints)
|
||||
keypoints = np.asarray([[7, 5], [11, 13]])
|
||||
assert_raises(ValueError, BRIEF().extract, img, keypoints)
|
||||
|
||||
|
||||
def test_descriptor_brief_normal_mode():
|
||||
"""Verify the computed BRIEF descriptors with expected for normal mode."""
|
||||
img = data.lena()
|
||||
img = rgb2gray(img)
|
||||
keypoints_loc = corner_peaks(corner_harris(img), min_distance=5)
|
||||
keypoints = create_keypoint_recarray(keypoints_loc[:, 0],
|
||||
keypoints_loc[:, 1])
|
||||
img = rgb2gray(data.lena())
|
||||
|
||||
descriptors, keypoints = descriptor_brief(img, keypoints[:8],
|
||||
descriptor_size=8)
|
||||
keypoints = corner_peaks(corner_harris(img), min_distance=5)
|
||||
|
||||
extractor = BRIEF(descriptor_size=8, sigma=2)
|
||||
|
||||
descriptors, mask = extractor.extract(img, keypoints[:8])
|
||||
|
||||
expected = np.array([[ True, False, True, False, True, True, False, False],
|
||||
[False, False, False, False, True, False, False, False],
|
||||
@@ -42,14 +38,13 @@ def test_descriptor_brief_normal_mode():
|
||||
|
||||
def test_descriptor_brief_uniform_mode():
|
||||
"""Verify the computed BRIEF descriptors with expected for uniform mode."""
|
||||
img = data.lena()
|
||||
img = rgb2gray(img)
|
||||
keypoints_loc = corner_peaks(corner_harris(img), min_distance=5)
|
||||
keypoints = create_keypoint_recarray(keypoints_loc[:, 0],
|
||||
keypoints_loc[:, 1])
|
||||
descriptors, keypoints = descriptor_brief(img, keypoints[:8],
|
||||
descriptor_size=8,
|
||||
mode='uniform')
|
||||
img = rgb2gray(data.lena())
|
||||
|
||||
keypoints = corner_peaks(corner_harris(img), min_distance=5)
|
||||
|
||||
extractor = BRIEF(descriptor_size=8, sigma=2, mode='uniform')
|
||||
|
||||
descriptors, mask = extractor.extract(img, keypoints[:8])
|
||||
|
||||
expected = np.array([[ True, False, True, False, False, True, False, False],
|
||||
[False, True, False, False, True, True, True, True],
|
||||
|
||||
+40
-45
@@ -3,43 +3,40 @@ import numpy as np
|
||||
from skimage.util import img_as_float
|
||||
|
||||
|
||||
def create_keypoint_recarray(rows, cols, scales=None, orientations=None,
|
||||
responses=None):
|
||||
"""Create keypoint array that allows field access through attributes.
|
||||
class FeatureDetector(object):
|
||||
|
||||
Parameters
|
||||
----------
|
||||
rows : (N, ) array
|
||||
Row coordinates of keypoints.
|
||||
cols : (N, ) array
|
||||
Column coordinates of keypoints.
|
||||
scales : (N, ) array
|
||||
Scales in which the keypoints have been detected.
|
||||
orientations : (N, ) array
|
||||
Orientations of the keypoints.
|
||||
responses : (N, ) array
|
||||
Detector response (strength) of the keypoints.
|
||||
def __init__(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
Returns
|
||||
-------
|
||||
recarray : (N, ...) recarray
|
||||
Array with the fields: `row`, `col`, `scale`, `orientation` and
|
||||
`response`.
|
||||
def detect(self, image):
|
||||
"""Detect keypoints in image.
|
||||
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
image : 2D array
|
||||
Input image.
|
||||
|
||||
dtype = [('row', np.double),
|
||||
('col', np.double),
|
||||
('scale', np.double),
|
||||
('orientation', np.double),
|
||||
('response', np.double)]
|
||||
keypoints = np.zeros(rows.shape[0], dtype=dtype)
|
||||
keypoints['row'] = rows
|
||||
keypoints['col'] = cols
|
||||
keypoints['scale'] = scales
|
||||
keypoints['orientation'] = orientations
|
||||
keypoints['response'] = responses
|
||||
return keypoints.view(np.recarray)
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class DescriptorExtractor(object):
|
||||
|
||||
def __init__(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def extract(self, image, keypoints):
|
||||
"""Extract feature descriptors in image for given keypoints.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : 2D array
|
||||
Input image.
|
||||
keypoints : (N, 2) array
|
||||
Keypoint locations as ``(row, col)``.
|
||||
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def _prepare_grayscale_input_2D(image):
|
||||
@@ -50,17 +47,15 @@ def _prepare_grayscale_input_2D(image):
|
||||
return img_as_float(image)
|
||||
|
||||
|
||||
def _mask_border_keypoints(shape, rr, cc, distance):
|
||||
def _mask_border_keypoints(image_shape, keypoints, distance):
|
||||
"""Mask coordinates that are within certain distance from the image border.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
shape : (2, ) array_like
|
||||
image_shape : (2, ) array_like
|
||||
Shape of the image as ``(rows, cols)``.
|
||||
rr : (N, ) array
|
||||
Row coordinates.
|
||||
cc : (N, ) array
|
||||
Column coordinates.
|
||||
coords : (N, 2) array
|
||||
Keypoint coordinates as ``(rows, cols)``.
|
||||
distance : int
|
||||
Image border distance.
|
||||
|
||||
@@ -72,13 +67,13 @@ def _mask_border_keypoints(shape, rr, cc, distance):
|
||||
|
||||
"""
|
||||
|
||||
rows = shape[0]
|
||||
cols = shape[1]
|
||||
rows = image_shape[0]
|
||||
cols = image_shape[1]
|
||||
|
||||
mask = (((distance - 1) < rr)
|
||||
& (rr < (rows - distance + 1))
|
||||
& ((distance - 1) < cc)
|
||||
& (cc < (cols - distance + 1)))
|
||||
mask = (((distance - 1) < keypoints[:, 0])
|
||||
& (keypoints[:, 0] < (rows - distance + 1))
|
||||
& ((distance - 1) < keypoints[:, 1])
|
||||
& (keypoints[:, 1] < (cols - distance + 1)))
|
||||
|
||||
return mask
|
||||
|
||||
|
||||
Reference in New Issue
Block a user