FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Floating point image RGB values must be in the 0..1 range · Issue #10372 · matplotlib/matplotlib · GitHub

Repository navigation

Floating point image RGB values must be in the 0..1 range #10372

Description

Bug report

Bug summary
From matplorlib 2.0 to 2.1 this problem appeared: Floating point image RGB values must be in the 0..1 range, instead of producing an image with noise on it.

Code for reproduction
Can use any image to try to reproduce this problem:

import imageio
import numpy as np
from matplotlib.pyplot import imshow
%matplotlib inline

image_file="image.jpg"
content_image = imageio.imread(image_file)
#imshow(content_image)

noise_ratio = 0.6
image_height, image_width, color_channels = content_image.shape
noise_image = np.random.uniform(-20, 20, (1, image_height, image_width, color_channels)).astype('float32')
input_image = noise_image * noise_ratio + content_image * (1 - noise_ratio)
imshow(input_image[0])

Actual outcome

<matplotlib.image.AxesImage at 0x7fad8700b748>
Error in callback <function install_repl_displayhook.<locals>.post_execute at 0x7fad44bbb510> (for post_execute):
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~/.local/lib/python3.5/site-packages/matplotlib/pyplot.py in post_execute()
    147             def post_execute():
    148                 if matplotlib.is_interactive():
--> 149                     draw_all()
    150 
    151             # IPython >= 2

~/.local/lib/python3.5/site-packages/matplotlib/_pylab_helpers.py in draw_all(cls, force)
    134         for f_mgr in cls.get_all_fig_managers():
    135             if force or f_mgr.canvas.figure.stale:
--> 136                 f_mgr.canvas.draw_idle()
    137 
    138 atexit.register(Gcf.destroy_all)

~/.local/lib/python3.5/site-packages/matplotlib/backend_bases.py in draw_idle(self, *args, **kwargs)
   2053         if not self._is_idle_drawing:
   2054             with self._idle_draw_cntx():
-> 2055                 self.draw(*args, **kwargs)
   2056 
   2057     def draw_cursor(self, event):

~/.local/lib/python3.5/site-packages/matplotlib/backends/backend_agg.py in draw(self)
    429             # if toolbar:
    430             #     toolbar.set_cursor(cursors.WAIT)
--> 431             self.figure.draw(self.renderer)
    432         finally:
    433             # if toolbar:

~/.local/lib/python3.5/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     53                 renderer.start_filter()
     54 
---> 55             return draw(artist, renderer, *args, **kwargs)
     56         finally:
     57             if artist.get_agg_filter() is not None:

~/.local/lib/python3.5/site-packages/matplotlib/figure.py in draw(self, renderer)
   1473 
   1474             mimage._draw_list_compositing_images(
-> 1475                 renderer, self, artists, self.suppressComposite)
   1476 
   1477             renderer.close_group('figure')

~/.local/lib/python3.5/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    136     if not_composite or not has_images:
    137         for a in artists:
--> 138             a.draw(renderer)
    139     else:
    140         # Composite any adjacent images together

~/.local/lib/python3.5/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     53                 renderer.start_filter()
     54 
---> 55             return draw(artist, renderer, *args, **kwargs)
     56         finally:
     57             if artist.get_agg_filter() is not None:

~/.local/lib/python3.5/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe)
   2579             renderer.stop_rasterizing()
   2580 
-> 2581         mimage._draw_list_compositing_images(renderer, self, artists)
   2582 
   2583         renderer.close_group('axes')

~/.local/lib/python3.5/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    136     if not_composite or not has_images:
    137         for a in artists:
--> 138             a.draw(renderer)
    139     else:
    140         # Composite any adjacent images together

~/.local/lib/python3.5/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     53                 renderer.start_filter()
     54 
---> 55             return draw(artist, renderer, *args, **kwargs)
     56         finally:
     57             if artist.get_agg_filter() is not None:

~/.local/lib/python3.5/site-packages/matplotlib/image.py in draw(self, renderer, *args, **kwargs)
    566         else:
    567             im, l, b, trans = self.make_image(
--> 568                 renderer, renderer.get_image_magnification())
    569             if im is not None:
    570                 renderer.draw_image(gc, l, b, im)

~/.local/lib/python3.5/site-packages/matplotlib/image.py in make_image(self, renderer, magnification, unsampled)
    793         return self._make_image(
    794             self._A, bbox, transformed_bbox, self.axes.bbox, magnification,
--> 795             unsampled=unsampled)
    796 
    797     def _check_unsampled_image(self, renderer):

~/.local/lib/python3.5/site-packages/matplotlib/image.py in _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification, unsampled, round_to_pixel_border)
    484             # (of int or float)
    485             # or an RGBA array of re-sampled input
--> 486             output = self.to_rgba(output, bytes=True, norm=False)
    487             # output is now a correctly sized RGBA array of uint8
    488 

~/.local/lib/python3.5/site-packages/matplotlib/cm.py in to_rgba(self, x, alpha, bytes, norm)
    254                 if xx.dtype.kind == 'f':
    255                     if norm and xx.max() > 1 or xx.min() < 0:
--> 256                         raise ValueError("Floating point image RGB values "
    257                                          "must be in the 0..1 range.")
    258                     if bytes:

ValueError: Floating point image RGB values must be in the 0..1 range.
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/usr/local/lib/python3.5/dist-packages/IPython/core/formatters.py in __call__(self, obj)
    339                 pass
    340             else:
--> 341                 return printer(obj)
    342             # Finally look for special method names
    343             method = get_real_method(obj, self.print_method)

/usr/local/lib/python3.5/dist-packages/IPython/core/pylabtools.py in <lambda>(fig)
    236 
    237     if 'png' in formats:
--> 238         png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
    239     if 'retina' in formats or 'png2x' in formats:
    240         png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))

/usr/local/lib/python3.5/dist-packages/IPython/core/pylabtools.py in print_figure(fig, fmt, bbox_inches, **kwargs)
    120 
    121     bytes_io = BytesIO()
--> 122     fig.canvas.print_figure(bytes_io, **kw)
    123     data = bytes_io.getvalue()
    124     if fmt == 'svg':

~/.local/lib/python3.5/site-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, **kwargs)
   2210                     orientation=orientation,
   2211                     dryrun=True,
-> 2212                     **kwargs)
   2213                 renderer = self.figure._cachedRenderer
   2214                 bbox_inches = self.figure.get_tightbbox(renderer)

~/.local/lib/python3.5/site-packages/matplotlib/backends/backend_agg.py in print_png(self, filename_or_obj, *args, **kwargs)
    506 
    507     def print_png(self, filename_or_obj, *args, **kwargs):
--> 508         FigureCanvasAgg.draw(self)
    509         renderer = self.get_renderer()
    510         original_dpi = renderer.dpi

~/.local/lib/python3.5/site-packages/matplotlib/backends/backend_agg.py in draw(self)
    429             # if toolbar:
    430             #     toolbar.set_cursor(cursors.WAIT)
--> 431             self.figure.draw(self.renderer)
    432         finally:
    433             # if toolbar:

~/.local/lib/python3.5/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     53                 renderer.start_filter()
     54 
---> 55             return draw(artist, renderer, *args, **kwargs)
     56         finally:
     57             if artist.get_agg_filter() is not None:

~/.local/lib/python3.5/site-packages/matplotlib/figure.py in draw(self, renderer)
   1473 
   1474             mimage._draw_list_compositing_images(
-> 1475                 renderer, self, artists, self.suppressComposite)
   1476 
   1477             renderer.close_group('figure')

~/.local/lib/python3.5/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    136     if not_composite or not has_images:
    137         for a in artists:
--> 138             a.draw(renderer)
    139     else:
    140         # Composite any adjacent images together

~/.local/lib/python3.5/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     53                 renderer.start_filter()
     54 
---> 55             return draw(artist, renderer, *args, **kwargs)
     56         finally:
     57             if artist.get_agg_filter() is not None:

~/.local/lib/python3.5/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe)
   2579             renderer.stop_rasterizing()
   2580 
-> 2581         mimage._draw_list_compositing_images(renderer, self, artists)
   2582 
   2583         renderer.close_group('axes')

~/.local/lib/python3.5/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    136     if not_composite or not has_images:
    137         for a in artists:
--> 138             a.draw(renderer)
    139     else:
    140         # Composite any adjacent images together

~/.local/lib/python3.5/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     53                 renderer.start_filter()
     54 
---> 55             return draw(artist, renderer, *args, **kwargs)
     56         finally:
     57             if artist.get_agg_filter() is not None:

~/.local/lib/python3.5/site-packages/matplotlib/image.py in draw(self, renderer, *args, **kwargs)
    566         else:
    567             im, l, b, trans = self.make_image(
--> 568                 renderer, renderer.get_image_magnification())
    569             if im is not None:
    570                 renderer.draw_image(gc, l, b, im)

~/.local/lib/python3.5/site-packages/matplotlib/image.py in make_image(self, renderer, magnification, unsampled)
    793         return self._make_image(
    794             self._A, bbox, transformed_bbox, self.axes.bbox, magnification,
--> 795             unsampled=unsampled)
    796 
    797     def _check_unsampled_image(self, renderer):

~/.local/lib/python3.5/site-packages/matplotlib/image.py in _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification, unsampled, round_to_pixel_border)
    484             # (of int or float)
    485             # or an RGBA array of re-sampled input
--> 486             output = self.to_rgba(output, bytes=True, norm=False)
    487             # output is now a correctly sized RGBA array of uint8
    488 

~/.local/lib/python3.5/site-packages/matplotlib/cm.py in to_rgba(self, x, alpha, bytes, norm)
    254                 if xx.dtype.kind == 'f':
    255                     if norm and xx.max() > 1 or xx.min() < 0:
--> 256                         raise ValueError("Floating point image RGB values "
    257                                          "must be in the 0..1 range.")
    258                     if bytes:

ValueError: Floating point image RGB values must be in the 0..1 range.
<Figure size 432x288 with 1 Axes>

Expected outcome

In matplotlib==2.0.2 and previous this code generates a image with some noise applied to it.

In matplotlib=2.1.x the error above appear.

Matplotlib version

  • Operating system: ubuntu 16.04
  • Matplotlib version: 2.1.X
  • Matplotlib backend (print(matplotlib.get_backend())): module://ipykernel.pylab.backend_inline
  • Python version: 3.5.2
  • Jupyter version (if applicable): Jupyterlab==0.30.6
  • Other libraries:

    numpy==1.14.0
    imageio==2.2.0

The libraries are installed in pure python via pip install. I also build from the source to test if a recent unreleased version had this problem solved this but also got the same output.

Activity

  1. jklymak commented on Feb 2, 2018

    Member

    I think #10220 addresses this by clipping, but its not merged yet

  2. ImportanceOfBeingErnest commented on Feb 3, 2018

    Member

    This error needs to be seen as a feature. It tells the user that what he is supplying to imshow is not a valid RGB image, because it has values outside of the range [0.,1.] in it.

    Since there are essentially a multitude of possible "desired outcomes" when supplying such an array (e.g. should the array be normalized, should each channel be normalized, should it be clipped?) it should be the user's responsibility to create a valid RGB(A) image from the array.

    I guess the documentation is already quite clear, saying

    The value for each component of MxNx3 and MxNx4 float arrays should be in the range 0.0 to 1.0.

    although one might change "should" to "must" if people feel like it is not precise enough.

  3. cyberwillis commented on Feb 3, 2018

    Author

    [UPDATED]

    I appreciate your answer but In any case in the earlier version of matplotlib the same documentation point this out and worked nice. But changing the version from matplotlib==2.0.2 to 2.1.x stopped to work. To me is clear that is a bug.

    In case I pass a uniform distribution (from NEGATIVE to POSITIVE) it not works but if I pass a distribution (from ZERO to INFINITY) it should ? where the constrain about 0 to 1 is happening here ?

    ### THIS DONT WORK 
    np.random.uniform(-1, 200000000, (1, image_height, image_width, color_channels))
    
    ### THIS WORK 
    np.random.uniform(0, 200000000, (1, image_height, image_width, color_channels))
    
    
  4. jklymak commented on Feb 3, 2018

    Member

    The converse could also be considered true if you are of the camp that the user must supply valid inputs: it was a bug before 2.1.x that got fixed. Anyway, this is duplicate of #10220 so feel free to comment on the proposed new behaviour there. Or if I'm mistaken and this is actually not a duplicate, please feel free to ask that it is re-opened.

  5. ImportanceOfBeingErnest commented on Feb 3, 2018

    Member

    Sorry, my point is that the fact that it used to work was a bug, which is now repaired by throwing the correct error if invalid RGBA image is passed onto imshow. From some yet-to-be released version on, there will be a warning, instead of an error in such cases, as seen in the duplicate.

  6. cyberwillis commented on Feb 3, 2018

    Author

    Thank you all for your explanations. Looking forward to see the fix in the future release.

  7. ImportanceOfBeingErnest commented on Feb 3, 2018

    Member

    @cyberwillis You are correct, the case where the input array range is strictly positive and exceeds 1, e.g. [0.,200000000.] should not be supported either. With the linked fix, it will throw a warning as well.

    In any case, you need to make sure that your array is in the range between [0.,1.] to be correctly shown as image. With the fix in place you will equally be forced to do that, so there is actually no reason to be looking forward to it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL