diff --git a/skimage/measure/__init__.py b/skimage/measure/__init__.py index de865f9e..be5f2bd0 100755 --- a/skimage/measure/__init__.py +++ b/skimage/measure/__init__.py @@ -2,7 +2,7 @@ from ._find_contours import find_contours from ._marching_cubes import (marching_cubes, mesh_surface_area, correct_mesh_orientation) from ._regionprops import regionprops, perimeter -from .simple_metrics import mse, nrmse, psnr +from .simple_metrics import mean_squared_error, normalized_root_mse, psnr from ._structural_similarity import structural_similarity from ._polygon import approximate_polygon, subdivide_polygon from ._pnpoly import points_in_poly, grid_points_in_poly @@ -36,6 +36,6 @@ __all__ = ['find_contours', 'label', 'points_in_poly', 'grid_points_in_poly', - 'mse', - 'nrmse', + 'mean_squared_error', + 'normalized_root_mse', 'psnr'] diff --git a/skimage/measure/simple_metrics.py b/skimage/measure/simple_metrics.py index 399bcf99..07038bb4 100644 --- a/skimage/measure/simple_metrics.py +++ b/skimage/measure/simple_metrics.py @@ -3,48 +3,49 @@ from __future__ import division import numpy as np from ..util.dtype import dtype_range -__all__ = ['mse', 'nrmse', 'psnr'] +__all__ = ['mean_squared_error', 'normalized_root_mse', 'psnr'] -def _assert_compatible(X, Y): +def _assert_compatible(im1, im2): """Raise an error if the shape and dtype do not match.""" - if not X.dtype == Y.dtype: + if not im1.dtype == im2.dtype: raise ValueError('Input images must have the same dtype.') - if not X.shape == Y.shape: + if not im1.shape == im2.shape: raise ValueError('Input images must have the same dimensions.') return -def _as_floats(X, Y): - """Promote X, Y to floating point precision.""" - if X.dtype != np.float64: - X = X.astype(np.float64) - if Y.dtype != np.float64: - Y = Y.astype(np.float64) - return X, Y +def _as_floats(im1, im2): + """Promote im1, im2 to floating point precision.""" + if im1.dtype != np.float64: + im1 = im1.astype(np.float64) + if im2.dtype != np.float64: + im2 = im2.astype(np.float64) + return im1, im2 -def mse(X, Y): +def mean_squared_error(im1, im2): """Compute the mean-squared error between two images. Parameters ---------- - X, Y : ndarray + im1, im2 : ndarray Image. Any dimensionality. Returns ------- mse : float - The MSE metric. + The mean-squared error (MSE) metric. """ - _assert_compatible(X, Y) - X, Y = _as_floats(X, Y) - return np.square(X - Y).mean() + _assert_compatible(im1, im2) + im1, im2 = _as_floats(im1, im2) + return np.mean(np.square(im1 - im2)) -def nrmse(im_true, im_test, norm_type='Euclidean'): - """Compute the normalized root mean-squared error between two images. +def normalized_root_mse(im_true, im_test, norm_type='Euclidean'): + """Compute the normalized root mean-squared error (NRMSE) between two + images. Parameters ---------- @@ -76,14 +77,14 @@ def nrmse(im_true, im_test, norm_type='Euclidean'): norm_type = norm_type.lower() if norm_type == 'euclidean': - denom = np.sqrt((im_true*im_true).mean()) + denom = np.sqrt(np.mean((im_true*im_true))) elif norm_type == 'min-max': denom = im_true.max() - im_true.min() elif norm_type == 'mean': denom = im_true.mean() else: raise ValueError("Unsupported norm_type") - return np.sqrt(mse(im_true, im_test)) / denom + return np.sqrt(mean_squared_error(im_true, im_test)) / denom def psnr(im_true, im_test, dynamic_range=None): @@ -113,7 +114,7 @@ def psnr(im_true, im_test, dynamic_range=None): _assert_compatible(im_true, im_test) if dynamic_range is None: dmin, dmax = dtype_range[im_true.dtype.type] - true_min, true_max = im_true.min(), im_true.max() + true_min, true_max = np.min(im_true), np.max(im_true) if true_max > dmax or true_min < dmin: raise ValueError( "im_true has intensity values outside the range expected for " @@ -126,5 +127,5 @@ def psnr(im_true, im_test, dynamic_range=None): im_true, im_test = _as_floats(im_true, im_test) - err = mse(im_true, im_test) + err = mean_squared_error(im_true, im_test) return 10 * np.log10((dynamic_range ** 2) / err) diff --git a/skimage/measure/tests/test_simple_metrics.py b/skimage/measure/tests/test_simple_metrics.py index f1ab274a..b59a11a8 100644 --- a/skimage/measure/tests/test_simple_metrics.py +++ b/skimage/measure/tests/test_simple_metrics.py @@ -2,7 +2,7 @@ import numpy as np from numpy.testing import (run_module_suite, assert_equal, assert_raises, assert_almost_equal) -from skimage.measure import psnr, nrmse, mse +from skimage.measure import psnr, normalized_root_mse, mean_squared_error import skimage.data np.random.seed(5) @@ -34,26 +34,27 @@ def test_PSNR_errors(): def test_NRMSE(): x = np.ones(4) y = np.asarray([0., 2., 2., 2.]) - assert_equal(nrmse(y, x, 'mean'), 1/np.mean(y)) - assert_equal(nrmse(y, x, 'Euclidean'), 1/np.sqrt(3)) - assert_equal(nrmse(y, x, 'min-max'), 1/(y.max()-y.min())) + assert_equal(normalized_root_mse(y, x, 'mean'), 1/np.mean(y)) + assert_equal(normalized_root_mse(y, x, 'Euclidean'), 1/np.sqrt(3)) + assert_equal(normalized_root_mse(y, x, 'min-max'), 1/(y.max()-y.min())) def test_NRMSE_no_int_overflow(): camf = cam.astype(np.float32) cam_noisyf = cam_noisy.astype(np.float32) - assert_almost_equal(mse(cam, cam_noisy), - mse(camf, cam_noisyf)) - assert_almost_equal(nrmse(cam, cam_noisy), - nrmse(camf, cam_noisyf)) + assert_almost_equal(mean_squared_error(cam, cam_noisy), + mean_squared_error(camf, cam_noisyf)) + assert_almost_equal(normalized_root_mse(cam, cam_noisy), + normalized_root_mse(camf, cam_noisyf)) def test_NRMSE_errors(): x = np.ones(4) - assert_raises(ValueError, nrmse, x.astype(np.uint8), x.astype(np.float32)) - assert_raises(ValueError, nrmse, x[:-1], x) + assert_raises(ValueError, normalized_root_mse, + x.astype(np.uint8), x.astype(np.float32)) + assert_raises(ValueError, normalized_root_mse, x[:-1], x) # invalid normalization name - assert_raises(ValueError, nrmse, x, x, 'foo') + assert_raises(ValueError, normalized_root_mse, x, x, 'foo') if __name__ == "__main__":