mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-30 12:31:08 +08:00
Refactor ORB
This commit is contained in:
+10
-10
@@ -11,9 +11,10 @@ from .corner_cy import corner_moravec, corner_orientations
|
||||
from .template import match_template
|
||||
from .brief import BRIEF
|
||||
from .censure import CenSurE
|
||||
from .orb import ORB
|
||||
from .match import match_binary_descriptors
|
||||
from .util import pairwise_hamming_distance
|
||||
from .orb import keypoints_orb, descriptor_orb
|
||||
|
||||
|
||||
__all__ = ['daisy',
|
||||
'hog',
|
||||
@@ -21,6 +22,10 @@ __all__ = ['daisy',
|
||||
'greycoprops',
|
||||
'local_binary_pattern',
|
||||
'peak_local_max',
|
||||
'structure_tensor',
|
||||
'structure_tensor_eigvals',
|
||||
'hessian_matrix',
|
||||
'hessian_matrix_eigvals',
|
||||
'corner_kitchen_rosenfeld',
|
||||
'corner_harris',
|
||||
'corner_shi_tomasi',
|
||||
@@ -28,16 +33,11 @@ __all__ = ['daisy',
|
||||
'corner_subpix',
|
||||
'corner_peaks',
|
||||
'corner_moravec',
|
||||
'corner_fast',
|
||||
'corner_orientations',
|
||||
'match_template',
|
||||
'BRIEF',
|
||||
'CenSurE',
|
||||
'ORB',
|
||||
'pairwise_hamming_distance',
|
||||
'match_binary_descriptors',
|
||||
'corner_fast',
|
||||
'corner_orientations',
|
||||
'structure_tensor',
|
||||
'structure_tensor_eigvals',
|
||||
'hessian_matrix',
|
||||
'hessian_matrix_eigvals',
|
||||
'keypoints_orb',
|
||||
'descriptor_orb']
|
||||
'match_binary_descriptors']
|
||||
|
||||
@@ -182,8 +182,8 @@ class CenSurE(FeatureDetector):
|
||||
-------
|
||||
keypoints : (N, 2) array
|
||||
Keypoint coordinates as ``(row, col)``.
|
||||
scales : (N, 1) array
|
||||
Corresponding scales of the N extracted keypoints.
|
||||
scales : (N, ) array
|
||||
Corresponding scales.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
+194
-140
@@ -1,6 +1,7 @@
|
||||
import numpy as np
|
||||
|
||||
from skimage.feature.util import (_mask_border_keypoints,
|
||||
from skimage.feature.util import (FeatureDetector, DescriptorExtractor,
|
||||
_mask_border_keypoints,
|
||||
_prepare_grayscale_input_2D)
|
||||
|
||||
from skimage.feature import (corner_fast, corner_orientations, corner_peaks,
|
||||
@@ -17,18 +18,13 @@ for i in range(-15, 16):
|
||||
OFAST_MASK[15 + j, 15 + i] = 1
|
||||
|
||||
|
||||
class ORB(FeatureDetector, DescriptorExtractor):
|
||||
|
||||
|
||||
|
||||
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.
|
||||
"""Oriented FAST and rotated BRIEF feature detector and binary descriptor
|
||||
extractor.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : 2D ndarray
|
||||
Input image.
|
||||
n_keypoints : int
|
||||
Number of keypoints to be returned. The function will return the best
|
||||
``n_keypoints`` according to the Harris corner response if more than
|
||||
@@ -58,165 +54,223 @@ def keypoints_orb(image, n_keypoints=500, fast_n=9, fast_threshold=0.08,
|
||||
Maximum number of scales from the bottom of the image pyramid to
|
||||
extract the features from.
|
||||
|
||||
Returns
|
||||
-------
|
||||
keypoints : (N, ...) recarray
|
||||
Record array as returned by `skimage.feature.create_keypoint_recarray`
|
||||
with the fields: `row`, `col`, `scale`, `orientation` and `response`.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] Ethan Rublee, Vincent Rabaud, Kurt Konolige and Gary Bradski
|
||||
"ORB : An efficient alternative to SIFT and SURF"
|
||||
"ORB: An efficient alternative to SIFT and SURF"
|
||||
http://www.vision.cs.chubu.ac.jp/CV-R/pdf/Rublee_iccv2011.pdf
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from skimage.feature import keypoints_orb, descriptor_orb
|
||||
>>> square = np.zeros((50, 50))
|
||||
>>> square[20:30, 20:30] = 1
|
||||
>>> keypoints = keypoints_orb(square, n_keypoints=8, n_scales=2)
|
||||
>>> keypoints.shape
|
||||
(8,)
|
||||
>>> keypoints.row
|
||||
array([ 29. , 29. , 20. , 20. , 20.4, 20.4, 28.8, 28.8])
|
||||
>>> keypoints.col
|
||||
array([ 29. , 20. , 29. , 20. , 28.8, 20.4, 28.8, 20.4])
|
||||
>>> keypoints.octave
|
||||
array([ 1. , 1. , 1. , 1. , 1.2, 1.2, 1.2, 1.2])
|
||||
>>> np.rad2deg(keypoints.orientation)
|
||||
array([-135., -45., 135., 45., 135., 45., -135., -45.])
|
||||
>>> keypoints.response
|
||||
array([ 21.4776577 , 21.4776577 , 21.4776577 , 21.4776577 ,
|
||||
14.03845308, 14.03845308, 14.03845308, 14.03845308])
|
||||
|
||||
"""
|
||||
|
||||
image = _prepare_grayscale_input_2D(image)
|
||||
def __init__(self, downscale=1.2, n_scales=8,
|
||||
n_keypoints=500, fast_n=9, fast_threshold=0.08,
|
||||
harris_k=0.04):
|
||||
self.downscale = downscale
|
||||
self.n_scales = n_scales
|
||||
self.n_keypoints = n_keypoints
|
||||
self.fast_n = fast_n
|
||||
self.fast_threshold = fast_threshold
|
||||
self.harris_k = harris_k
|
||||
|
||||
pyramid = list(pyramid_gaussian(image, n_scales - 1, downscale))
|
||||
|
||||
keypoints_list = []
|
||||
orientations_list = []
|
||||
scales_list = []
|
||||
harris_response_list = []
|
||||
|
||||
for octave in range(len(pyramid)):
|
||||
def _build_pyramid(self, image):
|
||||
image = _prepare_grayscale_input_2D(image)
|
||||
return list(pyramid_gaussian(image, self.n_scales - 1, self.downscale))
|
||||
|
||||
def _detect_octave(self, octave_image):
|
||||
# Extract keypoints for current octave
|
||||
corners = corner_peaks(corner_fast(pyramid[octave], fast_n,
|
||||
fast_threshold), min_distance=1)
|
||||
fast_response = corner_fast(octave_image, self.fast_n,
|
||||
self.fast_threshold)
|
||||
keypoints = corner_peaks(fast_response, min_distance=1)
|
||||
|
||||
# Scale keypoint coordinates so they correspond to the original
|
||||
# image shape
|
||||
keypoints_list.append(corners * downscale ** octave)
|
||||
mask = _mask_border_keypoints(octave_image.shape, keypoints,
|
||||
distance=16)
|
||||
keypoints = keypoints[mask]
|
||||
|
||||
orientations_list.append(corner_orientations(pyramid[octave], corners,
|
||||
OFAST_MASK))
|
||||
orientations = corner_orientations(octave_image, keypoints,
|
||||
OFAST_MASK)
|
||||
|
||||
scales_list.append(octave * np.ones(corners.shape[0], dtype=np.intp))
|
||||
harris_response = corner_harris(octave_image, method='k',
|
||||
k=self.harris_k)
|
||||
responses = harris_response[keypoints[:, 0], keypoints[:, 1]]
|
||||
|
||||
harris_response = corner_harris(pyramid[octave], method='k',
|
||||
k=harris_k)
|
||||
harris_response_list.append(harris_response[corners[:, 0],
|
||||
corners[:, 1]])
|
||||
return keypoints, orientations, responses
|
||||
|
||||
keypoints_array = np.vstack(keypoints_list)
|
||||
orientations = np.hstack(orientations_list)
|
||||
scales = downscale ** np.hstack(scales_list)
|
||||
harris_measure = np.hstack(harris_response_list)
|
||||
keypoints = create_keypoint_recarray(keypoints_array[:, 0],
|
||||
keypoints_array[:, 1],
|
||||
scales, orientations,
|
||||
harris_measure)
|
||||
def detect(self, image):
|
||||
"""Detect oriented FAST keypoints along with the corresponding scale.
|
||||
|
||||
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]
|
||||
Parameters
|
||||
----------
|
||||
image : 2D array
|
||||
Input image.
|
||||
|
||||
Returns
|
||||
-------
|
||||
keypoints : (N, 2) array
|
||||
Keypoint coordinates as ``(row, col)``.
|
||||
scales : (N, ) array
|
||||
Corresponding scales.
|
||||
orientations : (N, ) array
|
||||
Corresponding orientations in radians.
|
||||
responses : (N, ) array
|
||||
Corresponding Harris corner responses.
|
||||
|
||||
def descriptor_orb(image, keypoints, downscale=1.2, n_scales=8):
|
||||
"""Compute rBRIEF descriptors for keypoints.
|
||||
"""
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : 2D ndarray
|
||||
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``.
|
||||
n_scales : int
|
||||
Number of scales from the bottom of the image pyramid to extract
|
||||
the features from.
|
||||
pyramid = self._build_pyramid(image)
|
||||
|
||||
Returns
|
||||
-------
|
||||
descriptors : (P, 256) bool ndarray
|
||||
2darray of type bool describing the P keypoints obtained after
|
||||
filtering out those near the image border. Size of each descriptor
|
||||
is 32 bytes or 256 bits.
|
||||
filtered_keypoints : (P, 2) ndarray
|
||||
Record array with fields row, col, octave, orientation, response for
|
||||
P keypoints obtained after removing out those that are near the
|
||||
border.
|
||||
keypoints_list = []
|
||||
orientations_list = []
|
||||
octave_list = []
|
||||
responses_list = []
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] Ethan Rublee, Vincent Rabaud, Kurt Konolige and Gary Bradski
|
||||
"ORB : An efficient alternative to SIFT and SURF"
|
||||
http://www.vision.cs.chubu.ac.jp/CV-R/pdf/Rublee_iccv2011.pdf
|
||||
for octave in range(len(pyramid)):
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> import numpy as np
|
||||
>>> from skimage.feature import keypoints_orb, descriptor_orb
|
||||
>>> square = np.zeros((50, 50))
|
||||
>>> square[20:30, 20:30] = 1
|
||||
>>> keypoints = keypoints_orb(square, n_keypoints=8, n_scales=2)
|
||||
>>> keypoints.shape
|
||||
(8,)
|
||||
>>> descriptors, filtered_keypoints = descriptor_orb(square, keypoints, n_scales=2)
|
||||
>>> filtered_keypoints.shape
|
||||
(8,)
|
||||
>>> descriptors.shape
|
||||
(8, 256)
|
||||
octave_image = np.ascontiguousarray(pyramid[octave])
|
||||
|
||||
"""
|
||||
image = _prepare_grayscale_input_2D(image)
|
||||
keypoints, orientations, responses = \
|
||||
self._detect_octave(octave_image)
|
||||
|
||||
pyramid = list(pyramid_gaussian(image, n_scales - 1, downscale))
|
||||
keypoints_list.append(keypoints * self.downscale ** octave)
|
||||
orientations_list.append(orientations)
|
||||
octave_list.append(self.downscale ** octave
|
||||
* np.ones(keypoints.shape[0], dtype=np.intp))
|
||||
responses_list.append(responses)
|
||||
|
||||
descriptors_list = []
|
||||
keypoints_list = []
|
||||
keypoints = np.vstack(keypoints_list)
|
||||
orientations = np.hstack(orientations_list)
|
||||
scales = np.hstack(octave_list)
|
||||
responses = np.hstack(responses_list)
|
||||
|
||||
for scale in range(n_scales):
|
||||
curr_image = np.ascontiguousarray(pyramid[scale])
|
||||
if keypoints.shape[0] < self.n_keypoints:
|
||||
return keypoints, scales, orientations, responses
|
||||
else:
|
||||
# Choose best n_keypoints according to Harris corner response
|
||||
best_indices = responses.argsort()[::-1][:self.n_keypoints]
|
||||
return (keypoints[best_indices], scales[best_indices],
|
||||
orientations[best_indices], responses[best_indices])
|
||||
|
||||
curr_scale_mask = (np.log(keypoints.octave) /
|
||||
np.log(downscale)).astype(np.intp) == scale
|
||||
if np.sum(curr_scale_mask) > 0:
|
||||
curr_keypoints = keypoints[curr_scale_mask]
|
||||
curr_scale_kpts = np.squeeze(np.dstack((curr_keypoints.row / curr_keypoints.octave,
|
||||
curr_keypoints.col / curr_keypoints.octave)))
|
||||
border_mask = _mask_border_keypoints(curr_image,
|
||||
curr_scale_kpts,
|
||||
dist=16)
|
||||
def _extract_octave(self, octave_image, keypoints, orientations):
|
||||
mask = _mask_border_keypoints(octave_image.shape, keypoints,
|
||||
distance=16)
|
||||
keypoints = np.array(keypoints[mask], dtype=np.intp, order='C',
|
||||
copy=False)
|
||||
orientations = np.array(orientations[mask], dtype=np.double, order='C',
|
||||
copy=False)
|
||||
|
||||
curr_keypoints = curr_keypoints[border_mask]
|
||||
descriptors = _orb_loop(octave_image, keypoints, orientations)
|
||||
|
||||
curr_scale_kpts = np.ascontiguousarray(np.round(curr_scale_kpts[border_mask]).astype(np.intp))
|
||||
curr_scale_orientation = np.ascontiguousarray(curr_keypoints.orientation)
|
||||
curr_scale_descriptors = _orb_loop(curr_image, curr_scale)
|
||||
return descriptors, mask
|
||||
|
||||
descriptors_list.append(curr_scale_descriptors)
|
||||
keypoints_list.append(curr_keypoints)
|
||||
def extract(self, image, keypoints, scales, orientations):
|
||||
"""Extract rBRIEF binary descriptors for given keypoints in image.
|
||||
|
||||
descriptors = np.vstack(descriptors_list).view(np.bool)
|
||||
filtered_keypoints = np.hstack(keypoints_list)
|
||||
return descriptors, filtered_keypoints.view(np.recarray)
|
||||
Parameters
|
||||
----------
|
||||
image : 2D array
|
||||
Input image.
|
||||
keypoints : (N, 2) array
|
||||
Keypoint coordinates as ``(row, col)``.
|
||||
scales : (N, ) array
|
||||
Corresponding scales.
|
||||
orientations : (N, ) array
|
||||
Corresponding orientations in radians.
|
||||
|
||||
Returns
|
||||
-------
|
||||
descriptors : (Q, `descriptor_size`) array of dtype bool
|
||||
2D array 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``).
|
||||
|
||||
"""
|
||||
|
||||
pyramid = self._build_pyramid(image)
|
||||
|
||||
descriptors_list = []
|
||||
mask_list = []
|
||||
|
||||
# Determine octaves from scales
|
||||
octaves = (np.log(scales) / np.log(self.downscale)).astype(np.intp)
|
||||
|
||||
for octave in range(len(pyramid)):
|
||||
|
||||
# Mask for all keypoints in current octave
|
||||
octave_mask = octaves == octave
|
||||
|
||||
if np.sum(octave_mask) > 0:
|
||||
|
||||
octave_image = np.ascontiguousarray(pyramid[octave])
|
||||
|
||||
octave_keypoints = keypoints[octave_mask]
|
||||
octave_keypoints /= self.downscale ** octave
|
||||
|
||||
octave_orientations = orientations[octave_mask]
|
||||
|
||||
descriptors, mask = self._extract_octave(octave_image,
|
||||
octave_keypoints,
|
||||
octave_orientations)
|
||||
|
||||
descriptors_list.append(descriptors)
|
||||
mask_list.append(mask)
|
||||
|
||||
descriptors = np.vstack(descriptors_list).view(np.bool)
|
||||
mask = np.hstack(mask_list)
|
||||
|
||||
return descriptors, mask
|
||||
|
||||
def detect_and_extract(self, image):
|
||||
"""Detect oriented FAST keypoints and extract rBRIEF descriptors.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : 2D array
|
||||
Input image.
|
||||
|
||||
Returns
|
||||
-------
|
||||
keypoints : (Q, 2) array
|
||||
Keypoint coordinates as ``(row, col)``.
|
||||
descriptors : (Q, `descriptor_size`) array of dtype bool
|
||||
2D array 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)``.
|
||||
|
||||
"""
|
||||
|
||||
pyramid = self._build_pyramid(image)
|
||||
|
||||
keypoints_list = []
|
||||
responses_list = []
|
||||
descriptors_list = []
|
||||
|
||||
for octave in range(len(pyramid)):
|
||||
|
||||
octave_image = np.ascontiguousarray(pyramid[octave])
|
||||
|
||||
keypoints, orientations, responses = \
|
||||
self._detect_octave(octave_image)
|
||||
|
||||
descriptors, mask = self._extract_octave(octave_image, keypoints,
|
||||
orientations)
|
||||
|
||||
keypoints_list.append(keypoints * self.downscale ** octave)
|
||||
responses_list.append(responses)
|
||||
descriptors_list.append(descriptors)
|
||||
|
||||
keypoints = np.vstack(keypoints_list)
|
||||
responses = np.hstack(responses_list)
|
||||
descriptors = np.vstack(descriptors_list).view(np.bool)
|
||||
|
||||
if keypoints.shape[0] < self.n_keypoints:
|
||||
return keypoints, descriptors
|
||||
else:
|
||||
# Choose best n_keypoints according to Harris corner response
|
||||
best_indices = responses.argsort()[::-1][:self.n_keypoints]
|
||||
return (keypoints[best_indices], descriptors[best_indices])
|
||||
|
||||
@@ -13,21 +13,23 @@ from libc.math cimport sin, cos, round
|
||||
|
||||
POS = np.loadtxt(os.path.join(data_dir, "orb_descriptor_positions.txt"),
|
||||
dtype=np.int8)
|
||||
POS0 = np.ascontiguousarray(POS[:, :2])
|
||||
POS1 = np.ascontiguousarray(POS[:, 2:])
|
||||
|
||||
|
||||
def _orb_loop(double[:, ::1] image, Py_ssize_t[:, ::1] keypoints,
|
||||
double[:] orientations, pos):
|
||||
double[:] orientations):
|
||||
|
||||
cdef Py_ssize_t i, d, kr, kc, pr0, pr1, pc0, pc1, spr0, spc0, spr1, spc1
|
||||
cdef int[:, ::1] steered_pos0, steered_pos1
|
||||
cdef double angle
|
||||
cdef char[:, ::1] descriptors = np.zeros((keypoints.shape[0],
|
||||
pos.shape[0]), dtype=np.uint8)
|
||||
cdef char[:, ::1] cpos0 = pos[:, :2]
|
||||
cdef char[:, ::1] cpos1 = pos[:, 2:]
|
||||
|
||||
POS.shape[0]), dtype=np.uint8)
|
||||
cdef char[:, ::1] cpos0 = POS0
|
||||
cdef char[:, ::1] cpos1 = POS1
|
||||
|
||||
for i in range(descriptors.shape[0]):
|
||||
|
||||
angle = orientations[i]
|
||||
sin_a = sin(angle)
|
||||
cos_a = cos(angle)
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
import numpy as np
|
||||
from numpy.testing import assert_array_equal, assert_almost_equal
|
||||
from skimage.feature import keypoints_orb, descriptor_orb
|
||||
from skimage.feature import ORB
|
||||
from skimage.data import lena
|
||||
from skimage.color import rgb2gray
|
||||
|
||||
|
||||
def test_keypoints_orb_desired_no_of_keypoints():
|
||||
img = rgb2gray(lena())
|
||||
keypoints = keypoints_orb(img, n_keypoints=10, fast_n=12,
|
||||
fast_threshold=0.20)
|
||||
exp_row = np.array([ 435. , 435.6 , 376. , 455. , 434.88, 269. ,
|
||||
375.6 , 310.8 , 413. , 311.04])
|
||||
exp_col = np.array([ 180. , 180. , 156. , 176. , 180. , 111. ,
|
||||
156. , 172.8, 70. , 172.8])
|
||||
img = rgb2gray(lena())
|
||||
|
||||
exp_octaves = np.array([ 1. , 1.2 , 1. , 1. , 1.44 , 1. ,
|
||||
1.2 , 1.2 , 1. , 1.728])
|
||||
|
||||
def test_keypoints_orb_desired_no_of_keypoints():
|
||||
detector_extractor = ORB(n_keypoints=10, fast_n=12, fast_threshold=0.20)
|
||||
keypoints, scales, orientations, responses = detector_extractor.detect(img)
|
||||
|
||||
exp_rows = np.array([ 435. , 435.6 , 376. , 455. , 434.88, 269. ,
|
||||
375.6 , 310.8 , 413. , 311.04])
|
||||
exp_cols = np.array([ 180. , 180. , 156. , 176. , 180. , 111. ,
|
||||
156. , 172.8, 70. , 172.8])
|
||||
|
||||
exp_scales = np.array([ 1. , 1.2 , 1. , 1. , 1.44 , 1. ,
|
||||
1.2 , 1.2 , 1. , 1.728])
|
||||
|
||||
exp_orientations = np.array([-175.64733392, -167.94842949, -148.98350192,
|
||||
-142.03599837, -176.08535837, -53.08162354,
|
||||
@@ -25,24 +28,30 @@ def test_keypoints_orb_desired_no_of_keypoints():
|
||||
0.5626413 , 0.5097993 , 0.44351774,
|
||||
0.39154173, 0.39084861, 0.39063076,
|
||||
0.37602487])
|
||||
assert_almost_equal(exp_row, keypoints.row)
|
||||
assert_almost_equal(exp_col, keypoints.col)
|
||||
assert_almost_equal(exp_octaves, keypoints.octave)
|
||||
assert_almost_equal(exp_response, keypoints.response)
|
||||
assert_almost_equal(exp_orientations, np.rad2deg(keypoints.orientation))
|
||||
|
||||
assert_almost_equal(exp_rows, keypoints[:, 0])
|
||||
assert_almost_equal(exp_cols, keypoints[:, 1])
|
||||
assert_almost_equal(exp_scales, scales)
|
||||
assert_almost_equal(exp_response, responses)
|
||||
assert_almost_equal(exp_orientations, np.rad2deg(orientations), 5)
|
||||
|
||||
keypoints, _ = detector_extractor.detect_and_extract(img)
|
||||
assert_almost_equal(exp_rows, keypoints[:, 0])
|
||||
assert_almost_equal(exp_cols, keypoints[:, 1])
|
||||
|
||||
|
||||
def test_keypoints_orb_less_than_desired_no_of_keypoints():
|
||||
img = rgb2gray(lena())
|
||||
keypoints = keypoints_orb(img, n_keypoints=15, fast_n=12,
|
||||
fast_threshold=0.33, downscale=2, n_scales=2)
|
||||
detector_extractor = ORB(n_keypoints=15, fast_n=12,
|
||||
fast_threshold=0.33, downscale=2, n_scales=2)
|
||||
keypoints, scales, orientations, responses = detector_extractor.detect(img)
|
||||
|
||||
exp_row = np.array([ 67., 247., 269., 413., 435., 230., 264.,
|
||||
330., 372.])
|
||||
exp_col = np.array([ 157., 146., 111., 70., 180., 136., 336.,
|
||||
148., 156.])
|
||||
exp_rows = np.array([ 67., 247., 269., 413., 435., 230., 264.,
|
||||
330., 372.])
|
||||
exp_cols = np.array([ 157., 146., 111., 70., 180., 136., 336.,
|
||||
148., 156.])
|
||||
|
||||
exp_octaves = np.array([ 1., 1., 1., 1., 1., 2., 2., 2., 2.])
|
||||
exp_scales = np.array([ 1., 1., 1., 1., 1., 2., 2., 2., 2.])
|
||||
|
||||
exp_orientations = np.array([-105.76503839, -96.28973044, -53.08162354,
|
||||
-173.4479964 , -175.64733392, -106.07927215,
|
||||
@@ -52,33 +61,51 @@ def test_keypoints_orb_less_than_desired_no_of_keypoints():
|
||||
0.39063076, 0.96770745, 0.04935129,
|
||||
0.21431068, 0.15826555, 0.42403573])
|
||||
|
||||
assert_almost_equal(exp_row, keypoints.row)
|
||||
assert_almost_equal(exp_col, keypoints.col)
|
||||
assert_almost_equal(exp_octaves, keypoints.octave)
|
||||
assert_almost_equal(exp_response, keypoints.response)
|
||||
assert_almost_equal(exp_orientations, np.rad2deg(keypoints.orientation))
|
||||
assert_almost_equal(exp_rows, keypoints[:, 0])
|
||||
assert_almost_equal(exp_cols, keypoints[:, 1])
|
||||
assert_almost_equal(exp_scales, scales)
|
||||
assert_almost_equal(exp_response, responses)
|
||||
assert_almost_equal(exp_orientations, np.rad2deg(orientations), 5)
|
||||
|
||||
keypoints, _ = detector_extractor.detect_and_extract(img)
|
||||
assert_almost_equal(exp_rows, keypoints[:, 0])
|
||||
assert_almost_equal(exp_cols, keypoints[:, 1])
|
||||
|
||||
|
||||
def test_descriptor_orb():
|
||||
img = rgb2gray(lena())
|
||||
keypoints = keypoints_orb(img, n_keypoints=10, fast_n=12,
|
||||
fast_threshold=0.20)
|
||||
descriptors, filtered_keypoints = descriptor_orb(img, keypoints)
|
||||
detector_extractor = ORB(fast_n=12, fast_threshold=0.20)
|
||||
|
||||
descriptors_120_129 = np.array([[ True, False, False, True, False, False, False, False, False, False],
|
||||
[ True, True, False, False, True, False, False, True, False, True],
|
||||
[False, True, True, False, True, False, True, True, True, True],
|
||||
[False, False, False, True, True, False, True, False, True, False],
|
||||
[False, True, True, True, True, False, True, True, True, False],
|
||||
[ True, False, True, True, True, False, False, False, True, False],
|
||||
[ True, False, True, False, True, False, True, True, False, True],
|
||||
[ True, True, True, True, True, True, False, True, True, True],
|
||||
[ True, True, True, False, True, False, True, True, True, False],
|
||||
[ True, False, False, False, False, False, True, True, True, False]],
|
||||
dtype=bool)
|
||||
exp_descriptors = np.array([[ True, False, True, True, False, False, False, False, False, False],
|
||||
[False, False, True, True, False, True, True, False, True, True],
|
||||
[ True, False, False, False, True, False, True, True, True, False],
|
||||
[ True, False, False, True, False, True, True, False, False, False],
|
||||
[False, True, True, True, False, False, False, True, True, False],
|
||||
[False, False, False, False, False, True, False, True, True, True],
|
||||
[False, True, True, True, True, False, False, True, False, True],
|
||||
[ True, True, True, False, True, True, True, True, False, False],
|
||||
[ True, True, False, True, True, True, True, False, False, False],
|
||||
[ True, False, False, False, False, True, False, False, True, True],
|
||||
[ True, False, False, False, True, True, True, False, False, False],
|
||||
[False, False, True, False, True, False, False, True, False, False],
|
||||
[False, False, True, True, False, False, False, False, False, True],
|
||||
[ True, True, False, False, False, True, True, True, True, True],
|
||||
[ True, True, True, False, False, True, False, True, True, False],
|
||||
[False, True, True, False, False, True, True, True, True, True],
|
||||
[ True, True, True, False, False, False, False, True, True, True],
|
||||
[False, False, False, False, True, False, False, True, True, False],
|
||||
[False, True, False, False, True, False, False, False, True, True],
|
||||
[ True, False, True, False, False, False, True, True, False, False]], dtype=bool)
|
||||
|
||||
keypoints1, scales1, orientations1, responses1 \
|
||||
= detector_extractor.detect(img)
|
||||
descriptors1, mask1 \
|
||||
= detector_extractor.extract(img, keypoints1, scales1, orientations1)
|
||||
assert_array_equal(exp_descriptors, descriptors1[100:120, 10:20])
|
||||
|
||||
assert_array_equal(descriptors_120_129, descriptors[:, 120:130])
|
||||
keypoints2, descriptors2 = detector_extractor.detect_and_extract(img)
|
||||
assert_array_equal(exp_descriptors, descriptors2[100:120, 10:20])
|
||||
|
||||
assert_array_equal(keypoints1[mask1], keypoints2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Reference in New Issue
Block a user