pythonnumpypython-imageio

Saving a NumPy array with imageio.imsave distorts the image


I am processing an image with imageio library in Python, and I got unexpected result.

I tested the problem with the code below:

import imageio
import numpy as np

imgarray = np.zeros((3, 4032, 3024), dtype=np.uint8)
imgarray[0, 0::2, 1::2] = 255
print('Original\n', imgarray)
imageio.imsave('test.jpg', imgarray.transpose(1, 2, 0))

img = imageio.imread('test.jpg')
imgarray = np.array(img).transpose(2, 0, 1)
print('\n\nSave and load\n', imgarray)

Printed results are:

Original
[[[  0 255   0 ... 255   0 255]
  [  0   0   0 ...   0   0   0]
  [  0 255   0 ... 255   0 255]
  ...
  [  0   0   0 ...   0   0   0]
  [  0 255   0 ... 255   0 255]
  [  0   0   0 ...   0   0   0]]

 [[  0   0   0 ...   0   0   0]
  [  0   0   0 ...   0   0   0]
  [  0   0   0 ...   0   0   0]
  ...
  [  0   0   0 ...   0   0   0]
  [  0   0   0 ...   0   0   0]
  [  0   0   0 ...   0   0   0]]

 [[  0   0   0 ...   0   0   0]
  [  0   0   0 ...   0   0   0]
  [  0   0   0 ...   0   0   0]
  ...
  [  0   0   0 ...   0   0   0]
  [  0   0   0 ...   0   0   0]
  [  0   0   0 ...   0   0   0]]]


Save and load
[[[ 50 112  48 ... 120  56 118]
  [ 45  46  45 ...  45  45  46]
  [ 45 116  55 ... 112  52 129]
  ...
  [ 53  45  45 ...  50  45  45]
  [ 48 114  49 ... 117  53 119]
  [ 45  47  46 ...  45  45  46]]

 [[  0  48   0 ...  56   0  54]
  [  0   0   0 ...   0   0   0]
  [  0  52   0 ...  48   0  65]
  ...
  [  0   0   0 ...   0   0   0]
  [  0  50   0 ...  53   0  55]
  [  0   0   0 ...   0   0   0]]

 [[  0  48   0 ...  56   0  54]
  [  0   0   0 ...   0   0   0]
  [  0  52   0 ...  48   0  65]
  ...
  [  0   0   0 ...   0   0   0]
  [  0  50   0 ...  53   0  55]
  [  0   0   0 ...   0   0   0]]]

Why are the original numpy array and the numpy array after saving and loading different?

I think they should be identical after saving and loading.

I have same problem when using different libraries, e.g. cv2 or PIL.Image.

Is there a way to maintain the data unchanged after saving and loading?


Solution

  • JPEG is an image format that uses lossy compression. The algorithm is designed to reduce file size by removing details that the human eye would usually not perceive. If you need to retain the exact pixel information, use an image format with lossless compression, such as PNG.

    To make your code work as expected, you only need to change the file ending: test.png instead of test.jpg. ImageIO takes care of the rest.