diff --git a/skimage/measure/_ssim.py b/skimage/measure/_ssim.py index 17fc165c..322d5799 100644 --- a/skimage/measure/_ssim.py +++ b/skimage/measure/_ssim.py @@ -5,6 +5,8 @@ __all__ = ['structural_similarity'] import numpy as np from numpy.lib import stride_tricks +from ..util.dtype import dtype_range + def _as_windows(X, win_size=7, flatten_first_axis=True): """Re-stride an array to simulate a sliding window. @@ -39,7 +41,7 @@ def _as_windows(X, win_size=7, flatten_first_axis=True): return windows -def structural_similarity(X, Y, win_size=7, gradient=False, dynamic_range=255): +def structural_similarity(X, Y, win_size=7, gradient=False, dynamic_range=None): """Compute the mean structural similarity index between two images. Parameters @@ -49,12 +51,12 @@ def structural_similarity(X, Y, win_size=7, gradient=False, dynamic_range=255): win_size : int The side-length of the sliding window used in comparison. Must be an odd value. - dynamic_range : int - Dynamic range of the input image (distance between minimum and - maximum possible values). This should eventually be - auto-computed, but just specifying it manually for now. gradient : bool If True, also return the gradient. + dynamic_range : int + Dynamic range of the input image (distance between minimum and + maximum possible values). By default, this is estimated from + the image data-type. Returns ------- @@ -81,6 +83,10 @@ def structural_similarity(X, Y, win_size=7, gradient=False, dynamic_range=255): if not (win_size % 2 == 1): raise ValueError('Window size must be odd.') + if dynamic_range is None: + dmin, dmax = dtype_range[X.dtype.type] + dynamic_range = dmax - dmin + XW = _as_windows(X, win_size=win_size) YW = _as_windows(Y, win_size=win_size) diff --git a/skimage/measure/tests/test_ssim.py b/skimage/measure/tests/test_ssim.py index 4e713ecb..3115d78f 100644 --- a/skimage/measure/tests/test_ssim.py +++ b/skimage/measure/tests/test_ssim.py @@ -34,17 +34,32 @@ def test_ssim_image(): assert(S1 < 0.3) def test_ssim_grad(): + N = 30 + X = np.random.random((N, N)) * 255 + Y = np.random.random((N, N)) * 255 + + def func(Y): + return ssim(X, Y, dynamic_range=255) + + def grad(Y): + return ssim(X, Y, dynamic_range=255, gradient=True)[1] + + assert(np.all(opt.check_grad(func, grad, Y) < 0.05)) + +def test_ssim_dtype(): N = 30 X = np.random.random((N, N)) Y = np.random.random((N, N)) - def func(Y): - return ssim(X, Y) + S1 = ssim(X, Y) - def grad(Y): - return ssim(X, Y, gradient=True)[1] + X = (X * 255).astype(np.uint8) + Y = (X * 255).astype(np.uint8) - assert(np.all(opt.check_grad(func, grad, Y) < 0.05)) + S2 = ssim(X, Y) + + assert S1 < 0.1 + assert S2 < 0.1 if __name__ == "__main__":