Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not loading properly EXR file #356

Open
Overdrivr opened this issue Jun 25, 2018 · 24 comments
Open

Not loading properly EXR file #356

Overdrivr opened this issue Jun 25, 2018 · 24 comments

Comments

@Overdrivr
Copy link

While loading an exr file, the output is filled with 0's and this warning appears:

WARNING:root:imageio.freeimage warning: loading color model R as Y color model

I cannot seem to find much information about this. The image is a single-channel float32 exr, the warning comes from Freeimage that basically says that the image will be a single channel image. Does imageio supports this particular case ? Sadly I cannot share the image, let me know what I can do to help debug this. It's for an urgent work project so if I can go ahead and fix this I will

@almarklein
Copy link
Member

Hi @Overdrivr, EXR is provided by the FreeImage plugin. I just checked the imageio code, and FreeImage docs:

  • FreeImage does appear to support single channel float EXR images, so I'm not sure what the warning is about.
  • The warning is made by FreeImage (not by imageio's wrapper).
  • FreeImage does not seem to provide any options for reading EXR files, so there is little we can do from imageio.

In short, I really don't know how to help here, sorry :/ The problem appears to be at FreeImage. You could try upgrading the FreeImage lib, or posting an issue with them.

Asking, but I guess the answer is no: Is there a way for you to use another format?

@almarklein
Copy link
Member

BTW: A (sharable) example image that shows the same error would help test reproducibility.

@Overdrivr
Copy link
Author

Hi @almarklein, it looks like it's not a matter of channels but datatype in fact. The image i'm trying to load is a F32 EXR. All F16 EXR read/write just fine (single/multichannel), but float32 won't.

Since I cannot share the image, I tried saving a random EXR image using imageio in float32. However, the resulting image ends up being saved in F16 (I'm opening it up using DJV_View, to check information).

import imageio
import numpy as np
img = np.random.uniform(0, 1, size=(32,32))
imageio.imwrite('test_f32.exr', img.astype(np.float32))

I'm guessing it's because by default Freeimage saves EXR in half-float format. I saw in Freeimage doc that the EXR plugin can write in F32 under the condition that the EXR_FLOAT flag is passed. I tried the following but it won't work

>>> imageio.imwrite('test_f32.exr', img.astype(np.float32), flags=EXR_FLOAT)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'EXR_FLOAT' is not defined

How can I import the flags I need to pass to imageio ?

Asking, but I guess the answer is no: Is there a way for you to use another format?

I'm writing a software for VFX and while there are indeed other formats, the EXR format is absolutely instrumental since it was written by one of the top studios, so ideally I'd like to achieve full support.

@almarklein
Copy link
Member

How can I import the flags I need to pass to imageio ?

You'd have to hard-code them: put EXR_FLOAT = ... at the top of your module. The integer value you have to get from the docs or source code, probably the latter.

@Overdrivr
Copy link
Author

Ok thanks, I will try that ASAP

Would there be a point to add those flags to imageio, to make it easier for users ?

@Overdrivr
Copy link
Author

So the code for EXR_FLOAT is 0x0001. I have generated an EXR F32 image with the following code:

import imageio
import numpy as np
img = np.random.uniform(0, 1, (32, 32))
imageio.imwrite('test_exr_f32.exr', img.astype(np.float32), flags=0x0001)

And loaded that image back into imageio, I get no error. Cannot reproduce it. It must be something due to the image metadata. Any idea how I can inspect that ?

@almarklein
Copy link
Member

Would there be a point to add those flags to imageio, to make it easier for users ?

Probably best to put it in imageio.plugins.freeimage.

It must be something due to the image metadata. Any idea how I can inspect that ?

The metadata should be in im.meta. IIRC the wrapper tries to read all metadata that't in there ...

@Overdrivr
Copy link
Author

I just had a look at the metadata (at last :) ), there is nothing in it, it is an empty dict.

I am currently tracking down the software that produces this faulty image, I will soon be able to provide with a small test image. Keep you posted

@Overdrivr
Copy link
Author

Overdrivr commented Aug 30, 2018

Here is an image that causes the issue:

displace_v.zip

The problem comes from EXR images produced by ZBrush. They are single channel with L 32 pixel.

I am going to report this problem to FreeImage bug tracker. In the meantime, do you have any idea of a workaround ?

@almarklein
Copy link
Member

So if I understand correctly, the format in which the image is saved (single channel with L 32 pixel) is correct, but somehow does not work with freeimage?

@Overdrivr
Copy link
Author

Yes that's correct. The ticket on Freeimage issue tracker is here : https://sourceforge.net/p/freeimage/bugs/283/ (no replies yet)

There is also openexrpython but this wrapper requires the openexr library to be installed manually by the end user as a system library, which is a deal breaker for me.

However, this library should be capable of opening any EXR file out there because the wrapped library is actually written by the folks who created the EXR format.

@almarklein
Copy link
Member

Ok. Let's hope it gets fixed in Freeimage soon ...

@Overdrivr
Copy link
Author

Let's hope :P Otherwise, how difficult would it be to integrate openexrpython into imageio ?

Given that you have already implemented a pretty robust mechanism for fetching binaries of image loading libraries, is it complex to add a new one ?

@almarklein
Copy link
Member

It should not be too hard to do. Have a look at the example.py in the plugins directory, and the download functions in e.g. freeimage.py or ffmpeg.py.

As for the fetching of binaries, there is a repository for static files and binaries. We need to upload them there (for each platform). Then copy+modify a few lines of code from e.g. freeimage.py The rest is wrapping the library.

KelSolaar added a commit to colour-science/colour-demosaicing-tests-datasets that referenced this issue Oct 26, 2019
@devernay
Copy link

How can I import the flags I need to pass to imageio ?

You'd have to hard-code them: put EXR_FLOAT = ... at the top of your module. The integer value you have to get from the docs or source code, probably the latter.

You should not harcode the EXR_FLOAT value, but use imageio.plugins.freeimage.IO_FLAGS.EXR_FLOAT instead

@domef
Copy link

domef commented Jun 10, 2021

I've seen there are several flags for EXR format in imageio.plugins.freeimage.IO_FLAGS, is there any explanation of the meaning of these flags?

@devernay
Copy link

From the freeimage documentation:
image

@domef
Copy link

domef commented Jun 10, 2021

Thank you @devernay , do you have any idea why using EXR_FLOAT is not recommended? I couldn't find any information in the documentation.

@devernay
Copy link

I had bugs with imageio/freemage when writing 32-bit FP EXR on Linux, and I'm not the only one, see #517

here's an example where I wrote the same data as 32-bit TIFF and as EXR.

python -c "import skimage.io; img = skimage.io.imread('frames/xy.tif'); print(img[1799,265])"
[0.59474474 0.50933564 0.14748667 1.        ]
python -c "import skimage.io; img = skimage.io.imread('frames/xy.exr'); print(img[1799,265])"
# On macOS (correct result):
[0.59474474 0.50933564 0.14748667 1.        ]
# On Linux (wrong result, obtained on July 30 2020, newer imageio versions may give the right result):
[5.9474474e-01 5.0933564e-01 1.4748667e-01 2.2040519e-38]

So either use TIFF, wait for the bug to be fixed, or write your EXR from Python with OpenCV (which supports RGB but not RGBA for EXR).

@devernay
Copy link

This comment #517 (comment) also suggests using https://github.com/tvogels/pyexr

@FirefoxMetzger
Copy link
Contributor

Since pyav (ffmpeg) supports exr, I thought I give this issue a try and see if it got resolved in the process. Unfortunately it is not solved, but I thought I will leave this here for future reference.

The problematic EXR can be found in this comment: #356 (comment)

and the issue can be reproduced using the following snippet:

import imageio.v3 as iio
import numpy as np

img = iio.imread("displace_v.exr")
assert np.allclose(img, 0)  # should fail

The problem has been identified over in the freeimage repo; however, has not been fixed at the time of this writing:

The bug is really silly. FreeImage expects single and duo channel images to be named "Y" ("gray/luminance") or "Yx" (x being any other channel that will be ignored) .
Your image has a single channel named "R" as no channel Y is found and black is filled.

(Source: https://sourceforge.net/p/freeimage/bugs/283/)

PyAV is also able to read EXR files; however, it too fails to read the EXR ... for the same reason that freeimage fails to do so:

>>> img = iio.imread("displace_v.exr", plugin="pyav") 
Missing green channel.
Missing blue channel.
Could not find codec parameters for stream 0 (Video: exr, none): unspecified size
Consider increasing the value for the 'analyzeduration' (0) and 'probesize' (5000000) options
Missing green channel.
Missing blue channel.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\Sebastian\Documents\Coding-Projects\imageio\imageio\v3.py", line 61, in imread
    return np.asarray(img_file.read(**call_kwargs))
  File "C:\Users\Sebastian\Documents\Coding-Projects\imageio\imageio\plugins\pyav.py", line 375, in read
    [
  File "C:\Users\Sebastian\Documents\Coding-Projects\imageio\imageio\plugins\pyav.py", line 375, in <listcomp>
    [
  File "C:\Users\Sebastian\Documents\Coding-Projects\imageio\imageio\plugins\pyav.py", line 459, in iter
    for frame in self._container.decode(video=0):
  File "av\container\input.pyx", line 187, in decode
  File "av\packet.pyx", line 87, in av.packet.Packet.decode
  File "av\stream.pyx", line 183, in av.stream.Stream.decode
  File "av\codec\context.pyx", line 522, in av.codec.context.CodecContext.decode
  File "av\codec\context.pyx", line 425, in av.codec.context.CodecContext._send_packet_and_recv
  File "av\error.pyx", line 336, in av.error.err_check
av.error.InvalidDataError: [Errno 1094995529] Invalid data found when processing input; last error log: [exr] Missing blue channel.

@FirefoxMetzger
Copy link
Contributor

FirefoxMetzger commented Apr 18, 2022

OpenCV has the same problem as FreeImage when reading the faulty EXR:

>>> import numpy as np
>>> import cv2                         
>>> img = cv2.imread("displace_v.exr")
>>> np.allclose(img, 0)
True

@Bra1nsen
Copy link

any updates here. I would like so save 16 Bit rgb array as .exr file..

		rgb_array = np.zeros((760, 1016, 3), dtype=np.uint16)
		rgb_array[:, :, 0] = array16[1::2, 1::2] # red
		# Must avoid overflowing 16-bits in the addition here:
		rgb_array[:, :, 1] = (array16[0::2, 1::2].astype(int) + array16[1::2, 0::2]) / 2 # green
		rgb_array[:, :, 2] = array16[0::2, 0::2] # blue

		imageio.imwrite(f'{exp}rgb.exr', rgb_array)

ValueError: Could not find a backend to open 50rgb.exr with iomode wi`

@FirefoxMetzger
Copy link
Contributor

@Bra1nsen The problem discussed here is that FreeImage, the backend we use to reads EXR, has a bug that prevents it from properly reading some grayscale images in EXR format. Specifically, those that label their gray channel as "R" instead of the expected "Y" (luma).

I think that the issue that you are facing is due to a different problem and unrelated to this.

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

No branches or pull requests

6 participants