diff --git a/skimage/measure/_moments.py b/skimage/measure/_moments.py index 65b8f571..10ff3768 100644 --- a/skimage/measure/_moments.py +++ b/skimage/measure/_moments.py @@ -7,8 +7,8 @@ def moments(image, order=3): """Calculate all raw image moments up to a certain order. The following properties can be calculated from raw image moments: - * Area as ``m[0, 0]``. - * Centroid as {``m[0, 1] / m[0, 0]``, ``m[1, 0] / m[0, 0]``}. + * Area as: ``m[0, 0]``. + * Centroid as: {``m[0, 1] / m[0, 0]``, ``m[1, 0] / m[0, 0]``}. Note that raw moments are neither translation, scale nor rotation invariant. @@ -36,6 +36,16 @@ def moments(image, order=3): Berlin, 1993. .. [4] http://en.wikipedia.org/wiki/Image_moment + Examples + -------- + >>> image = np.zeros((20, 20), dtype=np.double) + >>> image[13:17, 13:17] = 1 + >>> m = moments(image) + >>> cr = m[0, 1] / m[0, 0] + >>> cc = m[1, 0] / m[0, 0] + >>> cr, cc + (14.5, 14.5) + """ return _moments_cy.moments_central(image, 0, 0, order) @@ -43,6 +53,9 @@ def moments(image, order=3): def moments_central(image, cr, cc, order=3): """Calculate all central image moments up to a certain order. + The center coordinates (cr, cc) can be calculated from the raw moments as: + {``m[0, 1] / m[0, 0]``, ``m[1, 0] / m[0, 0]``}. + Note that central moments are translation invariant but not scale and rotation invariant. @@ -73,6 +86,18 @@ def moments_central(image, cr, cc, order=3): Berlin, 1993. .. [4] http://en.wikipedia.org/wiki/Image_moment + Examples + -------- + >>> image = np.zeros((20, 20), dtype=np.double) + >>> image[13:17, 13:17] = 1 + >>> m = moments(image) + >>> cr = m[0, 1] / m[0, 0] + >>> cc = m[1, 0] / m[0, 0] + >>> moments_central(image, cr, cc) + array([[ 16., 0., 20., 0.], + [ 0., 0., 0., 0.], + [ 20., 0., 25., 0.], + [ 0., 0., 0., 0.]]) """ return _moments_cy.moments_central(image, cr, cc, order) @@ -107,7 +132,25 @@ def moments_normalized(mu, order=3): Berlin, 1993. .. [4] http://en.wikipedia.org/wiki/Image_moment + Examples + -------- + >>> image = np.zeros((20, 20), dtype=np.double) + >>> image[13:17, 13:17] = 1 + >>> m = moments(image) + >>> cr = m[0, 1] / m[0, 0] + >>> cc = m[1, 0] / m[0, 0] + >>> mu = moments_central(image, cr, cc) + >>> moments_normalized(mu) + array([[ nan, nan, 0.078125 , 0. ], + [ nan, 0. , 0. , 0. ], + [ 0.078125 , 0. , 0.00610352, 0. ], + [ 0. , 0. , 0. , 0. ]]) + """ + if mu.ndim != 2: + raise TypeError("Image moments must be 2-dimension") + if mu.shape[0] <= order or mu.shape[1] <= order: + raise TypeError("Shape of image moments must be >= `order`") return _moments_cy.moments_normalized(mu.astype(np.double), order) diff --git a/skimage/measure/tests/test_moments.py b/skimage/measure/tests/test_moments.py index 0667f688..033d0a54 100644 --- a/skimage/measure/tests/test_moments.py +++ b/skimage/measure/tests/test_moments.py @@ -1,4 +1,4 @@ -from numpy.testing import assert_equal, assert_almost_equal +from numpy.testing import assert_equal, assert_almost_equal, assert_raises import numpy as np from skimage.measure import (moments, moments_central, moments_normalized, @@ -50,6 +50,13 @@ def test_moments_normalized(): assert_almost_equal(nu, nu2, decimal=1) +def test_moments_normalized_invalid(): + assert_raises(TypeError, moments_normalized, np.zeros((3, 3, 3))) + assert_raises(TypeError, moments_normalized, np.zeros((3,))) + assert_raises(TypeError, moments_normalized, np.zeros((3, 3)), 3) + assert_raises(TypeError, moments_normalized, np.zeros((3, 3)), 4) + + def test_moments_hu(): image = np.zeros((20, 20), dtype=np.double) image[13:15, 13:17] = 1