comment convertir une image RVB en tableau numpy?
J'ai une image RVB. Je veux le convertir en tableau numpy. Je n'ai la suite
im = cv.LoadImage("abc.tiff")
a = numpy.asarray(im)
Il crée un tableau sans forme. Je suppose que c'est un objet iplimage.
Comment le faire?
Merci
8 réponses
Vous pouvez utiliser une interface Python OpenCV plus récente (si Je ne me trompe pas, elle est disponible depuis OpenCV 2.2). Il utilise nativement des tableaux numpy:
import cv2
im = cv2.imread("abc.tiff",mode='RGB')
print type(im)
Résultat:
<type 'numpy.ndarray'>
PIL (Python Imaging Library) et Numpy fonctionnent bien ensemble.
J'utilise les fonctions suivantes.
from PIL import Image
import numpy as np
def load_image( infilename ) :
img = Image.open( infilename )
img.load()
data = np.asarray( img, dtype="int32" )
return data
def save_image( npdata, outfilename ) :
img = Image.fromarray( np.asarray( np.clip(npdata,0,255), dtype="uint8"), "L" )
img.save( outfilename )
L'Image.fromarray' est un peu moche parce que je clip les données entrantes à [0,255], convertir en octets, puis créer une image en niveaux de gris. Je travaille principalement en gris.
Une image RVB serait quelque chose comme:
outimg = Image.fromarray( ycc_uint8, "RGB" )
outimg.save( "ycc.tif" )
Vous pouvez aussi utiliser matplotlib pour ce.
import matplotlib.image as mpimg
img = mpimg.imread('abc.tiff')
print(type(img))
Sortie:
<class 'numpy.ndarray'>
, Vous devez utiliser cv.LoadImageM au lieu de cv.LoadImage:
In [1]: import cv
In [2]: import numpy as np
In [3]: x = cv.LoadImageM('im.tif')
In [4]: im = np.asarray(x)
In [5]: im.shape
Out[5]: (487, 650, 3)
Réponse tardive, mais j'en suis venu à préférer le module imageio
aux autres alternatives
import imageio
im = imageio.imread('abc.tiff')
Similaire à cv2.imread()
, il produit un tableau numpy par défaut, mais sous forme RVB.
def opencv_image_as_array(im):
"""Interface image from OpenCV's native format to a numpy array.
note: this is a slicing trick, and modifying the output array will also change
the OpenCV image data. if you want a copy, use .copy() method on the array!
"""
import numpy as np
w, h, n = im.width, im.height, im.channels
modes = {1:"L", 3:"RGB"}#, 4:"RGBA"}
if n not in modes:
raise StandardError('unsupported number of channels: {0}'.format(n))
out = np.asarray(im) if n == 1 else np.asarray(im)[:,:,::-1] ## BGR -> RGB
return out
En utilisant la réponse de David Poole, j'obtiens une SystemError avec des png à échelle de gris et peut-être d'autres fichiers. Ma solution est:
import numpy as np
from PIL import Image
img = Image.open( filename )
try:
data = np.asarray( img, dtype='uint8' )
except SystemError:
data = np.asarray( img.getdata(), dtype='uint8' )
En fait img.getdata() fonctionnerait pour tous les fichiers, mais c'est plus lent, donc je l'utilise uniquement lorsque l'autre méthode échoue.
J'ai également adopté imageio, mais j'ai trouvé les machines suivantes utiles pour le pré-et le post-traitement:
import imageio
import numpy as np
def imload(*a, **k):
i = imageio.imread(*a, **k)
i = i.transpose((1, 0, 2)) # x and y are mixed up for some reason...
i = np.flip(i, 1) # make coordinate system right-handed!!!!!!
return i/255
def imsave(i, url, *a, **k):
# Original order of arguments was counterintuitive. It should
# read verbally "Save the image to the URL" — not "Save to the
# URL the image."
i = np.flip(i, 1)
i = i.transpose((1, 0, 2))
i *= 255
i = i.round()
i = np.maximum(i, 0)
i = np.minimum(i, 255)
i = np.asarray(i, dtype=np.uint8)
imageio.imwrite(url, i, *a, **k)
La raison d'être est que j'utilise numpy pour le traitement d'image, pas seulement l'affichage d'image. A cet effet, les uint8 sont gênants, donc je convertit en valeurs à virgule flottante allant de 0 à 1.
Lors de l'enregistrement des images, j'ai remarqué que je devais couper moi-même les valeurs hors de portée, sinon je me suis retrouvé avec une sortie vraiment grise. (La sortie grise était le résultat de la compression d'imageio plage complète, qui était en dehors de [0, 256), aux valeurs qui étaient à l'intérieur de la plage.)
Il y avait aussi quelques autres bizarreries, que j'ai mentionnées dans les commentaires.