Add a helper function to check for low contrast

Add a helper function to check for low contrast

Add a check for low contrast when using imsave

Use the low contrast helper in imshow and make sure warnings are always shown

Clean up parameter names and add doctests

Remove unnecessary warning context

Remove unnecessary warning context

Add dtype ranges for 64bit types

Update tests with new warnings

Fix doctest logic

Fix doctest logic

Add a low contrast test with multiple dtypes

Fix check for color images

Fix color check again

Add support for int32 types

Relax assertion for 32bit builds

Add a low contrast test with multiple dtypes

Add a low contrast test with multiple dtypes

Fix check for color images

Fix color check again

Add support for int32 types
This commit is contained in:
Steven Silvester
2015-03-07 09:29:04 -06:00
parent 1712ee0722
commit 0e61374a89
9 changed files with 87 additions and 10 deletions
+4 -2
View File
@@ -1,6 +1,7 @@
from .exposure import histogram, equalize_hist, \
rescale_intensity, cumulative_distribution, \
adjust_gamma, adjust_sigmoid, adjust_log
adjust_gamma, adjust_sigmoid, adjust_log, \
is_low_contrast
from ._adapthist import equalize_adapthist
@@ -12,4 +13,5 @@ __all__ = ['histogram',
'cumulative_distribution',
'adjust_gamma',
'adjust_sigmoid',
'adjust_log']
'adjust_log',
'is_low_contrast']
+47 -1
View File
@@ -1,7 +1,8 @@
from __future__ import division
import warnings
import numpy as np
from .. import img_as_float
from ..color import rgb2gray
from ..util.dtype import dtype_range, dtype_limits
@@ -463,3 +464,48 @@ def adjust_sigmoid(image, cutoff=0.5, gain=10, inv=False):
out = (1 / (1 + np.exp(gain * (cutoff - image / scale)))) * scale
return dtype(out)
def is_low_contrast(image, fraction_threshold=0.05, lower_percentile=1,
upper_percentile=99, method='linear'):
"""Detemine if an image is low contrast.
Parameters
----------
image : array-like
The image under test.
fraction_threshold : float, optional
The low contrast fraction threshold.
lower_bound : float, optional
Disregard values below this percentile when computing image contrast.
upper_bound : float, optional
Disregard values above this percentile when computing image contrast.
method : str, optional
The contrast determination method. Right now the only available
option is "linear".
Returns
-------
out : bool
True when the image is determined to be low contrast.
Examples
--------
>>> image = np.linspace(0, 0.04, 100)
>>> is_low_contrast(image)
True
>>> image[-1] = 1
>>> is_low_contrast(image)
True
>>> is_low_contrast(image, upper_percentile=100)
False
"""
image = np.asanyarray(image)
if image.ndim == 3 and image.shape[2] in [3, 4]:
image = rgb2gray(image)
dlimits = dtype_limits(image)
limits = np.percentile(image, [lower_percentile, upper_percentile])
ratio = (limits[1] - limits[0]) / (dlimits[1] - dlimits[0])
return ratio < fraction_threshold
+16
View File
@@ -472,6 +472,22 @@ def test_negative():
assert_raises(ValueError, exposure.adjust_gamma, image)
def test_is_low_contrast():
image = np.linspace(0, 0.04, 100)
assert exposure.is_low_contrast(image)
image[-1] = 1
assert exposure.is_low_contrast(image)
assert not exposure.is_low_contrast(image, upper_percentile=100)
image = (image * 255).astype(np.uint8)
assert exposure.is_low_contrast(image)
assert not exposure.is_low_contrast(image, upper_percentile=100)
image = (image.astype(np.uint16)) * 2**8
assert exposure.is_low_contrast(image)
assert not exposure.is_low_contrast(image, upper_percentile=100)
if __name__ == '__main__':
from numpy import testing
testing.run_module_suite()
+5
View File
@@ -1,4 +1,5 @@
from io import BytesIO
import warnings
import numpy as np
import six
@@ -6,6 +7,8 @@ import six
from ..io.manage_plugins import call_plugin
from ..color import rgb2grey
from .util import file_or_url_context
from ..exposure import is_low_contrast
from .._shared._warnings import all_warnings
__all__ = ['Image', 'imread', 'imread_collection', 'imsave', 'imshow', 'show']
@@ -152,6 +155,8 @@ def imsave(fname, arr, plugin=None, **plugin_args):
Passed to the given plugin.
"""
if is_low_contrast(arr):
warnings.warn('%s is a low contrast image' % fname)
return call_plugin('imsave', fname, arr, plugin=plugin, **plugin_args)
+6 -4
View File
@@ -2,7 +2,9 @@ from collections import namedtuple
import numpy as np
import warnings
import matplotlib.pyplot as plt
from skimage.util import dtype as dtypes
from ...util import dtype as dtypes
from ...exposure import is_low_contrast
from ..._shared._warnings import all_warnings
_default_colormap = 'gray'
@@ -49,7 +51,7 @@ def _get_image_properties(image):
out_of_range_float = (np.issubdtype(image.dtype, np.float) and
(immin < lo or immax > hi))
low_dynamic_range = (immin != immax and
(float(immax - immin) / (hi - lo)) < (1. / 255))
is_low_contrast(image))
unsupported_dtype = image.dtype not in dtypes._supported_types
return ImageProperties(signed, out_of_range_float,
@@ -72,8 +74,8 @@ def _raise_warnings(image_properties):
warnings.warn("Low image dynamic range; displaying image with "
"stretched contrast.")
if ip.out_of_range_float:
warnings.warn("Float image out of standard range; displaying image "
"with stretched contrast.")
warnings.warn("Float image out of standard range; displaying "
"image with stretched contrast.")
def _get_display_range(image):
+2 -1
View File
@@ -87,7 +87,8 @@ def test_outside_standard_range():
def test_nonstandard_type():
plt.figure()
with expected_warnings(["Non-standard image type"]):
with expected_warnings(["Non-standard image type",
"Low image dynamic range"]):
ax_im = io.imshow(im64)
assert ax_im.get_clim() == (im64.min(), im64.max())
assert n_subplots(ax_im) == 2
+2 -1
View File
@@ -147,7 +147,8 @@ def test_imsave_filelike():
s = BytesIO()
# save to file-like object
with expected_warnings(['precision loss|unclosed file']):
with expected_warnings(['precision loss|unclosed file',
'is a low contrast image']):
imsave(s, image)
# read from file-like object
+1 -1
View File
@@ -26,7 +26,7 @@ INTENSITY_SAMPLE[1, 9:11] = 2
def test_all_props():
region = regionprops(SAMPLE, INTENSITY_SAMPLE)[0]
for prop in PROPS:
assert_equal(region[prop], getattr(region, PROPS[prop]))
assert_almost_equal(region[prop], getattr(region, PROPS[prop]))
def test_dtype():
+4
View File
@@ -11,6 +11,10 @@ dtype_range = {np.bool_: (False, True),
np.uint16: (0, 65535),
np.int8: (-128, 127),
np.int16: (-32768, 32767),
np.int64: (-2**63, 2**63 - 1),
np.uint64: (0, 2**64 - 1),
np.int32: (-2**31, 2**31 - 1),
np.uint32: (0, 2**32 - 1),
np.float32: (-1, 1),
np.float64: (-1, 1)}