diff --git a/TODO.txt b/TODO.txt index b867bc73..4fe8e90d 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,3 +1,8 @@ +Version 0.11 +------------ +* Remove deprecated `reverse_map` parameter of `skimage.transform.warp` + + Version 0.10 ------------ * Remove deprecated functions in `skimage.filter.rank.*` @@ -14,3 +19,6 @@ Version 0.10 * Remove deprecated `skimage.color.is_gray` and `skimage.color.is_rgb` functions * Enable doctests of experimental `skimage.feature.brief` +* Remove deprecated `skimage.segmentation.visualize_boundaries` +* Remove deprecated `skimage.morphology.greyscale_*` +* Remove deprecated `skimage.exposure.equalize` diff --git a/skimage/exposure/exposure.py b/skimage/exposure/exposure.py index f703f846..31d9a57f 100644 --- a/skimage/exposure/exposure.py +++ b/skimage/exposure/exposure.py @@ -263,7 +263,7 @@ def adjust_gamma(image, gamma=1, gain=1): dtype = image.dtype.type if gamma < 0: - return "Gamma should be a non-negative real number" + raise ValueError("Gamma should be a non-negative real number.") scale = float(dtype_limits(image, True)[1] - dtype_limits(image, True)[0]) diff --git a/skimage/exposure/tests/test_exposure.py b/skimage/exposure/tests/test_exposure.py index 2b696b32..e6610874 100644 --- a/skimage/exposure/tests/test_exposure.py +++ b/skimage/exposure/tests/test_exposure.py @@ -2,7 +2,7 @@ import warnings import numpy as np from numpy.testing import assert_array_almost_equal as assert_close -from numpy.testing import assert_array_equal +from numpy.testing import assert_array_equal, assert_raises import skimage from skimage import data from skimage import exposure @@ -230,6 +230,11 @@ def test_adjust_gamma_greater_one(): assert_array_equal(result, expected) +def test_adjust_gamma_neggative(): + image = np.arange(0, 255, 4, np.uint8).reshape(8,8) + assert_raises(ValueError, exposure.adjust_gamma, image, -1) + + # Test Logarithmic Correction # =========================== @@ -336,3 +341,8 @@ def test_adjust_inv_sigmoid_cutoff_half(): result = exposure.adjust_sigmoid(image, 0.5, 10, True) assert_array_equal(result, expected) + + +def test_neggative(): + image = np.arange(-10, 245, 4).reshape(8, 8).astype(np.double) + assert_raises(ValueError, exposure.adjust_gamma, image) diff --git a/skimage/feature/_daisy.py b/skimage/feature/_daisy.py index 1a97de8f..3a55faf1 100644 --- a/skimage/feature/_daisy.py +++ b/skimage/feature/_daisy.py @@ -94,15 +94,15 @@ def daisy(img, step=4, radius=15, rings=3, histograms=8, orientations=8, ''' # Validate image format. - if img.ndim > 2: + if img.ndim != 2: raise ValueError('Only grey-level images are supported.') - if img.dtype.kind != 'f': - img = img_as_float(img) + + img = img_as_float(img) # Validate parameters. if sigmas is not None and ring_radii is not None \ and len(sigmas) - 1 != len(ring_radii): - raise ValueError('len(sigmas)-1 != len(ring_radii)') + raise ValueError('`len(sigmas)-1 != len(ring_radii)`') if ring_radii is not None: rings = len(ring_radii) radius = ring_radii[-1] diff --git a/skimage/feature/_greycomatrix.py b/skimage/feature/_greycomatrix.py deleted file mode 100644 index 45476d33..00000000 --- a/skimage/feature/_greycomatrix.py +++ /dev/null @@ -1,226 +0,0 @@ -""" -Compute grey level co-occurrence matrices (GLCMs) and associated -properties to characterize image textures. -""" - -import numpy as np - -from ._texture import _glcm_loop - - -def greycomatrix(image, distances, angles, levels=256, symmetric=False, - normed=False): - """Calculate the grey-level co-occurrence matrix. - - A grey level co-occurence matrix is a histogram of co-occuring - greyscale values at a given offset over an image. - - Parameters - ---------- - image : array_like of uint8 - Integer typed input image. The image will be cast to uint8, so - the maximum value must be less than 256. - distances : array_like - List of pixel pair distance offsets. - angles : array_like - List of pixel pair angles in radians. - levels : int, optional - The input image should contain integers in [0, levels-1], - where levels indicate the number of grey-levels counted - (typically 256 for an 8-bit image). The maximum value is - 256. - symmetric : bool, optional - If True, the output matrix `P[:, :, d, theta]` is symmetric. This - is accomplished by ignoring the order of value pairs, so both - (i, j) and (j, i) are accumulated when (i, j) is encountered - for a given offset. The default is False. - normed : bool, optional - If True, normalize each matrix `P[:, :, d, theta]` by dividing - by the total number of accumulated co-occurrences for the given - offset. The elements of the resulting matrix sum to 1. The - default is False. - - Returns - ------- - P : 4-D ndarray - The grey-level co-occurrence histogram. The value - `P[i,j,d,theta]` is the number of times that grey-level `j` - occurs at a distance `d` and at an angle `theta` from - grey-level `i`. If `normed` is `False`, the output is of - type uint32, otherwise it is float64. - - References - ---------- - .. [1] The GLCM Tutorial Home Page, - http://www.fp.ucalgary.ca/mhallbey/tutorial.htm - .. [2] Pattern Recognition Engineering, Morton Nadler & Eric P. - Smith - .. [3] Wikipedia, http://en.wikipedia.org/wiki/Co-occurrence_matrix - - - Examples - -------- - Compute 2 GLCMs: One for a 1-pixel offset to the right, and one - for a 1-pixel offset upwards. - - >>> image = np.array([[0, 0, 1, 1], - ... [0, 0, 1, 1], - ... [0, 2, 2, 2], - ... [2, 2, 3, 3]], dtype=np.uint8) - >>> result = greycomatrix(image, [1], [0, np.pi/2], levels=4) - >>> result[:, :, 0, 0] - array([[2, 2, 1, 0], - [0, 2, 0, 0], - [0, 0, 3, 1], - [0, 0, 0, 1]], dtype=uint32) - >>> result[:, :, 0, 1] - array([[3, 0, 2, 0], - [0, 2, 2, 0], - [0, 0, 1, 2], - [0, 0, 0, 0]], dtype=uint32) - - """ - - assert levels <= 256 - image = np.ascontiguousarray(image) - assert image.ndim == 2 - assert image.min() >= 0 - assert image.max() < levels - image = image.astype(np.uint8) - distances = np.ascontiguousarray(distances, dtype=np.float64) - angles = np.ascontiguousarray(angles, dtype=np.float64) - assert distances.ndim == 1 - assert angles.ndim == 1 - - P = np.zeros((levels, levels, len(distances), len(angles)), - dtype=np.uint32, order='C') - - # count co-occurences - _glcm_loop(image, distances, angles, levels, P) - - # make each GLMC symmetric - if symmetric: - Pt = np.transpose(P, (1, 0, 2, 3)) - P = P + Pt - - # normalize each GLMC - if normed: - P = P.astype(np.float64) - glcm_sums = np.apply_over_axes(np.sum, P, axes=(0, 1)) - glcm_sums[glcm_sums == 0] = 1 - P /= glcm_sums - - return P - - -def greycoprops(P, prop='contrast'): - """Calculate texture properties of a GLCM. - - Compute a feature of a grey level co-occurrence matrix to serve as - a compact summary of the matrix. The properties are computed as - follows: - - - 'contrast': :math:`\\sum_{i,j=0}^{levels-1} P_{i,j}(i-j)^2` - - 'dissimilarity': :math:`\\sum_{i,j=0}^{levels-1}P_{i,j}|i-j|` - - 'homogeneity': :math:`\\sum_{i,j=0}^{levels-1}\\frac{P_{i,j}}{1+(i-j)^2}` - - 'ASM': :math:`\\sum_{i,j=0}^{levels-1} P_{i,j}^2` - - 'energy': :math:`\\sqrt{ASM}` - - 'correlation': - .. math:: \\sum_{i,j=0}^{levels-1} P_{i,j}\\left[\\frac{(i-\\mu_i) \\ - (j-\\mu_j)}{\\sqrt{(\\sigma_i^2)(\\sigma_j^2)}}\\right] - - - Parameters - ---------- - P : ndarray - Input array. `P` is the grey-level co-occurrence histogram - for which to compute the specified property. The value - `P[i,j,d,theta]` is the number of times that grey-level j - occurs at a distance d and at an angle theta from - grey-level i. - - prop : {'contrast', 'dissimilarity', 'homogeneity', 'energy', \ - 'correlation', 'ASM'}, optional - The property of the GLCM to compute. The default is 'contrast'. - - Returns - ------- - results : 2-D ndarray - 2-dimensional array. `results[d, a]` is the property 'prop' for - the d'th distance and the a'th angle. - - References - ---------- - .. [1] The GLCM Tutorial Home Page, - http://www.fp.ucalgary.ca/mhallbey/tutorial.htm - - Examples - -------- - Compute the contrast for GLCMs with distances [1, 2] and angles - [0 degrees, 90 degrees] - - >>> image = np.array([[0, 0, 1, 1], - ... [0, 0, 1, 1], - ... [0, 2, 2, 2], - ... [2, 2, 3, 3]], dtype=np.uint8) - >>> g = greycomatrix(image, [1, 2], [0, np.pi/2], levels=4, - ... normed=True, symmetric=True) - >>> contrast = greycoprops(g, 'contrast') - >>> contrast - array([[ 0.58333333, 1. ], - [ 1.25 , 2.75 ]]) - - """ - - assert P.ndim == 4 - (num_level, num_level2, num_dist, num_angle) = P.shape - assert num_level == num_level2 - assert num_dist > 0 - assert num_angle > 0 - - # create weights for specified property - I, J = np.ogrid[0:num_level, 0:num_level] - if prop == 'contrast': - weights = (I - J)**2 - elif prop == 'dissimilarity': - weights = np.abs(I - J) - elif prop == 'homogeneity': - weights = 1. / (1. + (I - J)**2) - elif prop in ['ASM', 'energy', 'correlation']: - pass - else: - raise ValueError('%s is an invalid property' % (prop)) - - # compute property for each GLCM - if prop == 'energy': - asm = np.apply_over_axes(np.sum, (P**2), axes=(0, 1))[0, 0] - results = np.sqrt(asm) - elif prop == 'ASM': - results = np.apply_over_axes(np.sum, (P**2), axes=(0, 1))[0, 0] - elif prop == 'correlation': - results = np.zeros((num_dist, num_angle), dtype=np.float64) - I = np.array(range(num_level)).reshape((num_level, 1, 1, 1)) - J = np.array(range(num_level)).reshape((1, num_level, 1, 1)) - diff_i = I - np.apply_over_axes(np.sum, (I * P), axes=(0, 1))[0, 0] - diff_j = J - np.apply_over_axes(np.sum, (J * P), axes=(0, 1))[0, 0] - - std_i = np.sqrt(np.apply_over_axes(np.sum, (P * (diff_i)**2), - axes=(0, 1))[0, 0]) - std_j = np.sqrt(np.apply_over_axes(np.sum, (P * (diff_j)**2), - axes=(0, 1))[0, 0]) - cov = np.apply_over_axes(np.sum, (P * (diff_i * diff_j)), - axes=(0, 1))[0, 0] - - # handle the special case of standard deviations near zero - mask_0 = std_i < 1e-15 - mask_0[std_j < 1e-15] = True - results[mask_0] = 1 - - # handle the standard case - mask_1 = mask_0 == False - results[mask_1] = cov[mask_1] / (std_i[mask_1] * std_j[mask_1]) - elif prop in ['contrast', 'dissimilarity', 'homogeneity']: - weights = weights.reshape((num_level, num_level, 1, 1)) - results = np.apply_over_axes(np.sum, (P * weights), axes=(0, 1))[0, 0] - - return results diff --git a/skimage/feature/tests/test_corner.py b/skimage/feature/tests/test_corner.py index 9c07c006..7ff34796 100644 --- a/skimage/feature/tests/test_corner.py +++ b/skimage/feature/tests/test_corner.py @@ -19,7 +19,11 @@ def test_square_image(): assert len(results) == 57 # Harris - results = peak_local_max(corner_harris(im)) + results = peak_local_max(corner_harris(im, method='k')) + # interest at corner + assert len(results) == 1 + + results = peak_local_max(corner_harris(im, method='eps')) # interest at corner assert len(results) == 1 @@ -41,7 +45,9 @@ def test_noisy_square_image(): assert results.any() # Harris - results = peak_local_max(corner_harris(im, sigma=1.5)) + results = peak_local_max(corner_harris(im, sigma=1.5, method='k')) + assert len(results) == 1 + results = peak_local_max(corner_harris(im, sigma=1.5, method='eps')) assert len(results) == 1 # Shi-Tomasi @@ -140,6 +146,10 @@ def test_corner_peaks(): corners = corner_peaks(response, exclude_border=False, min_distance=0) assert len(corners) == 4 + corners = corner_peaks(response, exclude_border=False, min_distance=0, + indices=False) + assert np.sum(corners) == 4 + def test_blank_image_nans(): """Some of the corner detectors had a weakness in terms of returning diff --git a/skimage/feature/tests/test_daisy.py b/skimage/feature/tests/test_daisy.py index 7f4e85d7..32a7a5df 100644 --- a/skimage/feature/tests/test_daisy.py +++ b/skimage/feature/tests/test_daisy.py @@ -45,8 +45,15 @@ def test_descs_shape(): assert(descs.shape[1] == ceil((img.shape[1] - radius * 2) / float(step))) +def test_daisy_sigmas_and_radii(): + img = img_as_float(data.lena()[:64, :64].mean(axis=2)) + sigmas = [1, 2, 3] + radii = [1, 2] + daisy(img, sigmas=sigmas, ring_radii=radii) + + def test_daisy_incompatible_sigmas_and_radii(): - img = img_as_float(data.lena()[:128, :128].mean(axis=2)) + img = img_as_float(data.lena()[:64, :64].mean(axis=2)) sigmas = [1, 2] radii = [1, 2] assert_raises(ValueError, daisy, img, sigmas=sigmas, ring_radii=radii) diff --git a/skimage/measure/tests/test_fit.py b/skimage/measure/tests/test_fit.py index bde1fcc7..253ac0ea 100644 --- a/skimage/measure/tests/test_fit.py +++ b/skimage/measure/tests/test_fit.py @@ -44,7 +44,7 @@ def test_line_model_residuals(): assert_equal(abs(model.residuals(np.array([[10, 0]]))), 10) model._params = (5, np.pi / 4) assert_equal(abs(model.residuals(np.array([[0, 0]]))), 5) - assert_equal(abs(model.residuals(np.array([[np.sqrt(50), 0]]))), 5) + assert_almost_equal(abs(model.residuals(np.array([[np.sqrt(50), 0]]))), 0) def test_line_model_under_determined(): @@ -127,7 +127,7 @@ def test_ellipse_model_estimate(): assert_almost_equal(model0._params, model_est._params, 0) -def test_line_model_residuals(): +def test_ellipse_model_residuals(): model = EllipseModel() # vertical line through origin model._params = (0, 0, 10, 5, 0) diff --git a/skimage/measure/tests/test_regionprops.py b/skimage/measure/tests/test_regionprops.py index 5a4dd117..42926499 100644 --- a/skimage/measure/tests/test_regionprops.py +++ b/skimage/measure/tests/test_regionprops.py @@ -345,6 +345,9 @@ def test_old_dict_interface(): np.array([list(props.values()) for props in feats], np.float) assert_equal(len(feats[0]), 8) + def assign(): + feats[0]['Area'] = 0 + assert_raises(RuntimeError, assign) def test_label_sequence(): @@ -361,6 +364,13 @@ def test_pure_background(): assert len(ps) == 0 +def test_invalid(): + ps = regionprops(SAMPLE) + def get_intensity_image(): + ps[0].intensity_image + assert_raises(AttributeError, get_intensity_image) + + if __name__ == "__main__": from numpy.testing import run_module_suite run_module_suite() diff --git a/skimage/morphology/tests/test_grey.py b/skimage/morphology/tests/test_grey.py index e2a3928d..f0099ee5 100644 --- a/skimage/morphology/tests/test_grey.py +++ b/skimage/morphology/tests/test_grey.py @@ -155,5 +155,15 @@ class TestDTypes(): self._test_image(image) +def test_inplace(): + selem = np.ones((3, 3)) + image = np.zeros((5, 5)) + out = image + + for f in (grey.erosion, grey.dilation, + grey.white_tophat, grey.black_tophat): + testing.assert_raises(NotImplementedError, f, image, selem, out=out) + + if __name__ == '__main__': testing.run_module_suite() diff --git a/skimage/segmentation/tests/test_boundaries.py b/skimage/segmentation/tests/test_boundaries.py new file mode 100644 index 00000000..2fff52f8 --- /dev/null +++ b/skimage/segmentation/tests/test_boundaries.py @@ -0,0 +1,59 @@ +import numpy as np +from numpy.testing import assert_array_equal +from skimage.segmentation import find_boundaries, mark_boundaries + + +def test_find_boundaries(): + image = np.zeros((10, 10)) + image[2:7, 2:7] = 1 + + ref = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 1, 1, 1, 1, 1, 1, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 1, 1, 1, 1, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]) + + result = find_boundaries(image) + assert_array_equal(result, ref) + + +def test_mark_boundaries(): + image = np.zeros((10, 10)) + label_image = np.zeros((10, 10)) + label_image[2:7, 2:7] = 1 + + ref = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 1, 1, 1, 1, 1, 1, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 1, 1, 1, 1, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]) + result = mark_boundaries(image, label_image, color=(1, 1, 1)).mean(axis=2) + assert_array_equal(result, ref) + + ref = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 1, 1, 1, 1, 1, 1, 2, 0], + [0, 0, 1, 2, 2, 2, 2, 1, 2, 0], + [0, 0, 1, 2, 0, 0, 0, 1, 2, 0], + [0, 0, 1, 2, 0, 0, 0, 1, 2, 0], + [0, 0, 1, 2, 0, 0, 0, 1, 2, 0], + [0, 0, 1, 1, 1, 1, 1, 2, 2, 0], + [0, 0, 2, 2, 2, 2, 2, 2, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]) + result = mark_boundaries(image, label_image, color=(1, 1, 1), + outline_color=(2, 2, 2)).mean(axis=2) + assert_array_equal(result, ref) + + +if __name__ == "__main__": + np.testing.run_module_suite() diff --git a/skimage/segmentation/tests/test_slic.py b/skimage/segmentation/tests/test_slic.py index a4657785..15d1fe6d 100644 --- a/skimage/segmentation/tests/test_slic.py +++ b/skimage/segmentation/tests/test_slic.py @@ -1,7 +1,7 @@ import itertools as it import warnings import numpy as np -from numpy.testing import assert_equal, assert_array_equal +from numpy.testing import assert_equal, assert_raises from skimage.segmentation import slic @@ -21,10 +21,10 @@ def test_color_2d(): # we expect 4 segments assert_equal(len(np.unique(seg)), 4) assert_equal(seg.shape, img.shape[:-1]) - assert_array_equal(seg[:10, :10], 0) - assert_array_equal(seg[10:, :10], 2) - assert_array_equal(seg[:10, 10:], 1) - assert_array_equal(seg[10:, 10:], 3) + assert_equal(seg[:10, :10], 0) + assert_equal(seg[10:, :10], 2) + assert_equal(seg[:10, 10:], 1) + assert_equal(seg[10:, 10:], 3) def test_gray_2d(): @@ -41,10 +41,10 @@ def test_gray_2d(): assert_equal(len(np.unique(seg)), 4) assert_equal(seg.shape, img.shape) - assert_array_equal(seg[:10, :10], 0) - assert_array_equal(seg[10:, :10], 2) - assert_array_equal(seg[:10, 10:], 1) - assert_array_equal(seg[10:, 10:], 3) + assert_equal(seg[:10, :10], 0) + assert_equal(seg[10:, :10], 2) + assert_equal(seg[:10, 10:], 1) + assert_equal(seg[10:, 10:], 3) def test_color_3d(): @@ -65,7 +65,7 @@ def test_color_3d(): assert_equal(len(np.unique(seg)), 8) for s, c in zip(slices, range(8)): - assert_array_equal(seg[s], c) + assert_equal(seg[s], c) def test_gray_3d(): @@ -87,7 +87,7 @@ def test_gray_3d(): assert_equal(len(np.unique(seg)), 8) for s, c in zip(slices, range(8)): - assert_array_equal(seg[s], c) + assert_equal(seg[s], c) def test_list_sigma(): @@ -118,6 +118,12 @@ def test_spacing(): assert_equal(seg_spaced, result_spaced) +def test_invalid_lab_conversion(): + img = np.array([[1, 1, 1, 0, 0], + [1, 1, 0, 0, 0]], np.float) + assert_raises(ValueError, slic, img, multichannel=True, convert2lab=True) + + if __name__ == '__main__': from numpy import testing diff --git a/skimage/transform/__init__.py b/skimage/transform/__init__.py index 4f00a076..c6408309 100644 --- a/skimage/transform/__init__.py +++ b/skimage/transform/__init__.py @@ -5,6 +5,7 @@ from .radon_transform import radon, iradon, iradon_sart from .finite_radon_transform import frt2, ifrt2 from .integral import integral_image, integrate from ._geometric import (warp, warp_coords, estimate_transform, + matrix_transform, SimilarityTransform, AffineTransform, ProjectiveTransform, PolynomialTransform, PiecewiseAffineTransform) @@ -30,6 +31,7 @@ __all__ = ['hough_circle', 'warp', 'warp_coords', 'estimate_transform', + 'matrix_transform', 'SimilarityTransform', 'AffineTransform', 'ProjectiveTransform', diff --git a/skimage/transform/_geometric.py b/skimage/transform/_geometric.py index eb89460e..a4587c10 100644 --- a/skimage/transform/_geometric.py +++ b/skimage/transform/_geometric.py @@ -1021,10 +1021,12 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1, """ # Backward API compatibility if reverse_map is not None: + warnings.warn('`reverse_map` parameter is deprecated and replaced by ' + 'the `inverse_map` parameter.') inverse_map = reverse_map - if image.ndim < 2: - raise ValueError("Input must have more than 1 dimension.") + if image.ndim < 2 or image.ndim > 3: + raise ValueError("Input must have 2 or 3 dimensions.") orig_ndim = image.ndim image = np.atleast_3d(img_as_float(image)) @@ -1049,8 +1051,8 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1, # inverse_map is the inverse of a homography elif (hasattr(inverse_map, '__name__') and inverse_map.__name__ == 'inverse' - and isinstance(get_bound_method_class(inverse_map), - HOMOGRAPHY_TRANSFORMS)): + and get_bound_method_class(inverse_map) \ + in HOMOGRAPHY_TRANSFORMS): matrix = np.linalg.inv(six.get_method_self(inverse_map)._matrix) if matrix is not None: diff --git a/skimage/transform/tests/test_geometric.py b/skimage/transform/tests/test_geometric.py index c7f9f832..06c4f652 100644 --- a/skimage/transform/tests/test_geometric.py +++ b/skimage/transform/tests/test_geometric.py @@ -1,7 +1,9 @@ import numpy as np -from numpy.testing import assert_equal, assert_array_almost_equal +from numpy.testing import (assert_equal, assert_array_almost_equal, + assert_raises) from skimage.transform._geometric import _stackcopy -from skimage.transform import (estimate_transform, +from skimage.transform._geometric import GeometricTransform +from skimage.transform import (estimate_transform, matrix_transform, SimilarityTransform, AffineTransform, ProjectiveTransform, PolynomialTransform, PiecewiseAffineTransform) @@ -38,6 +40,18 @@ def test_stackcopy(): assert_array_almost_equal(x[..., i], y) +def test_estimate_transform(): + for tform in ('similarity', 'affine', 'projective', 'polynomial'): + estimate_transform(tform, SRC[:2, :], DST[:2, :]) + assert_raises(ValueError, estimate_transform, 'foobar', + SRC[:2, :], DST[:2, :]) + + +def test_matrix_transform(): + tform = AffineTransform(scale=(0.1, 0.5), rotation=2) + assert_equal(tform(SRC), matrix_transform(SRC, tform._matrix)) + + def test_similarity_estimation(): # exact solution tform = estimate_transform('similarity', SRC[:2, :], DST[:2, :]) @@ -74,6 +88,16 @@ def test_similarity_init(): assert_array_almost_equal(tform2.rotation, rotation) assert_array_almost_equal(tform2.translation, translation) + # test special case for scale if rotation=0 + scale = 0.1 + rotation = 0 + translation = (1, 1) + tform = SimilarityTransform(scale=scale, rotation=rotation, + translation=translation) + assert_array_almost_equal(tform.scale, scale) + assert_array_almost_equal(tform.rotation, rotation) + assert_array_almost_equal(tform.translation, translation) + def test_affine_estimation(): # exact solution @@ -165,15 +189,44 @@ def test_polynomial_default_order(): assert_array_almost_equal(tform2._params, tform._params) +def test_polynomial_inverse(): + assert_raises(Exception, PolynomialTransform().inverse, 0) + + def test_union(): tform1 = SimilarityTransform(scale=0.1, rotation=0.3) tform2 = SimilarityTransform(scale=0.1, rotation=0.9) tform3 = SimilarityTransform(scale=0.1 ** 2, rotation=0.3 + 0.9) - tform = tform1 + tform2 - assert_array_almost_equal(tform._matrix, tform3._matrix) + tform1 = AffineTransform(scale=(0.1, 0.1), rotation=0.3) + tform2 = SimilarityTransform(scale=0.1, rotation=0.9) + tform3 = SimilarityTransform(scale=0.1 ** 2, rotation=0.3 + 0.9) + tform = tform1 + tform2 + assert_array_almost_equal(tform._matrix, tform3._matrix) + assert tform.__class__ == ProjectiveTransform + + +def test_geometric_tform(): + tform = GeometricTransform() + assert_raises(NotImplementedError, tform, 0) + assert_raises(NotImplementedError, tform.inverse, 0) + assert_raises(NotImplementedError, tform.__add__, 0) + + +def test_invalid_input(): + assert_raises(ValueError, ProjectiveTransform, np.zeros((2, 3))) + assert_raises(ValueError, AffineTransform, np.zeros((2, 3))) + assert_raises(ValueError, SimilarityTransform, np.zeros((2, 3))) + + assert_raises(ValueError, AffineTransform, + matrix=np.zeros((2, 3)), scale=1) + assert_raises(ValueError, SimilarityTransform, + matrix=np.zeros((2, 3)), scale=1) + + assert_raises(ValueError, PolynomialTransform, np.zeros((3, 3))) + if __name__ == "__main__": from numpy.testing import run_module_suite diff --git a/skimage/transform/tests/test_warps.py b/skimage/transform/tests/test_warps.py index 7f7ef47d..db936a3a 100644 --- a/skimage/transform/tests/test_warps.py +++ b/skimage/transform/tests/test_warps.py @@ -1,4 +1,5 @@ -from numpy.testing import assert_array_almost_equal, run_module_suite, assert_array_equal +from numpy.testing import (assert_array_almost_equal, run_module_suite, + assert_array_equal, assert_raises) import numpy as np from scipy.ndimage import map_coordinates @@ -234,5 +235,18 @@ def test_downscale_local_mean(): assert_array_equal(expected2, out2) +def test_invalid(): + assert_raises(ValueError, warp, np.ones((4, )), SimilarityTransform()) + assert_raises(ValueError, warp, np.ones((4, 3, 3, 3)), + SimilarityTransform()) + + +def test_inverse(): + tform = SimilarityTransform(scale=0.5, rotation=0.1) + inverse_tform = SimilarityTransform(matrix=np.linalg.inv(tform._matrix)) + image = np.arange(10 * 10).reshape(10, 10).astype(np.double) + assert_array_equal(warp(image, inverse_tform), warp(image, tform.inverse)) + + if __name__ == "__main__": run_module_suite()