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:
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 ----------------------------------------