thyu
thyu

Reputation: 1773

Why is it showing different images in 4d numpy array?

I'm trying to create a 4D array for a bunch of 3D images. I can load the image and show the image correctly, but after storing it to the 4D array and show the image from the array, it shows gibberish.

I tried to compare if the image loaded and the one read from the 4D array is equal, and it prints True.

import os
from glob import glob
import numpy as np
from PIL import Image

IMG_PATH = '32x32'
img_paths = glob(os.path.join(IMG_PATH, '*.jpg'))
images = np.empty((len(img_paths), 32, 32, 3))
for i, path_i in enumerate(img_paths):
    img_i = np.array(Image.open(path_i))
    Image.fromarray(img_i, 'RGB').show() # showing correct image
    images[i] = img_i
    Image.fromarray(images[i], 'RGB').show() # showing gibberish
    print(np.array_equal(img_i, images[i])) # True
    if i == 0:
        break

I expect to show the exact same image as I run images[i] = img_i.

Upvotes: 1

Views: 337

Answers (1)

Eric
Eric

Reputation: 97571

This line is performing a cast:

images[i] = img_i

Since images.dtype == np.float64, but img_i.dtype is probably np.uint8.


You can catch this type of mistake by specifying a casting rule:

np.copy_to(images[i], img_i, casting='no')
# TypeError: Cannot cast scalar from dtype('uint8') to dtype('float64') according to the rule 'no'

You can fix this by allocating the array with the right type:

images = np.empty((len(img_paths), 32, 32, 3), dtype=np.uint8)

Or you can let numpy do the allocation for you, but this will temporarily use almost twice the memory:

images = np.stack([
    Image.open(path_i)
    for path_i in img_paths
], axis=0)

Upvotes: 2

Related Questions