Weird imsave inverting behaviour

154 Aufrufe
Direkt zur ersten ungelesenen Nachricht

Juan Nunez-Iglesias

ungelesen,
26.05.2013, 23:31:1426.05.13
an scikit...@googlegroups.com
Hey all,

I noticed that some of my microscopy images appeared inverted after saving them with skimage.io.imsave. After some testing, here's some of the weirdness. My image is called s:

```python
In [37]: np.min(s)
Out[37]: 119

In [38]: np.max(s)
Out[38]: 4095

In [39]: s.shape
Out[39]: (1040, 1392)

In [40]: s.dtype
Out[40]: dtype('uint16')

In [41]: io.imsave('/Users/nuneziglesiasj/Desktop/im.tif', s)

In [42]: sr = io.imread('/Users/nuneziglesiasj/Desktop/im.tif')

In [43]: (s == sr).all()
Out[43]: Image(False, dtype=bool)

In [44]: sr.min()
Out[44]: Image(0, dtype=uint8)

In [45]: sr.max()
Out[45]: Image(255, dtype=uint8)
```

Ok, already this is not desirable... One would hope than an imsave followed by an imread would be a no-op, but whatever, let's accept for argument's sake that we want to limit ourselves to uint8. Here's the real downer:

```python
In [46]: np.corrcoef(s.ravel(), sr.ravel())
Out[46]:
array([[ 1.        , -0.29849602],
       [-0.29849602,  1.        ]])
```

This is simply unacceptable. I haven't explored any more than this yet but maybe someone has an idea about what is going on here? If it helps, the problem is with imsave — opening the images in Apple Preview shows the inversion. I just wanted to know if it was some weird incompatibility between skimage and Preview, rather than skimage acting stupid. Sadly, it appears to be the latter.

PS: I just tested with png and get the exact same result.

Christoph Gohlke

ungelesen,
27.05.2013, 00:32:3727.05.13
an scikit...@googlegroups.com
> the problem is with imsave � opening the images in Apple Preview shows
> the inversion. I just wanted to know if it was some weird
> incompatibility between skimage and Preview, rather than skimage acting
> stupid. Sadly, it appears to be the latter.
>
> PS: I just tested with png and get the exact same result.
>

Not many skimage.io plugins are capable of handling 16 bit data. Use
gdal (read only), tifffile (uncompressed tiff only), or freeimage, e.g.
`io.use_plugin('freeimage')`

Christoph

Juan Nunez-Iglesias

ungelesen,
27.05.2013, 01:27:1027.05.13
an scikit...@googlegroups.com
OH. Right. That's what's happening, it's not inverted, it's looping around with the overflow! (I was wondering why the correlation was not closer to -1.)

Guh. imho:

- This really shouldn't happen. The plugin selection should be aware of the data type, and use only a plugin that can handle it (if available)
- PIL can definitely do 16bit PNG, so either it is being used incorrectly, or the imsave docstring stating that PIL is the first selection is wrong. I just tested this on my PIL-based Gala library, which is 3D so it required a bit of modification:

In [66]: imio.write_png_image_stack(s[np.newaxis, ...], '~/Desktop/im%02i.png', axis=0)

In [67]: srg = imio.read_image_stack('/Users/nuneziglesiasj/Desktop/im0*.png')

In [68]: srg.shape
Out[68]: (1040, 1392)

In [69]: (s == srg).all()
Out[69]: True

- The IO module is a mess! I know Stefan mentioned overhauling it briefly, but I didn't quite realise how urgent that was. In particular: 
   - is `from blah import *` used as a matter of policy or is it a remnant of an earlier age? Took me ages to find the `call` function.
   - `plugin_store`? I have no idea where this gets updated.

So, to the core skimage devs: what is the scope for updating this? Am I allowed to break some functionality in a PR? Or are we sticking with this API?


the problem is with imsave — opening the images in Apple Preview shows

the inversion. I just wanted to know if it was some weird
incompatibility between skimage and Preview, rather than skimage acting
stupid. Sadly, it appears to be the latter.

PS: I just tested with png and get the exact same result.

Not many skimage.io plugins are capable of handling 16 bit data. Use gdal (read only), tifffile (uncompressed tiff only), or freeimage, e.g. `io.use_plugin('freeimage')`


Christoph

--
You received this message because you are subscribed to the Google Groups "scikit-image" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scikit-image+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



Johannes Schönberger

ungelesen,
27.05.2013, 02:51:5927.05.13
an scikit...@googlegroups.com
To be honest I agree, right now it is a mess, which is also the reason why I have not touched this package yet. Things I noticed:

- depending on the plugin, the code and comment / doc string quality should be improved
- what's the purpose of _colormixer.pyx, _histogram.pyx, q_histogram.py, q_color_mixer.py etc. and why are they in the io plugin directory?
- the way plugins are managed should be overhauled and we should discuss it together before implementation

My ideas:

- rather than having .ini files I would opt for `register(plugin, desc, funcs, setup_func, *args, **kwargs)` and `unregister(plugin)` functions. This enables also users to add new plugins at runtime.

- `setup_func` should check whether the plugin is available on this system.

- what is indicated as `args` and `kwargs` above should definitely contain two more things: an explicit whitelist of supported file formats, extensions and dtypes or an explicit blacklist of file formats, extensions and dtypes. This could be represented as a dictionary:

{['png']: ['uint8', 'float', '…'], ['tif', 'tiff']: … }

It allows us to automatically select an available plugin for the given data or raise an error.

- Explicitly selecting a plugin should be possible through an extra argument to `imread`, `imsave`. E.g. `imsave(file, data, plugin='freeimage')`.




Johannes Schönberger
> To unsubscribe from this group and stop receiving emails from it, send an email to scikit-image...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>
>
> --
> You received this message because you are subscribed to the Google Groups "scikit-image" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to scikit-image...@googlegroups.com.

Ronnie Ghose

ungelesen,
27.05.2013, 02:55:0127.05.13
an scikit...@googlegroups.com
while we're on the subject, it seems algorithms / arrays are mixing using / wanting as input,  [0,1] and [0,256] for grayscale, which leads to unexpected results

Ronnie Ghose

ungelesen,
27.05.2013, 02:56:1127.05.13
an scikit...@googlegroups.com
can we just standardize it so that _everything_ uses one of the two representations? If an algorithm needs it differently, it can do the 256*array or array/256 and then again output this standard format

Johannes Schönberger

ungelesen,
27.05.2013, 03:02:1027.05.13
an scikit...@googlegroups.com
IMO the convention is to use double ([0, 1]) everywhere, except in rare cases…?

Johannes Schönberger

Ronnie Ghose

ungelesen,
27.05.2013, 03:03:3427.05.13
an scikit...@googlegroups.com
Can I add that in the docs somewhere? hmm... the question is where should general guidelines go....

Johannes Schönberger

ungelesen,
27.05.2013, 03:29:1027.05.13
an scikit...@googlegroups.com
`CONTRIBUTING.txt`

Johannes Schönberger

Juan Nunez-Iglesias

ungelesen,
27.05.2013, 03:36:3727.05.13
an scikit...@googlegroups.com
Well, [0, 1] is great for working, but useless for saving. So what should the convention be for saving? And should we use single or double precision floats? I think in general it's hard to choose for users, and the best thing is to try to preserve user input type unless there's a good reason not to do so.

Note that 16 bit grayscale images are fairly common, so assuming uint8 for the output is a no-no.

Johannes Schönberger

ungelesen,
27.05.2013, 03:49:1827.05.13
an scikit...@googlegroups.com
I was just talking of functions… io should always preserve the input data type and range.

Johannes Schönberger

Stéfan van der Walt

ungelesen,
27.05.2013, 05:35:4527.05.13
an scikit-image
On Mon, May 27, 2013 at 8:51 AM, Johannes Schönberger
<jschoe...@demuc.de> wrote:
>
> - depending on the plugin, the code and comment / doc string quality should be improved
> - what's the purpose of _colormixer.pyx, _histogram.pyx, q_histogram.py, q_color_mixer.py etc. and why are they in the io plugin directory?

These are used in the fancy QT image viewer, i.e. "imshow(image, fancy=True)".

> - the way plugins are managed should be overhauled and we should discuss it together before implementation
>
> My ideas:
>
> - rather than having .ini files I would opt for `register(plugin, desc, funcs, setup_func, *args, **kwargs)` and `unregister(plugin)` functions. This enables also users to add new plugins at runtime.

This sounds very similar to the ideas mentioned by Almar Klein earlier
this month:

https://groups.google.com/d/msg/imageio/jNwYY6B8n7Y/svdUiYWA4mMJ

Unfortunately, there's a trade-off between having things "just work"
and the amount of magic that happens behind the scene. When starting
scikit-image, we set it as a priority that a person should be able to
do ``imread(...)`` on almost any system and have it work. I think
this was an important requirement for having demos Just Work.

> - what is indicated as `args` and `kwargs` above should definitely contain two more things: an explicit whitelist of supported file formats, extensions and dtypes or an explicit blacklist of file formats, extensions and dtypes. This could be represented as a dictionary:
>
> {['png']: ['uint8', 'float', '…'], ['tif', 'tiff']: … }
>
> It allows us to automatically select an available plugin for the given data or raise an error.

Having formats and data-types specified is a good idea. It can also
be done using the ini-file format, but I'd prefer the approach you
suggest. That said, let me motivate those configuration files: the
idea was that one could add plugins by simply dropping the appropriate
files in-place. However, the right place for those plugins to live
would probably be inside the skimage repository, so it doesn't matters
that much.

> - Explicitly selecting a plugin should be possible through an extra argument to `imread`, `imsave`. E.g. `imsave(file, data, plugin='freeimage')`.

Just verifying that this is the way it currently functions.

Stéfan

Stéfan van der Walt

ungelesen,
27.05.2013, 05:37:4327.05.13
an scikit-image
On Mon, May 27, 2013 at 9:03 AM, Ronnie Ghose <ronnie...@gmail.com> wrote:
> Can I add that in the docs somewhere? hmm... the question is where should
> general guidelines go....

http://scikit-image.org/docs/dev/user_guide/data_types.html


Our policy is: anything in, whatever the algorithm prefers out. The
data type determines the range:

float : [-1, 1] or [0, 1]
uint8: [0, 255]

Stéfan

Juan Nunez-Iglesias

ungelesen,
27.05.2013, 09:08:2727.05.13
an scikit...@googlegroups.com
@stefanv

On Mon, May 27, 2013 at 7:35 PM, Stéfan van der Walt <ste...@sun.ac.za> wrote:
Unfortunately, there's a trade-off between having things "just work"
and the amount of magic that happens behind the scene.  

I think you have the right approach, ie imread() should just work. However, what started this post is that it doesn't. =) 

Stéfan van der Walt

ungelesen,
27.05.2013, 09:48:4627.05.13
an scikit-image
On Mon, May 27, 2013 at 3:08 PM, Juan Nunez-Iglesias <jni....@gmail.com> wrote:
> I think you have the right approach, ie imread() should just work. However,
> what started this post is that it doesn't. =)

Yes, that's a bug and should be fixed.

Stéfan

Johannes Schönberger

ungelesen,
05.06.2013, 02:57:2305.06.13
an scikit...@googlegroups.com
What's the status of this discussion? Do we want to tackle this?

Johannes Schönberger

Juan Nunez-Iglesias

ungelesen,
05.06.2013, 04:15:2105.06.13
an scikit...@googlegroups.com
I'd argue yes. ;) But I'm not sure any hard conclusions were reached as to what exactly needs to be done. I guess the first thing is fixing the TIFF input bug, before any more refactoring. But that might go away in a refactor anyway...

Stéfan van der Walt

ungelesen,
10.07.2013, 07:39:0310.07.13
an scikit-image
On Wed, Jun 5, 2013 at 10:15 AM, Juan Nunez-Iglesias <jni....@gmail.com> wrote:
> I'd argue yes. ;) But I'm not sure any hard conclusions were reached as to
> what exactly needs to be done. I guess the first thing is fixing the TIFF
> input bug, before any more refactoring. But that might go away in a refactor
> anyway...

We need to a) refactor the I/O infrastructure which b) should allow
plugins to describe their supported functionality.

Another option would be to get rid of plugins, and to provide a
directory of snippets that illustrate how to load various other file
formats with skimage.

Stéfan

Juan Nunez-Iglesias

ungelesen,
11.07.2013, 05:45:3711.07.13
an scikit...@googlegroups.com
I'd be interested in tackling this, but a number of alternatives were proposed, including my io.png.read() and Johannes's plugin registry thingy, with no clear decision on which way to go...



Stéfan

Stéfan van der Walt

ungelesen,
11.07.2013, 06:09:1411.07.13
an scikit-image
On Thu, Jul 11, 2013 at 11:45 AM, Juan Nunez-Iglesias
<jni....@gmail.com> wrote:
> I'd be interested in tackling this, but a number of alternatives were
> proposed, including my io.png.read() and Johannes's plugin registry thingy,
> with no clear decision on which way to go...

We can refactor the current infrastructure without changing the
API--that would be a good start.

Stéfan
Allen antworten
Antwort an Autor
Weiterleiten
0 neue Nachrichten