Files
Juan Nunez-Iglesias 29e9bff5eb Add test for 3D images
2016-07-16 21:03:42 -05:00

415 lines
16 KiB
Python

import numpy as np
from numpy.testing import (assert_array_equal, assert_raises,
assert_almost_equal)
from skimage import data
from skimage import img_as_float
from skimage.color import rgb2gray
from skimage.morphology import octagon
from skimage._shared.testing import test_parallel
from skimage.feature import (corner_moravec, corner_harris, corner_shi_tomasi,
corner_subpix, peak_local_max, corner_peaks,
corner_kitchen_rosenfeld, corner_foerstner,
corner_fast, corner_orientations,
structure_tensor, structure_tensor_eigvals,
hessian_matrix, hessian_matrix_eigvals,
hessian_matrix_det)
def test_structure_tensor():
square = np.zeros((5, 5))
square[2, 2] = 1
Axx, Axy, Ayy = structure_tensor(square, sigma=0.1)
assert_array_equal(Axx, np.array([[ 0, 0, 0, 0, 0],
[ 0, 1, 0, 1, 0],
[ 0, 4, 0, 4, 0],
[ 0, 1, 0, 1, 0],
[ 0, 0, 0, 0, 0]]))
assert_array_equal(Axy, np.array([[ 0, 0, 0, 0, 0],
[ 0, 1, 0, -1, 0],
[ 0, 0, 0, -0, 0],
[ 0, -1, -0, 1, 0],
[ 0, 0, 0, 0, 0]]))
assert_array_equal(Ayy, np.array([[ 0, 0, 0, 0, 0],
[ 0, 1, 4, 1, 0],
[ 0, 0, 0, 0, 0],
[ 0, 1, 4, 1, 0],
[ 0, 0, 0, 0, 0]]))
def test_hessian_matrix():
square = np.zeros((5, 5))
square[2, 2] = 4
Hxx, Hxy, Hyy = hessian_matrix(square, sigma=0.1)
assert_almost_equal(Hxx, np.array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[2, 0, -2, 0, 2],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]]))
assert_almost_equal(Hxy, np.array([[0, 0, 0, 0, 0],
[0, 1, 0, -1, 0],
[0, 0, 0, 0, 0],
[0, -1, 0, 1, 0],
[0, 0, 0, 0, 0]]))
assert_almost_equal(Hyy, np.array([[0, 0, 2, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, -2, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 2, 0, 0]]))
def test_hessian_matrix_3d():
cube = np.zeros((5, 5, 5))
cube[2, 2, 2] = 4
Hs = hessian_matrix(cube, sigma=0.1)
assert len(Hs) == 6, ("incorrect number of Hessian images (%i) for 3D" %
len(Hs))
assert_almost_equal(Hs[2][:, 2, :], np.array([[0, 0, 0, 0, 0],
[0, 1, 0, -1, 0],
[0, 0, 0, 0, 0],
[0, -1, 0, 1, 0],
[0, 0, 0, 0, 0]]))
def test_structure_tensor_eigvals():
square = np.zeros((5, 5))
square[2, 2] = 1
Axx, Axy, Ayy = structure_tensor(square, sigma=0.1)
l1, l2 = structure_tensor_eigvals(Axx, Axy, Ayy)
assert_array_equal(l1, np.array([[0, 0, 0, 0, 0],
[0, 2, 4, 2, 0],
[0, 4, 0, 4, 0],
[0, 2, 4, 2, 0],
[0, 0, 0, 0, 0]]))
assert_array_equal(l2, np.array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]]))
def test_hessian_matrix_eigvals():
square = np.zeros((5, 5))
square[2, 2] = 4
Hxx, Hxy, Hyy = hessian_matrix(square, sigma=0.1)
l1, l2 = hessian_matrix_eigvals(Hxx, Hxy, Hyy)
assert_almost_equal(l1, np.array([[0, 0, 2, 0, 0],
[0, 1, 0, 1, 0],
[2, 0, -2, 0, 2],
[0, 1, 0, 1, 0],
[0, 0, 2, 0, 0]]))
assert_almost_equal(l2, np.array([[0, 0, 0, 0, 0],
[0, -1, 0, -1, 0],
[0, 0, -2, 0, 0],
[0, -1, 0, -1, 0],
[0, 0, 0, 0, 0]]))
@test_parallel()
def test_hessian_matrix_det():
image = np.zeros((5, 5))
image[2, 2] = 1
det = hessian_matrix_det(image, 5)
assert_almost_equal(det, 0, decimal = 3)
@test_parallel()
def test_square_image():
im = np.zeros((50, 50)).astype(float)
im[:25, :25] = 1.
# Moravec
results = peak_local_max(corner_moravec(im),
min_distance=10, threshold_rel=0)
# interest points along edge
assert len(results) == 57
# Harris
results = peak_local_max(corner_harris(im, method='k'),
min_distance=10, threshold_rel=0)
# interest at corner
assert len(results) == 1
results = peak_local_max(corner_harris(im, method='eps'),
min_distance=10, threshold_rel=0)
# interest at corner
assert len(results) == 1
# Shi-Tomasi
results = peak_local_max(corner_shi_tomasi(im),
min_distance=10, threshold_rel=0)
# interest at corner
assert len(results) == 1
def test_noisy_square_image():
im = np.zeros((50, 50)).astype(float)
im[:25, :25] = 1.
np.random.seed(seed=1234)
im = im + np.random.uniform(size=im.shape) * .2
# Moravec
results = peak_local_max(corner_moravec(im),
min_distance=10, threshold_rel=0)
# undefined number of interest points
assert results.any()
# Harris
results = peak_local_max(corner_harris(im, method='k'),
min_distance=10, threshold_rel=0)
assert len(results) == 1
results = peak_local_max(corner_harris(im, method='eps'),
min_distance=10, threshold_rel=0)
assert len(results) == 1
# Shi-Tomasi
results = peak_local_max(corner_shi_tomasi(im, sigma=1.5),
min_distance=10, threshold_rel=0)
assert len(results) == 1
def test_squared_dot():
im = np.zeros((50, 50))
im[4:8, 4:8] = 1
im = img_as_float(im)
# Moravec fails
# Harris
results = peak_local_max(corner_harris(im),
min_distance=10, threshold_rel=0)
assert (results == np.array([[6, 6]])).all()
# Shi-Tomasi
results = peak_local_max(corner_shi_tomasi(im),
min_distance=10, threshold_rel=0)
assert (results == np.array([[6, 6]])).all()
def test_rotated_img():
"""
The harris filter should yield the same results with an image and it's
rotation.
"""
im = img_as_float(data.astronaut().mean(axis=2))
im_rotated = im.T
# Moravec
results = peak_local_max(corner_moravec(im),
min_distance=10, threshold_rel=0)
results_rotated = peak_local_max(corner_moravec(im_rotated),
min_distance=10, threshold_rel=0)
assert (np.sort(results[:, 0]) == np.sort(results_rotated[:, 1])).all()
assert (np.sort(results[:, 1]) == np.sort(results_rotated[:, 0])).all()
# Harris
results = peak_local_max(corner_harris(im),
min_distance=10, threshold_rel=0)
results_rotated = peak_local_max(corner_harris(im_rotated),
min_distance=10, threshold_rel=0)
assert (np.sort(results[:, 0]) == np.sort(results_rotated[:, 1])).all()
assert (np.sort(results[:, 1]) == np.sort(results_rotated[:, 0])).all()
# Shi-Tomasi
results = peak_local_max(corner_shi_tomasi(im),
min_distance=10, threshold_rel=0)
results_rotated = peak_local_max(corner_shi_tomasi(im_rotated),
min_distance=10, threshold_rel=0)
assert (np.sort(results[:, 0]) == np.sort(results_rotated[:, 1])).all()
assert (np.sort(results[:, 1]) == np.sort(results_rotated[:, 0])).all()
def test_subpix_edge():
img = np.zeros((50, 50))
img[:25, :25] = 255
img[25:, 25:] = 255
corner = peak_local_max(corner_harris(img),
min_distance=10, threshold_rel=0, num_peaks=1)
subpix = corner_subpix(img, corner)
assert_array_equal(subpix[0], (24.5, 24.5))
def test_subpix_dot():
img = np.zeros((50, 50))
img[25, 25] = 255
corner = peak_local_max(corner_harris(img),
min_distance=10, threshold_rel=0, num_peaks=1)
subpix = corner_subpix(img, corner)
assert_array_equal(subpix[0], (25, 25))
def test_subpix_no_class():
img = np.zeros((50, 50))
subpix = corner_subpix(img, np.array([[25, 25]]))
assert_array_equal(subpix[0], (np.nan, np.nan))
img[25, 25] = 1e-10
corner = peak_local_max(corner_harris(img),
min_distance=10, threshold_rel=0, num_peaks=1)
subpix = corner_subpix(img, np.array([[25, 25]]))
assert_array_equal(subpix[0], (np.nan, np.nan))
def test_subpix_border():
img = np.zeros((50, 50))
img[1:25,1:25] = 255
img[25:-1,25:-1] = 255
corner = corner_peaks(corner_harris(img), threshold_rel=0)
subpix = corner_subpix(img, corner, window_size=11)
ref = np.array([[ 0.52040816, 0.52040816],
[ 0.52040816, 24.47959184],
[24.47959184, 0.52040816],
[24.5 , 24.5 ],
[24.52040816, 48.47959184],
[48.47959184, 24.52040816],
[48.47959184, 48.47959184]])
assert_almost_equal(subpix, ref)
def test_num_peaks():
"""For a bunch of different values of num_peaks, check that
peak_local_max returns exactly the right amount of peaks. Test
is run on the astronaut image in order to produce a sufficient number of corners"""
img_corners = corner_harris(rgb2gray(data.astronaut()))
for i in range(20):
n = np.random.randint(1, 21)
results = peak_local_max(img_corners,
min_distance=10, threshold_rel=0, num_peaks=n)
assert (results.shape[0] == n)
def test_corner_peaks():
response = np.zeros((10, 10))
response[2:5, 2:5] = 1
corners = corner_peaks(response, exclude_border=False, min_distance=10,
threshold_rel=0)
assert len(corners) == 1
corners = corner_peaks(response, exclude_border=False, min_distance=1)
assert len(corners) == 4
corners = corner_peaks(response, exclude_border=False, min_distance=1,
indices=False)
assert np.sum(corners) == 4
def test_blank_image_nans():
"""Some of the corner detectors had a weakness in terms of returning
NaN when presented with regions of constant intensity. This should
be fixed by now. We test whether each detector returns something
finite in the case of constant input"""
detectors = [corner_moravec, corner_harris, corner_shi_tomasi,
corner_kitchen_rosenfeld, corner_foerstner]
constant_image = np.zeros((20, 20))
for det in detectors:
response = det(constant_image)
assert np.all(np.isfinite(response))
def test_corner_fast_image_unsupported_error():
img = np.zeros((20, 20, 3))
assert_raises(ValueError, corner_fast, img)
@test_parallel()
def test_corner_fast_astronaut():
img = rgb2gray(data.astronaut())
expected = np.array([[101, 198],
[140, 205],
[141, 242],
[177, 156],
[188, 113],
[197, 148],
[213, 117],
[223, 375],
[232, 266],
[245, 137],
[249, 171],
[300, 244],
[305, 57],
[325, 245],
[339, 242],
[346, 279],
[353, 172],
[358, 307],
[362, 252],
[362, 328],
[363, 192],
[364, 147],
[369, 159],
[374, 171],
[379, 183],
[387, 195],
[390, 149],
[401, 197],
[403, 162],
[413, 181],
[444, 310],
[464, 251],
[476, 250],
[489, 155],
[492, 139],
[494, 169],
[496, 266]])
actual = corner_peaks(corner_fast(img, 12, 0.3),
min_distance=10, threshold_rel=0)
assert_array_equal(actual, expected)
def test_corner_orientations_image_unsupported_error():
img = np.zeros((20, 20, 3))
assert_raises(ValueError, corner_orientations, img,
np.asarray([[7, 7]]), np.ones((3, 3)))
def test_corner_orientations_even_shape_error():
img = np.zeros((20, 20))
assert_raises(ValueError, corner_orientations, img,
np.asarray([[7, 7]]), np.ones((4, 4)))
@test_parallel()
def test_corner_orientations_astronaut():
img = rgb2gray(data.astronaut())
corners = corner_peaks(corner_fast(img, 11, 0.35),
min_distance=10, threshold_abs=0, threshold_rel=0.1)
expected = np.array([-1.75220190e+00, 2.01197383e+00, -2.01162417e+00,
-1.88247204e-01, 1.19134149e+00, -6.61151410e-01,
-2.99143370e+00, 2.17103132e+00, -7.52950306e-04,
1.25854853e+00, 2.43573659e+00, -1.69230287e+00,
-9.88548213e-01, 1.47154532e+00, -1.65449964e+00,
1.09650167e+00, 1.07812134e+00, -1.68885773e+00,
-1.64397304e+00, 3.09780364e+00, -3.49561988e-01,
-1.46554357e+00, -2.81524886e+00, 8.12701702e-01,
2.47305654e+00, -1.63869275e+00, 5.46905279e-02,
-4.40598471e-01, 3.14918803e-01, -1.76069982e+00,
3.05330950e+00, 2.39291733e+00, -1.22091334e-01,
-3.09279990e-01, 1.45931342e+00])
actual = corner_orientations(img, corners, octagon(3, 2))
assert_almost_equal(actual, expected)
def test_corner_orientations_square():
square = np.zeros((12, 12))
square[3:9, 3:9] = 1
corners = corner_peaks(corner_fast(square, 9),
min_distance=1, threshold_rel=0)
actual_orientations = corner_orientations(square, corners, octagon(3, 2))
actual_orientations_degrees = np.rad2deg(actual_orientations)
expected_orientations_degree = np.array([ 45., 135., -45., -135.])
assert_array_equal(actual_orientations_degrees,
expected_orientations_degree)
if __name__ == '__main__':
from numpy import testing
testing.run_module_suite()