convert EXR to JPEG using ImageIO and Python
Asked Answered
C

2

6

I'm simply trying to convert and EXR to a jpg image however my results are turning out to be very dark. Does anyone know what I'm doing wrong here? I'm normalizing the image values and then placing them into 0-255 color space. It still appears incorrect though.

Dropbox link to test exr image: https://www.dropbox.com/s/9a5z6fjsyth7w98/torus.exr?dl=0

enter image description here

import sys, os
import imageio

def convert_exr_to_jpg(exr_file, jpg_file):
    if not os.path.isfile(exr_file):
        return False

    filename, extension = os.path.splitext(exr_file)
    if not extension.lower().endswith('.exr'):
        return False

    # imageio.plugins.freeimage.download() #DOWNLOAD IT
    image = imageio.imread(exr_file, format='EXR-FI')

    # remove alpha channel for jpg conversion
    image = image[:,:,:3]

    # normalize the image
    data = image.astype(image.dtype) / image.max() # normalize the data to 0 - 1
    data = 255 * data # Now scale by 255
    rgb_image = data.astype('uint8')
    # rgb_image = imageio.core.image_as_uint(rgb_image, bitdepth=8)

    imageio.imwrite(jpg_file, rgb_image, format='jpeg')
    return True


if __name__ == '__main__':
    exr = "C:/Users/John/images/torus.exr"
    jpg = "C:/Users/John/images/torus.jpg"
    convert_exr_to_jpg(exr, jpg)
Capias answered 7/6, 2018 at 18:37 Comment(3)
I believe EXR allows ridiculously wide ranges of values, so scaling to the maximum may be a bad idea. I think you might also need some gamma correction.Bonnette
i think you should normalize each color channel separately.Portecochere
any help on how to do that would be much appreciatedCapias
U
4

I ran into the same issue, and fixed it here. Because ImageIO converts everything to a numpy array you can gamma correct the values (fixing your darkness issue) and then convert that back to a PIL Image to work with easily:

im = imageio.imread("image.exr")
im_gamma_correct = numpy.clip(numpy.power(im, 0.45), 0, 1)
im_fixed = Image.fromarray(numpy.uint8(im_gamma_correct*255))

I tested this on your very beautiful torus knot and it worked perfectly. Just let me know if you need a more complete code snippet, but I think the above answers your actual question.

Ulu answered 24/10, 2019 at 22:26 Comment(1)
Same thing for .hdr's btw.Ulu
I
3

The sample image is an EXR image with 16 bit depth (channel). Here is a python script to convert the exr image to png with opencv.

import numpy as np
import cv2
im=cv2.imread("torus.exr",-1)
im=im*65535
im[im>65535]=65535
im=np.uint16(im)
cv2.imwrite("torus.png",im)

enter image description here

Here is the modified code with imageio that will save the image in jpeg format

import sys, os
import imageio

def convert_exr_to_jpg(exr_file, jpg_file):
    if not os.path.isfile(exr_file):
        return False

    filename, extension = os.path.splitext(exr_file)
    if not extension.lower().endswith('.exr'):
        return False

    # imageio.plugins.freeimage.download() #DOWNLOAD IT
    image = imageio.imread(exr_file)
    print(image.dtype)

    # remove alpha channel for jpg conversion
    image = image[:,:,:3]


    data = 65535 * image
    data[data>65535]=65535
    rgb_image = data.astype('uint16')
    print(rgb_image.dtype)
    #rgb_image = imageio.core.image_as_uint(rgb_image, bitdepth=16)

    imageio.imwrite(jpg_file, rgb_image, format='jpeg')
    return True


if __name__ == '__main__':
    exr = "torus.exr"
    jpg = "torus3.jpeg"
    convert_exr_to_jpg(exr, jpg)

enter image description here

(Tested with python 3.5.2,Ubuntu 16.04)

Innermost answered 14/6, 2019 at 7:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.