Skip to content

Commit ab6e305

Browse files
committed
Clip invalid values in RGB imshow to bounds
1 parent 18b6b06 commit ab6e305

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

doc/users/next_whats_new/2018_01_11_imshow-rgb-scaling-clipping.rst

+4
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@
44
`Axes.imshow` can now apply the ``norm`` or ``vmin`` and ``vmax`` arguments
55
to RGB images, allowing easy display of high-bit-depth data, or adjustments
66
of brightness and contrast.
7+
8+
Out-of-range values in un-normalised RGB and RGBA images are now clipped to
9+
the nearest bound, rather than being wrapped. This bug often hid outliers,
10+
and could make interpretation of the plotted image entirely unreliable.

lib/matplotlib/axes/_axes.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -5237,7 +5237,7 @@ def imshow(self, X, cmap=None, norm=None, aspect=None,
52375237
Elements of RGB and RGBA arrays represent pixels of an MxN image.
52385238
All values - unless normalised with `norm` or `vmin` and `vmax` -
52395239
should be in the range [0 .. 1] for floats or [0 .. 255] for
5240-
integers.
5240+
integers. Out-of-range values will be clipped to these bounds.
52415241
52425242
cmap : `~matplotlib.colors.Colormap`, optional, default: None
52435243
If None, default to rc `image.cmap` value. `cmap` is ignored
@@ -5362,6 +5362,20 @@ def imshow(self, X, cmap=None, norm=None, aspect=None,
53625362
# Disable later styling based on these values
53635363
norm, vmin, vmax = None, None, None
53645364

5365+
# If the input data has values outside the valid range (after
5366+
# normalisation), we issue a warning and then clip X to the bounds
5367+
# - otherwise casting wraps extreme values, hiding outliers and
5368+
# making reliable interpretation impossible.
5369+
high_bound = 255 if np.issubdtype(X.dtype, np.integer) else 1
5370+
if X.min() < 0 or high_bound < X.max():
5371+
warnings.warn(
5372+
'Clipping input data to the valid range for imshow with '
5373+
'RGB data ([0..1] for floats or [0..255] for integers). '
5374+
'Pass the `norm`, `vmin`, or `vmax` arguments to avoid '
5375+
'this error.'
5376+
)
5377+
X = np.clip(X, 0, high_bound)
5378+
53655379
im = mimage.AxesImage(self, cmap, norm, interpolation, origin, extent,
53665380
filternorm=filternorm, filterrad=filterrad,
53675381
resample=resample, **kwargs)

0 commit comments

Comments
 (0)