crashes when showing binary images

Hey scikit-image friends,

some of my teaching notebooks recently broke. Suddenly, the imshow function in scikit-image can’t show binary images anymore. Does anybody have an idea what we could do (change dependency versions? change code?) to make them run again?

Here is the code (and that’s the data):

from import imshow, imread

image = imread("blobs.tif")

from skimage import filters
threshold = filters.threshold_otsu(image)

binary_image = image >= threshold


That error pops up in the last line:

TypeError                                 Traceback (most recent call last)
<ipython-input-3-94950852c6d3> in <module>
      1 binary_image = image >= threshold
----> 3 imshow(binary_image)

~\miniconda3\envs\bio\lib\site-packages\skimage\io\ in imshow(arr, plugin, **plugin_args)
    157     if isinstance(arr, str):
    158         arr = call_plugin('imread', arr, plugin=plugin)
--> 159     return call_plugin('imshow', arr, plugin=plugin, **plugin_args)

~\miniconda3\envs\bio\lib\site-packages\skimage\io\ in call_plugin(kind, *args, **kwargs)
    205                                (plugin, kind))
--> 207     return func(*args, **kwargs)

~\miniconda3\envs\bio\lib\site-packages\skimage\io\_plugins\ in imshow(image, ax, show_cbar, **kwargs)
    148     import matplotlib.pyplot as plt
--> 150     lo, hi, cmap = _get_display_range(image)
    152     kwargs.setdefault('interpolation', 'nearest')

~\miniconda3\envs\bio\lib\site-packages\skimage\io\_plugins\ in _get_display_range(image)
     95         The name of the colormap to use.
     96     """
---> 97     ip = _get_image_properties(image)
     98     immin, immax = np.min(image), np.max(image)
     99     if ip.signed:

~\miniconda3\envs\bio\lib\site-packages\skimage\io\_plugins\ in _get_image_properties(image)
     53                           (immin < lo or immax > hi))
     54     low_data_range = (immin != immax and
---> 55                       is_low_contrast(image))
     56     unsupported_dtype = image.dtype not in dtypes._supported_types

~\miniconda3\envs\bio\lib\site-packages\skimage\exposure\ in is_low_contrast(image, fraction_threshold, lower_percentile, upper_percentile, method)
    650     dlimits = dtype_limits(image, clip_negative=False)
--> 651     limits = np.percentile(image, [lower_percentile, upper_percentile])
    652     ratio = (limits[1] - limits[0]) / (dlimits[1] - dlimits[0])

<__array_function__ internals> in percentile(*args, **kwargs)

~\miniconda3\envs\bio\lib\site-packages\numpy\lib\ in percentile(a, q, axis, out, overwrite_input, interpolation, keepdims)
   3816     if not _quantile_is_valid(q):
   3817         raise ValueError("Percentiles must be in the range [0, 100]")
-> 3818     return _quantile_unchecked(
   3819         a, q, axis, out, overwrite_input, interpolation, keepdims)

~\miniconda3\envs\bio\lib\site-packages\numpy\lib\ in _quantile_unchecked(a, q, axis, out, overwrite_input, interpolation, keepdims)
   3935                         interpolation='linear', keepdims=False):
   3936     """Assumes that q is in [0, 1], and is an ndarray"""
-> 3937     r, k = _ureduce(a, func=_quantile_ureduce_func, q=q, axis=axis, out=out,
   3938                     overwrite_input=overwrite_input,
   3939                     interpolation=interpolation)

~\miniconda3\envs\bio\lib\site-packages\numpy\lib\ in _ureduce(a, func, **kwargs)
   3513         keepdim = (1,) * a.ndim
-> 3515     r = func(a, **kwargs)
   3516     return r, keepdim

~\miniconda3\envs\bio\lib\site-packages\numpy\lib\ in _quantile_ureduce_func(***failed resolving arguments***)
   4062         x_above = take(ap, indices_above, axis=0)
-> 4064         r = _lerp(x_below, x_above, weights_above, out=out)
   4066     # if any slice contained a nan, then all results on that slice are also nan

~\miniconda3\envs\bio\lib\site-packages\numpy\lib\ in _lerp(a, b, t, out)
   3959 def _lerp(a, b, t, out=None):
   3960     """ Linearly interpolate from a to b by a factor of t """
-> 3961     diff_b_a = subtract(b, a)
   3962     # asanyarray is a stop-gap until gh-13105
   3963     lerp_interpolation = asanyarray(add(a, diff_b_a*t, out=out))

TypeError: numpy boolean subtract, the `-` operator, is not supported, use the bitwise_xor, the `^` operator, or the logical_xor function instead.

Any hint is appreciated!


You should prefer:

import matplotlib.pyplot as plt


We will probably deprecate in the not-too-distant future. The reason it exists is that a long time ago, matplotlib’s imshow defaulted to the jet colormap, which is terrible. Now that matplotlib defaults to viridis, it no longer has a reason to exist.

If you must get it to work for binary images, the trick is to revert your NumPy version to one before they deprecated bool_arr1 - bool_arr2. (I forget what number that is.) But as you can see, it was sort of a coincidence that worked at all with binary images…

1 Like

Awesome @jni , I was aready suspecting that matplotlib is the right tool of choice here but wasn’t sure. Thanks for the light-speed support and have a great weekend!


Still, it sounds like something we can easily detect and fix; at least until we remove our own viewers.