mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-13 02:20:51 +08:00
Implement CenSurE detector in object oriented interface
This commit is contained in:
@@ -9,10 +9,10 @@ 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 BRIEF
|
||||
from .brief import BRIEF
|
||||
from .censure import CenSurE
|
||||
from .match import match_binary_descriptors
|
||||
from .util import pairwise_hamming_distance
|
||||
from .censure import keypoints_censure
|
||||
from .orb import keypoints_orb, descriptor_orb
|
||||
|
||||
__all__ = ['daisy',
|
||||
@@ -30,9 +30,9 @@ __all__ = ['daisy',
|
||||
'corner_moravec',
|
||||
'match_template',
|
||||
'BRIEF',
|
||||
'CenSurE',
|
||||
'pairwise_hamming_distance',
|
||||
'match_binary_descriptors',
|
||||
'keypoints_censure',
|
||||
'corner_fast',
|
||||
'corner_orientations',
|
||||
'structure_tensor',
|
||||
|
||||
@@ -101,6 +101,7 @@ class BRIEF(DescriptorExtractor):
|
||||
def __init__(self, descriptor_size=256, patch_size=49,
|
||||
mode='normal', sigma=1, sample_seed=1):
|
||||
|
||||
mode = mode.lower()
|
||||
if mode not in ('normal', 'uniform'):
|
||||
raise ValueError("`mode` must be 'normal' or 'uniform'.")
|
||||
|
||||
+95
-76
@@ -1,7 +1,7 @@
|
||||
import numpy as np
|
||||
from scipy.ndimage.filters import maximum_filter, minimum_filter, convolve
|
||||
|
||||
from .util import _prepare_grayscale_input_2D
|
||||
from skimage.feature.util import FeatureDetector, _prepare_grayscale_input_2D
|
||||
|
||||
from skimage.transform import integral_image
|
||||
from skimage.feature import structure_tensor
|
||||
@@ -66,19 +66,19 @@ def _filter_image(image, min_scale, max_scale, mode):
|
||||
mo, no = OCTAGON_OUTER_SHAPE[min_scale + i - 1]
|
||||
mi, ni = OCTAGON_INNER_SHAPE[min_scale + i - 1]
|
||||
response[:, :, i] = convolve(image,
|
||||
_octagon_filter_kernel(mo, no, mi, ni))
|
||||
_octagon_kernel(mo, no, mi, ni))
|
||||
|
||||
elif mode == 'star':
|
||||
|
||||
for i in range(max_scale - min_scale + 1):
|
||||
m = STAR_SHAPE[STAR_FILTER_SHAPE[min_scale + i - 1][0]]
|
||||
n = STAR_SHAPE[STAR_FILTER_SHAPE[min_scale + i - 1][1]]
|
||||
response[:, :, i] = convolve(image, _star_filter_kernel(m, n))
|
||||
response[:, :, i] = convolve(image, _star_kernel(m, n))
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def _octagon_filter_kernel(mo, no, mi, ni):
|
||||
def _octagon_kernel(mo, no, mi, ni):
|
||||
outer = (mo + 2 * no)**2 - 2 * no * (no + 1)
|
||||
inner = (mi + 2 * ni)**2 - 2 * ni * (ni + 1)
|
||||
outer_weight = 1.0 / (outer - inner)
|
||||
@@ -92,7 +92,7 @@ def _octagon_filter_kernel(mo, no, mi, ni):
|
||||
return bfilter
|
||||
|
||||
|
||||
def _star_filter_kernel(m, n):
|
||||
def _star_kernel(m, n):
|
||||
c = m + m // 2 - n - n // 2
|
||||
outer_star = star(m)
|
||||
inner_star = np.zeros_like(outer_star)
|
||||
@@ -106,21 +106,15 @@ def _star_filter_kernel(m, n):
|
||||
|
||||
def _suppress_lines(feature_mask, image, sigma, line_threshold):
|
||||
Axx, Axy, Ayy = structure_tensor(image, sigma)
|
||||
feature_mask[(Axx + Ayy) * (Axx + Ayy)
|
||||
> line_threshold * (Axx * Ayy - Axy * Axy)] = False
|
||||
feature_mask[(Axx + Ayy) ** 2
|
||||
> line_threshold * (Axx * Ayy - Axy ** 2)] = False
|
||||
|
||||
|
||||
def keypoints_censure(image, min_scale=1, max_scale=7, mode='DoB',
|
||||
non_max_threshold=0.15, line_threshold=10):
|
||||
"""**Experimental function**.
|
||||
|
||||
Extracts CenSurE keypoints along with the corresponding scale using
|
||||
either Difference of Boxes, Octagon or STAR bi-level filter.
|
||||
class CenSurE(FeatureDetector):
|
||||
|
||||
"""CenSurE keypoint detector.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : 2D ndarray
|
||||
Input image.
|
||||
min_scale : int
|
||||
Minimum scale to extract keypoints from.
|
||||
max_scale : int
|
||||
@@ -145,13 +139,6 @@ def keypoints_censure(image, min_scale=1, max_scale=7, mode='DoB',
|
||||
Threshold for rejecting interest points which have ratio of principal
|
||||
curvatures greater than this value.
|
||||
|
||||
Returns
|
||||
-------
|
||||
keypoints : (N, 2) array
|
||||
Location of the extracted keypoints in the ``(row, col)`` format.
|
||||
scales : (N, 1) array
|
||||
The corresponding scale of the N extracted keypoints.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] Motilal Agrawal, Kurt Konolige and Morten Rufus Blas
|
||||
@@ -166,69 +153,101 @@ def keypoints_censure(image, min_scale=1, max_scale=7, mode='DoB',
|
||||
|
||||
"""
|
||||
|
||||
# (1) First we generate the required scales on the input grayscale image
|
||||
# using a bi-level filter and stack them up in `filter_response`.
|
||||
# (2) We then perform Non-Maximal suppression in 3 x 3 x 3 window on the
|
||||
# filter_response to suppress points that are neither minima or maxima in
|
||||
# 3 x 3 x 3 neighbourhood. We obtain a boolean ndarray `feature_mask`
|
||||
# containing all the minimas and maximas in `filter_response` as True.
|
||||
# (3) Then we suppress all the points in the `feature_mask` for which the
|
||||
# corresponding point in the image at a particular scale has the ratio of
|
||||
# principal curvatures greater than `line_threshold`.
|
||||
# (4) Finally, we remove the border keypoints and return the keypoints
|
||||
# along with its corresponding scale.
|
||||
def __init__(self, min_scale=1, max_scale=7, mode='DoB',
|
||||
non_max_threshold=0.15, line_threshold=10):
|
||||
|
||||
image = _prepare_grayscale_input_2D(image)
|
||||
mode = mode.lower()
|
||||
if mode not in ('dob', 'octagon', 'star'):
|
||||
raise ValueError("`mode` must be one of 'DoB', 'Octagon', 'STAR'.")
|
||||
|
||||
mode = mode.lower()
|
||||
if mode not in ('dob', 'octagon', 'star'):
|
||||
raise ValueError('Mode must be one of "DoB", "Octagon", "STAR".')
|
||||
if min_scale < 1 or max_scale < 1 or max_scale - min_scale < 2:
|
||||
raise ValueError('The scales must be >= 1 and the number of '
|
||||
'scales should be >= 3.')
|
||||
|
||||
if min_scale < 1 or max_scale < 1 or max_scale - min_scale < 2:
|
||||
raise ValueError('The scales must be >= 1 and the number of scales '
|
||||
'should be >= 3.')
|
||||
self.min_scale = min_scale
|
||||
self.max_scale = max_scale
|
||||
self.mode = mode
|
||||
self.non_max_threshold = non_max_threshold
|
||||
self.line_threshold = line_threshold
|
||||
|
||||
image = np.ascontiguousarray(image)
|
||||
def detect(self, image):
|
||||
"""Detect CenSurE keypoints along with the corresponding scale.
|
||||
|
||||
# Generating all the scales
|
||||
filter_response = _filter_image(image, min_scale, max_scale, mode)
|
||||
Parameters
|
||||
----------
|
||||
image : 2D ndarray
|
||||
Input image.
|
||||
|
||||
# Suppressing points that are neither minima or maxima in their 3 x 3 x 3
|
||||
# neighbourhood to zero
|
||||
minimas = minimum_filter(filter_response, (3, 3, 3)) == filter_response
|
||||
maximas = maximum_filter(filter_response, (3, 3, 3)) == filter_response
|
||||
Returns
|
||||
-------
|
||||
keypoints : (N, 2) array
|
||||
Keypoint coordinates as ``(row, col)``.
|
||||
scales : (N, 1) array
|
||||
Corresponding scales of the N extracted keypoints.
|
||||
|
||||
feature_mask = minimas | maximas
|
||||
feature_mask[filter_response < non_max_threshold] = False
|
||||
"""
|
||||
|
||||
for i in range(1, max_scale - min_scale):
|
||||
# sigma = (window_size - 1) / 6.0, so the window covers > 99% of the
|
||||
# kernel's distribution
|
||||
# window_size = 7 + 2 * (min_scale - 1 + i)
|
||||
# Hence sigma = 1 + (min_scale - 1 + i)/ 3.0
|
||||
_suppress_lines(feature_mask[:, :, i], image,
|
||||
(1 + (min_scale + i - 1) / 3.0), line_threshold)
|
||||
# (1) First we generate the required scales on the input grayscale
|
||||
# image using a bi-level filter and stack them up in `filter_response`.
|
||||
|
||||
rows, cols, scales = np.nonzero(feature_mask[..., 1:max_scale - min_scale])
|
||||
keypoints = np.column_stack([rows, cols])
|
||||
scales = scales + min_scale + 1
|
||||
# (2) We then perform Non-Maximal suppression in 3 x 3 x 3 window on
|
||||
# the filter_response to suppress points that are neither minima or
|
||||
# maxima in 3 x 3 x 3 neighbourhood. We obtain a boolean ndarray
|
||||
# `feature_mask` containing all the minimas and maximas in
|
||||
# `filter_response` as True.
|
||||
# (3) Then we suppress all the points in the `feature_mask` for which
|
||||
# the corresponding point in the image at a particular scale has the
|
||||
# ratio of principal curvatures greater than `line_threshold`.
|
||||
# (4) Finally, we remove the border keypoints and return the keypoints
|
||||
# along with its corresponding scale.
|
||||
|
||||
if mode == 'dob':
|
||||
return keypoints, scales
|
||||
num_scales = self.max_scale - self.min_scale
|
||||
|
||||
cumulative_mask = np.zeros(keypoints.shape[0], dtype=np.bool)
|
||||
image = np.ascontiguousarray(_prepare_grayscale_input_2D(image))
|
||||
|
||||
if mode == 'octagon':
|
||||
for i in range(min_scale + 1, max_scale):
|
||||
c = (OCTAGON_OUTER_SHAPE[i - 1][0] - 1) // 2 \
|
||||
+ OCTAGON_OUTER_SHAPE[i - 1][1]
|
||||
cumulative_mask |= _mask_border_keypoints(image, keypoints, c) \
|
||||
& (scales == i)
|
||||
elif mode == 'star':
|
||||
for i in range(min_scale + 1, max_scale):
|
||||
c = STAR_SHAPE[STAR_FILTER_SHAPE[i - 1][0]] \
|
||||
+ STAR_SHAPE[STAR_FILTER_SHAPE[i - 1][0]] // 2
|
||||
cumulative_mask |= _mask_border_keypoints(image, keypoints, c) \
|
||||
& (scales == i)
|
||||
# Generating all the scales
|
||||
filter_response = _filter_image(image, self.min_scale, self.max_scale,
|
||||
self.mode)
|
||||
|
||||
return keypoints[cumulative_mask], scales[cumulative_mask]
|
||||
# Suppressing points that are neither minima or maxima in their
|
||||
# 3 x 3 x 3 neighborhood to zero
|
||||
minimas = minimum_filter(filter_response, (3, 3, 3)) == filter_response
|
||||
maximas = maximum_filter(filter_response, (3, 3, 3)) == filter_response
|
||||
|
||||
feature_mask = minimas | maximas
|
||||
feature_mask[filter_response < self.non_max_threshold] = False
|
||||
|
||||
for i in range(1, num_scales):
|
||||
# sigma = (window_size - 1) / 6.0, so the window covers > 99% of
|
||||
# the kernel's distribution
|
||||
# window_size = 7 + 2 * (min_scale - 1 + i)
|
||||
# Hence sigma = 1 + (min_scale - 1 + i)/ 3.0
|
||||
_suppress_lines(feature_mask[:, :, i], image,
|
||||
(1 + (self.min_scale + i - 1) / 3.0),
|
||||
self.line_threshold)
|
||||
|
||||
rows, cols, scales = np.nonzero(feature_mask[..., 1:num_scales])
|
||||
keypoints = np.column_stack([rows, cols])
|
||||
scales = scales + self.min_scale + 1
|
||||
|
||||
if self.mode == 'dob':
|
||||
return keypoints, scales
|
||||
|
||||
cumulative_mask = np.zeros(keypoints.shape[0], dtype=np.bool)
|
||||
|
||||
if self.mode == 'octagon':
|
||||
for i in range(self.min_scale + 1, self.max_scale):
|
||||
c = (OCTAGON_OUTER_SHAPE[i - 1][0] - 1) // 2 \
|
||||
+ OCTAGON_OUTER_SHAPE[i - 1][1]
|
||||
cumulative_mask |= (
|
||||
_mask_border_keypoints(image.shape, keypoints, c)
|
||||
& (scales == i))
|
||||
elif self.mode == 'star':
|
||||
for i in range(self.min_scale + 1, self.max_scale):
|
||||
c = STAR_SHAPE[STAR_FILTER_SHAPE[i - 1][0]] \
|
||||
+ STAR_SHAPE[STAR_FILTER_SHAPE[i - 1][0]] // 2
|
||||
cumulative_mask |= (
|
||||
_mask_border_keypoints(image.shape, keypoints, c)
|
||||
& (scales == i))
|
||||
|
||||
return keypoints[cumulative_mask], scales[cumulative_mask]
|
||||
|
||||
+41
-30
@@ -1,8 +1,7 @@
|
||||
import numpy as np
|
||||
|
||||
from skimage.feature.util import (_mask_border_keypoints,
|
||||
_prepare_grayscale_input_2D,
|
||||
create_keypoint_recarray)
|
||||
_prepare_grayscale_input_2D)
|
||||
|
||||
from skimage.feature import (corner_fast, corner_orientations, corner_peaks,
|
||||
corner_harris)
|
||||
@@ -12,36 +11,39 @@ from .orb_cy import _orb_loop
|
||||
|
||||
|
||||
OFAST_MASK = np.zeros((31, 31))
|
||||
umax = [15, 15, 15, 15, 14, 14, 14, 13, 13, 12, 11, 10, 9, 8, 6, 3]
|
||||
OFAST_UMAX = [15, 15, 15, 15, 14, 14, 14, 13, 13, 12, 11, 10, 9, 8, 6, 3]
|
||||
for i in range(-15, 16):
|
||||
for j in range(-umax[np.abs(i)], umax[np.abs(i)] + 1):
|
||||
for j in range(-OFAST_UMAX[abs(i)], OFAST_UMAX[abs(i)] + 1):
|
||||
OFAST_MASK[15 + j, 15 + i] = 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def keypoints_orb(image, n_keypoints=500, fast_n=9, fast_threshold=0.08,
|
||||
harris_k=0.04, downscale=1.2, n_scales=8):
|
||||
|
||||
"""Detect Oriented Fast keypoints.
|
||||
"""Detect oriented FAST keypoints.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : 2D ndarray
|
||||
Input grayscale image.
|
||||
Input image.
|
||||
n_keypoints : int
|
||||
Number of keypoints to be returned from this function. The function
|
||||
will return best ``n_keypoints`` if more than n_keypoints are detected
|
||||
based on the values of other parameters. If not, then all the detected
|
||||
keypoints are returned.
|
||||
Number of keypoints to be returned. The function will return the best
|
||||
``n_keypoints`` according to the Harris corner response if more than
|
||||
``n_keypoints`` are detected. If not, then all the detected keypoints
|
||||
are returned.
|
||||
fast_n : int
|
||||
The ``n`` parameter in ``feature.corner_fast``. Minimum number of
|
||||
consecutive pixels out of 16 pixels on the circle that should all be
|
||||
either brighter or darker w.r.t testpixel. A point c on the circle is
|
||||
either brighter or darker w.r.t test-pixel. A point c on the circle is
|
||||
darker w.r.t test pixel p if ``Ic < Ip - threshold`` and brighter if
|
||||
``Ic > Ip + threshold``. Also stands for the n in ``FAST-n`` corner
|
||||
detector.
|
||||
fast_threshold : float
|
||||
The ``threshold`` parameter in ``feature.corner_fast``. Threshold used to
|
||||
decide whether the pixels on the circle are brighter, darker or
|
||||
The ``threshold`` parameter in ``feature.corner_fast``. Threshold used
|
||||
to decide whether the pixels on the circle are brighter, darker or
|
||||
similar w.r.t. the test pixel. Decrease the threshold when more
|
||||
corners are desired and vice-versa.
|
||||
harris_k : float
|
||||
@@ -50,15 +52,17 @@ def keypoints_orb(image, n_keypoints=500, fast_n=9, fast_threshold=0.08,
|
||||
values of k result in detection of sharp corners.
|
||||
downscale : float
|
||||
Downscale factor for the image pyramid. Default value 1.2 is chosen so
|
||||
that we have more dense scales that enable robust scale invariance.
|
||||
that there are more dense scales which enable robust scale invariance
|
||||
for a subsequent feature description.
|
||||
n_scales : int
|
||||
Number of scales from the bottom of the image pyramid to extract
|
||||
the features from.
|
||||
Maximum number of scales from the bottom of the image pyramid to
|
||||
extract the features from.
|
||||
|
||||
Returns
|
||||
-------
|
||||
keypoints : record array
|
||||
Record array with fields row, col, octave, orientation, response.
|
||||
keypoints : (N, ...) recarray
|
||||
Record array as returned by `skimage.feature.create_keypoint_recarray`
|
||||
with the fields: `row`, `col`, `scale`, `orientation` and `response`.
|
||||
|
||||
References
|
||||
----------
|
||||
@@ -97,46 +101,53 @@ def keypoints_orb(image, n_keypoints=500, fast_n=9, fast_threshold=0.08,
|
||||
scales_list = []
|
||||
harris_response_list = []
|
||||
|
||||
for scale in range(n_scales):
|
||||
for octave in range(len(pyramid)):
|
||||
|
||||
corners = corner_peaks(corner_fast(pyramid[scale], fast_n,
|
||||
# Extract keypoints for current octave
|
||||
corners = corner_peaks(corner_fast(pyramid[octave], fast_n,
|
||||
fast_threshold), min_distance=1)
|
||||
keypoints_list.append(corners * downscale ** scale)
|
||||
|
||||
orientations_list.append(corner_orientations(pyramid[scale], corners,
|
||||
# Scale keypoint coordinates so they correspond to the original
|
||||
# image shape
|
||||
keypoints_list.append(corners * downscale ** octave)
|
||||
|
||||
orientations_list.append(corner_orientations(pyramid[octave], corners,
|
||||
OFAST_MASK))
|
||||
|
||||
scales_list.append(scale * np.ones(corners.shape[0], dtype=np.intp))
|
||||
scales_list.append(octave * np.ones(corners.shape[0], dtype=np.intp))
|
||||
|
||||
harris_response = corner_harris(pyramid[scale], method='k', k=harris_k)
|
||||
harris_response = corner_harris(pyramid[octave], method='k',
|
||||
k=harris_k)
|
||||
harris_response_list.append(harris_response[corners[:, 0],
|
||||
corners[:, 1]])
|
||||
|
||||
keypoints_array = np.vstack(keypoints_list)
|
||||
orientations = np.hstack(orientations_list)
|
||||
octaves = downscale ** np.hstack(scales_list)
|
||||
scales = downscale ** np.hstack(scales_list)
|
||||
harris_measure = np.hstack(harris_response_list)
|
||||
keypoints = create_keypoint_recarray(keypoints_array[:, 0],
|
||||
keypoints_array[:, 1],
|
||||
octaves, orientations,
|
||||
scales, orientations,
|
||||
harris_measure)
|
||||
|
||||
if keypoints.shape[0] < n_keypoints:
|
||||
return keypoints
|
||||
else:
|
||||
# Choose best n_keypoints according to Harris corner response
|
||||
best_indices = harris_measure.argsort()[::-1][:n_keypoints]
|
||||
return keypoints[best_indices]
|
||||
|
||||
|
||||
def descriptor_orb(image, keypoints, downscale=1.2, n_scales=8):
|
||||
"""Compute rBRIEF descriptors of input keypoints.
|
||||
"""Compute rBRIEF descriptors for keypoints.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : 2D ndarray
|
||||
Input grayscale image.
|
||||
keypoints : record array
|
||||
Record array with fields row, col, octave, orientation, response.
|
||||
Input image.
|
||||
keypoints : (N, ...) recarray
|
||||
Record array as returned by `skimage.feature.create_keypoint_recarray`
|
||||
with the fields: `row`, `col`, `scale`, `orientation` and `response`.
|
||||
downscale : float
|
||||
Downscale factor for the image pyramid. Should be the same as that
|
||||
used in ``keypoints_orb``.
|
||||
|
||||
@@ -15,7 +15,7 @@ def configuration(parent_package='', top_path=None):
|
||||
cython(['corner_cy.pyx'], working_path=base_path)
|
||||
cython(['censure_cy.pyx'], working_path=base_path)
|
||||
cython(['orb_cy.pyx'], working_path=base_path)
|
||||
cython(['_brief_cy.pyx'], working_path=base_path)
|
||||
cython(['brief_cy.pyx'], working_path=base_path)
|
||||
cython(['match_cy.pyx'], working_path=base_path)
|
||||
cython(['_texture.pyx'], working_path=base_path)
|
||||
cython(['_template.pyx'], working_path=base_path)
|
||||
@@ -26,7 +26,7 @@ def configuration(parent_package='', top_path=None):
|
||||
include_dirs=[get_numpy_include_dirs()])
|
||||
config.add_extension('orb_cy', sources=['orb_cy.c'],
|
||||
include_dirs=[get_numpy_include_dirs()])
|
||||
config.add_extension('_brief_cy', sources=['_brief_cy.c'],
|
||||
config.add_extension('brief_cy', sources=['brief_cy.c'],
|
||||
include_dirs=[get_numpy_include_dirs()])
|
||||
config.add_extension('match_cy', sources=['match_cy.c'],
|
||||
include_dirs=[get_numpy_include_dirs()])
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
import numpy as np
|
||||
from numpy.testing import assert_array_equal, assert_raises
|
||||
from skimage.data import moon
|
||||
from skimage.feature import keypoints_censure
|
||||
|
||||
|
||||
def test_keypoints_censure_color_image_unsupported_error():
|
||||
"""Censure keypoints can be extracted from gray-scale images only."""
|
||||
img = np.zeros((20, 20, 3))
|
||||
assert_raises(ValueError, keypoints_censure, img)
|
||||
|
||||
|
||||
def test_keypoints_censure_mode_validity_error():
|
||||
"""Mode argument in keypoints_censure can be either DoB, Octagon or
|
||||
STAR."""
|
||||
img = np.zeros((20, 20))
|
||||
assert_raises(ValueError, keypoints_censure, img, mode='dummy')
|
||||
|
||||
|
||||
def test_keypoints_censure_scale_range_error():
|
||||
"""Difference between the the max_scale and min_scale parameters in
|
||||
keypoints_censure should be greater than or equal to two."""
|
||||
img = np.zeros((20, 20))
|
||||
assert_raises(ValueError, keypoints_censure, img, min_scale=1, max_scale=2)
|
||||
|
||||
|
||||
def test_keypoints_censure_moon_image_dob():
|
||||
"""Verify the actual Censure keypoints and their corresponding scale with
|
||||
the expected values for DoB filter."""
|
||||
img = moon()
|
||||
actual_kp_dob, actual_scale = keypoints_censure(img, 1, 7, 'DoB', 0.15)
|
||||
expected_kp_dob = np.array([[ 21, 497],
|
||||
[ 36, 46],
|
||||
[119, 350],
|
||||
[185, 177],
|
||||
[287, 250],
|
||||
[357, 239],
|
||||
[463, 116],
|
||||
[464, 132],
|
||||
[467, 260]])
|
||||
expected_scale = np.array([3, 4, 4, 2, 2, 3, 2, 2, 2])
|
||||
|
||||
assert_array_equal(expected_kp_dob, actual_kp_dob)
|
||||
assert_array_equal(expected_scale, actual_scale)
|
||||
|
||||
|
||||
def test_keypoints_censure_moon_image_octagon():
|
||||
"""Verify the actual Censure keypoints and their corresponding scale with
|
||||
the expected values for Octagon filter."""
|
||||
img = moon()
|
||||
actual_kp_octagon, actual_scale = keypoints_censure(img, 1, 7, 'Octagon',
|
||||
0.15)
|
||||
expected_kp_octagon = np.array([[ 21, 496],
|
||||
[ 35, 46],
|
||||
[287, 250],
|
||||
[356, 239],
|
||||
[463, 116]])
|
||||
|
||||
expected_scale = np.array([3, 4, 2, 2, 2])
|
||||
|
||||
assert_array_equal(expected_kp_octagon, actual_kp_octagon)
|
||||
assert_array_equal(expected_scale, actual_scale)
|
||||
|
||||
|
||||
def test_keypoints_censure_moon_image_star():
|
||||
"""Verify the actual Censure keypoints and their corresponding scale with
|
||||
the expected values for STAR filter."""
|
||||
img = moon()
|
||||
actual_kp_star, actual_scale = keypoints_censure(img, 1, 7, 'STAR', 0.15)
|
||||
expected_kp_star = np.array([[ 21, 497],
|
||||
[ 36, 46],
|
||||
[117, 356],
|
||||
[185, 177],
|
||||
[260, 227],
|
||||
[287, 250],
|
||||
[357, 239],
|
||||
[451, 281],
|
||||
[463, 116],
|
||||
[467, 260]])
|
||||
|
||||
expected_scale = np.array([3, 3, 6, 2, 3, 2, 3, 5, 2, 2])
|
||||
|
||||
assert_array_equal(expected_kp_star, actual_kp_star)
|
||||
assert_array_equal(expected_scale, actual_scale)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy import testing
|
||||
testing.run_module_suite()
|
||||
@@ -0,0 +1,89 @@
|
||||
import numpy as np
|
||||
from numpy.testing import assert_array_equal, assert_raises
|
||||
from skimage.data import moon
|
||||
from skimage.feature import CenSurE
|
||||
|
||||
|
||||
img = moon()
|
||||
|
||||
|
||||
def test_keypoints_censure_color_image_unsupported_error():
|
||||
"""Censure keypoints can be extracted from gray-scale images only."""
|
||||
assert_raises(ValueError, CenSurE().detect, np.zeros((20, 20, 3)))
|
||||
|
||||
|
||||
def test_keypoints_censure_mode_validity_error():
|
||||
"""Mode argument in keypoints_censure can be either DoB, Octagon or
|
||||
STAR."""
|
||||
assert_raises(ValueError, CenSurE, mode='dummy')
|
||||
|
||||
|
||||
def test_keypoints_censure_scale_range_error():
|
||||
"""Difference between the the max_scale and min_scale parameters in
|
||||
keypoints_censure should be greater than or equal to two."""
|
||||
assert_raises(ValueError, CenSurE, min_scale=1, max_scale=2)
|
||||
|
||||
|
||||
def test_keypoints_censure_moon_image_dob():
|
||||
"""Verify the actual Censure keypoints and their corresponding scale with
|
||||
the expected values for DoB filter."""
|
||||
detector = CenSurE()
|
||||
keypoints, scales = detector.detect(img)
|
||||
expected_keypoints = np.array([[ 21, 497],
|
||||
[ 36, 46],
|
||||
[119, 350],
|
||||
[185, 177],
|
||||
[287, 250],
|
||||
[357, 239],
|
||||
[463, 116],
|
||||
[464, 132],
|
||||
[467, 260]])
|
||||
expected_scales = np.array([3, 4, 4, 2, 2, 3, 2, 2, 2])
|
||||
|
||||
assert_array_equal(expected_keypoints, keypoints)
|
||||
assert_array_equal(expected_scales, scales)
|
||||
|
||||
|
||||
def test_keypoints_censure_moon_image_octagon():
|
||||
"""Verify the actual Censure keypoints and their corresponding scale with
|
||||
the expected values for Octagon filter."""
|
||||
|
||||
detector = CenSurE(mode='octagon')
|
||||
keypoints, scales = detector.detect(img)
|
||||
expected_keypoints = np.array([[ 21, 496],
|
||||
[ 35, 46],
|
||||
[287, 250],
|
||||
[356, 239],
|
||||
[463, 116]])
|
||||
|
||||
expected_scales = np.array([3, 4, 2, 2, 2])
|
||||
|
||||
assert_array_equal(expected_keypoints, keypoints)
|
||||
assert_array_equal(expected_scales, scales)
|
||||
|
||||
|
||||
def test_keypoints_censure_moon_image_star():
|
||||
"""Verify the actual Censure keypoints and their corresponding scale with
|
||||
the expected values for STAR filter."""
|
||||
detector = CenSurE(mode='star')
|
||||
keypoints, scales = detector.detect(img)
|
||||
expected_keypoints = np.array([[ 21, 497],
|
||||
[ 36, 46],
|
||||
[117, 356],
|
||||
[185, 177],
|
||||
[260, 227],
|
||||
[287, 250],
|
||||
[357, 239],
|
||||
[451, 281],
|
||||
[463, 116],
|
||||
[467, 260]])
|
||||
|
||||
expected_scale = np.array([3, 3, 6, 2, 3, 2, 3, 5, 2, 2])
|
||||
|
||||
assert_array_equal(expected_keypoints, keypoints)
|
||||
assert_array_equal(expected_scale, scales)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy import testing
|
||||
testing.run_module_suite()
|
||||
Reference in New Issue
Block a user