Skip to content
Advertisement

How to save a full size image with RGB and float32?

I have an image array with RGB, np.float32, and values in the range of 0 ... 1.

When I multiply the array with 255, and use cv2.imwrite, the output is not correct. When I use plt.imshow(img.astype(np.float32)), the output is right, but the image size is too small.

plt.imshow(img.astype(np.float32))
plt.axis("off")
#plt.show()
#io.imsave("233.jpg", img)
plt.savefig('233.jpg')

How can I output a good image?

Advertisement

Answer

The common JPEG format doesn’t support storing 32-bit floating point values. Even the somehow common JPEG 2000 format isn’t capable to do that. You might have a look at the OpenEXR format, which is also supported by OpenCV, and which can store 32-bit floating point values per channel. Nevertheless, OpenEXR seems to be less supported in general.

Here’s some small example, also comparing to some JPEG export:

import cv2
from matplotlib import pyplot as plt
import numpy as np

# Generate image
x = np.linspace(0, 1, 1024, dtype=np.float32)
x, y = np.meshgrid(x, x)
img = np.stack([x, y, np.fliplr(x)], axis=2)

# Save image as JPG and EXR
cv2.imwrite('img.jpg', img * 255)
cv2.imwrite('img.exr', img)

# Read JPG and EXR images
jpg = cv2.imread('img.jpg', cv2.IMREAD_UNCHANGED)
exr = cv2.imread('img.exr', cv2.IMREAD_UNCHANGED)

# Compare original with EXR image
print('Original image shape and type: ', img.shape, img.dtype)
print('EXR image shape and type: ', exr.shape, exr.dtype)
print('Original image == EXR image:', np.all(img == exr))
# Original image shape and type:  (1024, 1024, 3) float32
# EXR image shape and type:  (1024, 1024, 3) float32
# Original image == EXR image: True

# Show all images
plt.figure(1, figsize=(18, 9))
plt.subplot(2, 3, 1), plt.imshow(img), plt.title('Original')
plt.subplot(2, 3, 2), plt.imshow(jpg), plt.title('JPG image')
plt.subplot(2, 3, 3), plt.imshow(exr), plt.title('EXR image')
plt.subplot(2, 3, 4), plt.imshow(img[200:300, 500:600, ...])
plt.subplot(2, 3, 5), plt.imshow(jpg[200:300, 500:600, ...])
plt.subplot(2, 3, 6), plt.imshow(exr[200:300, 500:600, ...])
plt.tight_layout(), plt.show()

That’d be the plot:

Plot

I’m not sure, what differences you see, when comparing your JPEG export and your Matplotlib plot, but for the given example, from my point of view, differences between original image, JPG image, and EXR image can be hardly seen. Of course, you can see some blocks in the JPG image when zooimg, but does that really “falsify” an “image”?

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.19041-SP0
Python:        3.9.1
PyCharm:       2021.1.1
Matplotlib:    3.4.1
NumPy:         1.20.2
OpenCV:        4.5.1
----------------------------------------
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement