Including min_scale as another input parameter

This commit is contained in:
Ankit Agrawal
2013-08-12 23:51:19 +05:30
parent 6d1be9aee4
commit c3b6ce2c82
3 changed files with 76 additions and 31 deletions
+31 -24
View File
@@ -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) \
+40 -2
View File
@@ -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]
+5 -5
View File
@@ -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],