mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-09 07:11:31 +08:00
Including min_scale as another input parameter
This commit is contained in:
+31
-24
@@ -19,10 +19,10 @@ STAR_FILTER_SHAPE = [(1, 0), (3, 1), (4, 2), (5, 3), (7, 4), (8, 5),
|
||||
(9, 6),(11, 8), (13, 10), (14, 11), (15, 12), (16, 14)]
|
||||
|
||||
|
||||
def _get_filtered_image(image, max_scale, mode):
|
||||
def _get_filtered_image(image, min_scale, max_scale, mode):
|
||||
|
||||
scales = np.zeros((image.shape[0], image.shape[1], max_scale),
|
||||
dtype=np.double)
|
||||
scales = np.zeros((image.shape[0], image.shape[1],
|
||||
max_scale - min_scale +1), dtype=np.double)
|
||||
|
||||
if mode == 'dob':
|
||||
|
||||
@@ -34,8 +34,8 @@ def _get_filtered_image(image, max_scale, mode):
|
||||
|
||||
integral_img = integral_image(image)
|
||||
|
||||
for i in range(max_scale):
|
||||
n = i + 1
|
||||
for i in range(max_scale - min_scale + 1):
|
||||
n = min_scale + i
|
||||
|
||||
# Constant multipliers for the outer region and the inner region
|
||||
# of the bilevel filters with the constraint of keeping the
|
||||
@@ -54,16 +54,16 @@ def _get_filtered_image(image, max_scale, mode):
|
||||
elif mode == 'octagon':
|
||||
# TODO : Decide the shapes of Octagon filters for scales > 7
|
||||
|
||||
for i in range(max_scale):
|
||||
mo, no = OCTAGON_OUTER_SHAPE[i]
|
||||
mi, ni = OCTAGON_INNER_SHAPE[i]
|
||||
for i in range(max_scale - min_scale + 1):
|
||||
mo, no = OCTAGON_OUTER_SHAPE[min_scale + i - 1]
|
||||
mi, ni = OCTAGON_INNER_SHAPE[min_scale + i - 1]
|
||||
scales[:, :, i] = convolve(image,
|
||||
_octagon_filter_kernel(mo, no, mi, ni))
|
||||
elif mode == 'star':
|
||||
|
||||
for i in range(max_scale):
|
||||
m = STAR_SHAPE[STAR_FILTER_SHAPE[i][0]]
|
||||
n = STAR_SHAPE[STAR_FILTER_SHAPE[i][1]]
|
||||
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]]
|
||||
scales[:, :, i] = convolve(image,
|
||||
_star_filter_kernel(m, n))
|
||||
|
||||
@@ -135,8 +135,8 @@ def _suppress_lines(feature_mask, image, sigma, line_threshold):
|
||||
> line_threshold * (Axx * Ayy - Axy * Axy)] = False
|
||||
|
||||
|
||||
def keypoints_censure(image, max_scale=7, mode='DoB', non_max_threshold=0.15,
|
||||
line_threshold=10):
|
||||
def keypoints_censure(image, min_scale=1, max_scale=7, mode='DoB',
|
||||
non_max_threshold=0.15, line_threshold=10):
|
||||
"""
|
||||
Extracts Censure keypoints along with the corresponding scale using
|
||||
either Difference of Boxes, Octagon or STAR bilevel filter.
|
||||
@@ -145,9 +145,12 @@ def keypoints_censure(image, max_scale=7, mode='DoB', non_max_threshold=0.15,
|
||||
----------
|
||||
image : 2D ndarray
|
||||
Input image.
|
||||
min_scale : positive integer
|
||||
Minimum scale to extract keypoints from.
|
||||
max_scale : positive integer
|
||||
Number of scales to extract keypoints from. The keypoints will be
|
||||
extracted from all the scales except the first and the last.
|
||||
Maximum scale to extract keypoints from. The keypoints will be
|
||||
extracted from all the scales except the first and the last i.e.
|
||||
from the scales in the range [min_scale + 1, max_scale - 1].
|
||||
mode : ('DoB', 'Octagon', 'STAR')
|
||||
Type of bilevel filter used to get the scales of the input image.
|
||||
Possible values are 'DoB', 'Octagon' and 'STAR'. The three modes
|
||||
@@ -197,8 +200,12 @@ def keypoints_censure(image, max_scale=7, mode='DoB', non_max_threshold=0.15,
|
||||
if mode not in ('dob', 'octagon', 'star'):
|
||||
raise ValueError('Mode must be one of "DoB", "Octagon", "STAR".')
|
||||
|
||||
if max_scale - min_scale < 2:
|
||||
raise ValueError('The number of scales should be greater than or'
|
||||
'equal to 3.')
|
||||
|
||||
# Generating all the scales
|
||||
filter_response = _get_filtered_image(image, max_scale, mode)
|
||||
filter_response = _get_filtered_image(image, min_scale, max_scale, mode)
|
||||
|
||||
# Suppressing points that are neither minima or maxima in their 3 x 3 x 3
|
||||
# neighbourhood to zero
|
||||
@@ -208,17 +215,17 @@ def keypoints_censure(image, max_scale=7, mode='DoB', non_max_threshold=0.15,
|
||||
feature_mask = minimas | maximas
|
||||
feature_mask[filter_response < non_max_threshold] = False
|
||||
|
||||
for i in range(1, max_scale - 1):
|
||||
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 * i
|
||||
# Hence sigma = 1 + i / 3.0
|
||||
# window_size = 7 + 2 * (min_scale - 1 + i)
|
||||
# Hence sigma = 1 + (min_scale - 1 + i)/ 3.0
|
||||
_suppress_lines(feature_mask[:, :, i], image,
|
||||
(1 + i / 3.0), line_threshold)
|
||||
(1 + (min_scale + i - 1) / 3.0), line_threshold)
|
||||
|
||||
rows, cols, scales = np.nonzero(feature_mask[..., 1:max_scale - 1])
|
||||
rows, cols, scales = np.nonzero(feature_mask[..., 1:max_scale - min_scale])
|
||||
keypoints = np.column_stack([rows, cols])
|
||||
scales = scales + 2
|
||||
scales = scales + min_scale + 1
|
||||
|
||||
if mode == 'dob':
|
||||
return keypoints, scales
|
||||
@@ -226,13 +233,13 @@ def keypoints_censure(image, max_scale=7, mode='DoB', non_max_threshold=0.15,
|
||||
cumulative_mask = np.zeros(keypoints.shape[0], dtype=np.bool)
|
||||
|
||||
if mode == 'octagon':
|
||||
for i in range(2, max_scale):
|
||||
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(2, max_scale):
|
||||
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) \
|
||||
|
||||
@@ -18,8 +18,46 @@ def _censure_dob_loop(Py_ssize_t n,
|
||||
cdef Py_ssize_t n2 = 2 * n
|
||||
cdef double total_weight = inner_weight + outer_weight
|
||||
|
||||
for i in range(n2, integral_img.shape[0] - n2):
|
||||
for j in range(n2, integral_img.shape[1] - n2):
|
||||
# top-left pixel
|
||||
inner = (integral_img[n2 + n, n2 + n]
|
||||
+ integral_img[n2 - n - 1, n2 - n - 1]
|
||||
- integral_img[n2 + n, n2 - n - 1]
|
||||
- integral_img[n2 - n - 1, n2 + n])
|
||||
|
||||
outer = integral_img[2 * n2, 2 * n2]
|
||||
|
||||
filtered_image[n2, n2] = (outer_weight * outer
|
||||
- total_weight * inner)
|
||||
|
||||
# left column
|
||||
for i in range(n2 + 1, integral_img.shape[0] - n2):
|
||||
inner = (integral_img[i + n, n2 + n]
|
||||
+ integral_img[i - n - 1, n2 - n - 1]
|
||||
- integral_img[i + n, n2 - n - 1]
|
||||
- integral_img[i - n - 1, n2 + n])
|
||||
|
||||
outer = (integral_img[i + n2, 2 * n2]
|
||||
- integral_img[i - n2 - 1, 2 * n2])
|
||||
|
||||
filtered_image[i, n2] = (outer_weight * outer
|
||||
- total_weight * inner)
|
||||
|
||||
# top row
|
||||
for j in range(n2 + 1, integral_img.shape[1] - n2):
|
||||
inner = (integral_img[n2 + n, j + n]
|
||||
+ integral_img[n2 - n - 1, j - n - 1]
|
||||
- integral_img[n2 + n, j - n - 1]
|
||||
- integral_img[n2 - n - 1, j + n])
|
||||
|
||||
outer = (integral_img[2 * n2, j + n2]
|
||||
- integral_img[2 * n2, j - n2 - 1])
|
||||
|
||||
filtered_image[n2, j] = (outer_weight * outer
|
||||
- total_weight * inner)
|
||||
|
||||
# remaining block
|
||||
for i in range(n2 + 1, integral_img.shape[0] - n2):
|
||||
for j in range(n2 + 1, integral_img.shape[1] - n2):
|
||||
inner = (integral_img[i + n, j + n]
|
||||
+ integral_img[i - n - 1, j - n - 1]
|
||||
- integral_img[i + n, j - n - 1]
|
||||
|
||||
@@ -14,7 +14,7 @@ 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, 7, 'DoB', 0.15)
|
||||
actual_kp_dob, actual_scale = keypoints_censure(img, 1, 7, 'DoB', 0.15)
|
||||
expected_kp_dob = np.array([[ 21, 497],
|
||||
[ 36, 46],
|
||||
[119, 350],
|
||||
@@ -30,11 +30,11 @@ def test_keypoints_censure_moon_image_dob():
|
||||
assert_array_equal(expected_scale, actual_scale)
|
||||
|
||||
|
||||
def test_keypoints_censure_moon_image_Octagon():
|
||||
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, 7, 'Octagon',
|
||||
actual_kp_octagon, actual_scale = keypoints_censure(img, 1, 7, 'Octagon',
|
||||
0.15)
|
||||
expected_kp_octagon = np.array([[ 21, 496],
|
||||
[ 35, 46],
|
||||
@@ -48,11 +48,11 @@ def test_keypoints_censure_moon_image_Octagon():
|
||||
assert_array_equal(expected_scale, actual_scale)
|
||||
|
||||
|
||||
def test_keypoints_censure_moon_image_STAR():
|
||||
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, 7, 'STAR', 0.15)
|
||||
actual_kp_star, actual_scale = keypoints_censure(img, 1, 7, 'STAR', 0.15)
|
||||
expected_kp_star = np.array([[ 21, 497],
|
||||
[ 36, 46],
|
||||
[117, 356],
|
||||
|
||||
Reference in New Issue
Block a user