mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-18 12:40:14 +08:00
Overhaul imshow to clarify flow
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
from collections import namedtuple
|
||||
import numpy as np
|
||||
import warnings
|
||||
import matplotlib.pyplot as plt
|
||||
@@ -9,6 +10,106 @@ _nonstandard_colormap = 'cubehelix'
|
||||
_diverging_colormap = 'RdBu'
|
||||
|
||||
|
||||
ImageProperties = namedtuple('ImageProperties',
|
||||
['signed', 'out_of_range_float',
|
||||
'low_dynamic_range', 'unsupported_dtype'])
|
||||
|
||||
|
||||
def _get_image_properties(image):
|
||||
"""Determine nonstandard properties of an input image.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : array
|
||||
The input image.
|
||||
|
||||
Returns
|
||||
-------
|
||||
ip : ImageProperties named tuple
|
||||
The properties of the image:
|
||||
|
||||
- signed: whether the image has negative values.
|
||||
- out_of_range_float: if the image has floating point data
|
||||
outside of [-1, 1].
|
||||
- low_dynamic_range: if the image is in the standard image
|
||||
range (e.g. [0, 1] for a floating point image) but its
|
||||
dynamic range would be too small to display with standard
|
||||
image ranges.
|
||||
- unsupported_dtype: if the image data type is not a
|
||||
standard skimage type, e.g. ``numpy.uint64``.
|
||||
"""
|
||||
immin, immax = np.min(image), np.max(image)
|
||||
imtype = image.dtype.type
|
||||
try:
|
||||
lo, hi = dtypes.dtype_range[imtype]
|
||||
except KeyError:
|
||||
lo, hi = immin, immax
|
||||
|
||||
signed = immin < 0
|
||||
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))
|
||||
unsupported_dtype = image.dtype not in dtypes._supported_types
|
||||
|
||||
ip = ImageProperties(signed, out_of_range_float,
|
||||
low_dynamic_range, unsupported_dtype)
|
||||
return ip
|
||||
|
||||
|
||||
def _raise_warnings(image_properties):
|
||||
"""Raise the appropriate warning for each nonstandard image type.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image_properties : ImageProperties named tuple
|
||||
The properties of the considered image.
|
||||
"""
|
||||
ip = image_properties
|
||||
if ip.unsupported_dtype:
|
||||
warnings.warn("Non-standard image type; displaying image with "
|
||||
"stretched contrast.")
|
||||
if ip.low_dynamic_range:
|
||||
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.")
|
||||
|
||||
|
||||
def _get_display_range(image):
|
||||
"""Return the display range for a given set of image properties.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : array
|
||||
The input image.
|
||||
|
||||
Returns
|
||||
-------
|
||||
lo, hi : same type as immin, immax
|
||||
The display range to be used for the input image.
|
||||
cmap : string
|
||||
The name of the colormap to use.
|
||||
"""
|
||||
ip = _get_image_properties(image)
|
||||
immin, immax = np.min(image), np.max(image)
|
||||
if ip.signed:
|
||||
magnitude = max(abs(immin), abs(immax))
|
||||
lo, hi = -magnitude, magnitude
|
||||
cmap = _diverging_colormap
|
||||
elif any(ip):
|
||||
_raise_warnings(ip)
|
||||
lo, hi = immin, immax
|
||||
cmap = _nonstandard_colormap
|
||||
else:
|
||||
lo = 0
|
||||
imtype = image.dtype.type
|
||||
hi = dtypes.dtype_range[imtype][1]
|
||||
cmap = _default_colormap
|
||||
return lo, hi, cmap
|
||||
|
||||
|
||||
def imshow(im, *args, **kwargs):
|
||||
"""Show the input image and return the current axes.
|
||||
|
||||
@@ -37,41 +138,13 @@ def imshow(im, *args, **kwargs):
|
||||
"""
|
||||
if plt.gca().has_data():
|
||||
plt.figure()
|
||||
immin, immax = np.min(im), np.max(im)
|
||||
lo, hi = immin, immax
|
||||
cmap = _default_colormap
|
||||
supported_dtype = im.dtype in dtypes._supported_types
|
||||
if supported_dtype:
|
||||
lo, hi = dtypes.dtype_range[im.dtype.type]
|
||||
# for nonnegative float images, ensure lower bound is 0, not -1
|
||||
if immin > 0:
|
||||
lo = 0
|
||||
# for signed images, show diverging colormap centered at 0
|
||||
else:
|
||||
cmap = _diverging_colormap
|
||||
magnitude = max(-immin, abs(immax))
|
||||
lo, hi = -magnitude, magnitude
|
||||
else:
|
||||
warnings.warn("Non-standard image type; displaying image with "
|
||||
"stretched contrast.")
|
||||
out_of_range_float = (np.issubdtype(im.dtype, np.float) and
|
||||
(immin < lo or immax > hi))
|
||||
if out_of_range_float:
|
||||
warnings.warn("Float image out of standard range; displaying image "
|
||||
"with stretched contrast.")
|
||||
low_dynamic_range = (immin != immax and
|
||||
(float(immax - immin) / (hi - lo)) < (1. / 255))
|
||||
if low_dynamic_range:
|
||||
warnings.warn("Low image dynamic range; displaying image with "
|
||||
"stretched contrast.")
|
||||
if not supported_dtype or out_of_range_float or low_dynamic_range:
|
||||
cmap = _nonstandard_colormap
|
||||
lo, hi, cmap = _get_display_range(im)
|
||||
kwargs.setdefault('interpolation', 'nearest')
|
||||
kwargs.setdefault('cmap', cmap)
|
||||
kwargs.setdefault('vmin', lo)
|
||||
kwargs.setdefault('vmax', hi)
|
||||
ax_im = plt.imshow(im, *args, **kwargs)
|
||||
if not supported_dtype or out_of_range_float or low_dynamic_range:
|
||||
if cmap != _default_colormap:
|
||||
plt.colorbar()
|
||||
return ax_im
|
||||
|
||||
|
||||
Reference in New Issue
Block a user