Vous pouvez lire les jolies petites images JPEG/PNG/JP2 dans la mémoire sous la forme d'un tas d'octets et les y maintenir compressées avec la même taille que sur le disque, puis les décompresser de la mémoire lorsque vous en avez besoin.
Tout d'abord, regardons la mémoire requise par une image 1280x1024 de RGB888 en mémoire - c'est un énorme 3.9MB :
# Decompressed image in memory takes 3.9MB memory
im = np.zeros([1280,1024,3], dtype=np.uint8)
# print(im.nbytes) => 3932160
Maintenant, regardons un JPEG de la même taille :
Le voici sur le disque, avec ls -l
:
-rw-r--r--@ 1 mark staff 47276 2 Apr 17:13 image.jpg
Et ici, il est toujours compressé en mémoire, également à 47kB ou seulement 1,2% de la taille :
# Same image as JPEG takes 47kB of memory
with open('image.jpg','rb') as f:
jpg = f.read()
# print(len(jpg)) => 47276
Maintenant, lorsque vous voulez une image, vous la décompressez depuis la mémoire plutôt que depuis le disque.
# Read with 'imageio'
from io import BytesIO
import imageio
numpyArray = imageio.imread(BytesIO(jpg))
# print(numpyArray.shape) =>(1024, 1280, 3)
# Or, alternatively, and probably faster, read with OpenCV
import cv2
numpyArray = cv2.imdecode(np.frombuffer(jpg,dtype=np.uint8), -1)
# print(numpyArray.shape) =>(1024, 1280, 3)
Une autre option, totalement différente, qui décodera des kilomètres plus vite, mais qui ne réduira l'empreinte mémoire que par un facteur 3, consiste à palettiser les images. Vous réduisez le nombre de couleurs à moins de 256 couleurs uniques et stockez une palette de 256 couleurs. À chaque emplacement de pixel, vous stockez alors un seul octet qui est l'index dans la palette, plutôt que 3 octets de RVB. Cela réduira votre utilisation de la mémoire de 3,9 Mo/image à 1,3 Mo/image. Cela ne nécessite aucun décodage, mais peut entraîner une légère perte de la fidélité des couleurs et/ou des bandes - ce qui peut ou non être un problème selon la qualité de votre appareil photo ou de vos images.
Cela ressemble à quelque chose comme ceci (non testé) :
from PIL import Image
import numpy as np
im = Image.open('image.jpg')
# Make into Numpy array - size is 3.9MB
a = np.array(im)
# Now make a 256 colour palletised version
p = im.convert('P',palette=Image.ADAPTIVE)
# Make into Numpy array - size is now only 1.3MB
a = np.array(p)