structural_similarity: add image_content_weighting option

This commit is contained in:
Gregory R. Lee
2015-05-11 14:03:31 -04:00
parent b193e7990e
commit 3b27107bfb
2 changed files with 24 additions and 4 deletions
+21 -4
View File
@@ -76,7 +76,8 @@ def _discard_edges(X, pad):
def structural_similarity(X, Y, win_size=None, gradient=False,
dynamic_range=None, multichannel=None,
gaussian_weights=False, full=False):
gaussian_weights=False, full=False,
image_content_weighting=False):
"""Compute the mean structural similarity index between two images.
Parameters
@@ -102,6 +103,9 @@ def structural_similarity(X, Y, win_size=None, gradient=False,
full : bool
If True, return the full structural similarity image instead of the
mean value
image_content_weighting : bool
If True, weight the ssim mean is spatially weighted by image content as
proposed in Wang and Shang 2006 [3].
Returns
-------
@@ -128,6 +132,9 @@ def structural_similarity(X, Y, win_size=None, gradient=False,
.. [2] Avanaki, A. N. (2009). Exact global histogram specification
optimized for structural similarity. Optical Review, 16, 613-621.
.. [3] Wang, Z. and Shang, X. Spatial pooling strategies for perceptual
image quality assessment. Proc. IEEE Inter. Conf. Image. Proc.
2945-2948.
"""
if not X.dtype == Y.dtype:
raise ValueError('Input images must have the same dtype.')
@@ -135,6 +142,10 @@ def structural_similarity(X, Y, win_size=None, gradient=False,
if not X.shape == Y.shape:
raise ValueError('Input images must have the same dimensions.')
if image_content_weighting and gradient:
raise ValueError(
"gradient not implemented for image content weighted case")
# default treats 3D arrays with shape[2] == 3 as multichannel
if multichannel is None:
if X.ndim == 3 and X.shape[2] == 3:
@@ -234,8 +245,15 @@ def structural_similarity(X, Y, win_size=None, gradient=False,
# to avoid edge effects will ignore filter radius strip around edges
pad = (win_size - 1) // 2
# compute mean of ssim
mssim = _discard_edges(S, pad).mean()
# compute (weighted) mean of ssim
if image_content_weighting:
# weight with Eq. 7 of Wang and Simoncelli 2006.
W = np.log((1 + vx / C2) * (1 + vy / C2))
W /= W.sum()
mssim = _discard_edges(S * W, pad).sum()
else:
mssim = _discard_edges(S, pad).mean()
if gradient:
# The following is Eqs. 7-8 of Avanaki 2009.
@@ -254,4 +272,3 @@ def structural_similarity(X, Y, win_size=None, gradient=False,
return mssim, S
else:
return mssim
@@ -143,6 +143,9 @@ def test_invalid_input():
assert_raises(ValueError, ssim, X, X, win_size=8)
# do not allow both image content weighting and gradient calculation
assert_raises(ValueError, ssim, X, X, image_content_weighting=True,
gradient=True)
if __name__ == "__main__":
np.testing.run_module_suite()