How to correctly read .exr files in python?

527 views Asked by At

like the title says I want to read .exr image files which encode depth.

Sample image - displayed using openexr-viewer (Source: Synscapes datatset)

I tried:

os.environ["OPENCV_IO_ENABLE_OPENEXR"]="1"

import cv2
import numpy as np

exr_file_path = 'path/to/file'

image = cv2.imread(exr_file_path,  cv2.IMREAD_ANYCOLOR | cv2.IMREAD_ANYDEPTH)

The dimensions of image are correct, but the image is completely filled with zeros.

Debugger shows this:

->image.shape
      (720, 1440)
->np.unique(image)
      array([0.], dtype=float32)

What am I missing ?

My goal would be to create a function which accepts a path to an .exr file and returns the image as a pillow image.

Currently this is what I have:

def exr_to_pil(exr_file_path): 
    exr_file_path = str(exr_file_path)
    image = cv2.imread(exr_file_path,  cv2.IMREAD_ANYCOLOR | cv2.IMREAD_ANYDEPTH)
    
    # Debugger stops here to check output of imread
    img = Image.fromarray(image.astype('uint8'))
    
    return img
1

There are 1 answers

1
Chris On BEST ANSWER

Solved the problem using the OpenEXR an Imath libs

At first had some problems installing OpenEXR but could fix is thanks to this answer in this post.

On MacOS with the same python version I hit similar errors and everything worked when installing with this command: pip install git+https://github.com/jamesbowman/openexrpython.git

Code for depth map loading is:

import OpenEXR as exr
import Imath

def exr_to_array(filepath: Path):
    exrfile = exr.InputFile(filepath.as_posix())
    raw_bytes = exrfile.channel('Z', Imath.PixelType(Imath.PixelType.FLOAT))
    depth_vector = numpy.frombuffer(raw_bytes, dtype=numpy.float32)
    height = exrfile.header()['displayWindow'].max.y + 1 - exrfile.header()['displayWindow'].min.y
    width = exrfile.header()['displayWindow'].max.x + 1 - exrfile.header()['displayWindow'].min.x
    depth_map = numpy.reshape(depth_vector, (height, width))
    return depth_map