mirror of
https://github.com/wassname/scikit-image.git
synced 2026-06-27 19:48:43 +08:00
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:
@@ -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']
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user