comment convertir une image RVB en tableau numpy?


113

J'ai une image RVB. Je veux le convertir en tableau numpy. J'ai fait ce qui suit

im = cv.LoadImage("abc.tiff")
a = numpy.asarray(im)

Il crée un tableau sans forme. Je suppose que c'est un objet iplimage.


2
S'il cvs'agit du module OpenCV, vous devez le marquer comme tel. Ce lien peut vous aider: opencv.willowgarage.com/documentation/python/…
Paul

Réponses:


142

Vous pouvez utiliser la nouvelle interface python OpenCV (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'>

95
Attention, cv2.imread () renvoie un tableau numpy dans BGR et non RVB.
pnd

6
@pnd votre commentaire est sacré!
Eduardo Pignatelli

4
Pour référence future: $ pip install opencv-pythonpour installer opencv
Kyle C

2
TypeError: 'mode' is an invalid keyword argument for imread()
Rishabh Agrahari

8
OpenCV semble avoir abandonné l' modeargument. Voir ma réponse ci-dessous pour une méthode mise à jour.
belvederef

73

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 )

Le 'Image.fromarray' est un peu moche car je découpe les données entrantes à [0,255], je les convertis en octets, puis je crée 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" )

1
Cela échoue avec une erreur, TypeError: long() argument must be a string or a number, not 'PixelAccess'et en regardant la documentation de la PixelAccessclasse de PIL , il ne semble pas offrir de méthodes qui permettraient np.arrayde convertir ses données sous-jacentes dans un ndarrayformat. Vous devez omettre l'utilisation de img.load()et ne traiter que le résultat de Image.open(...).
ely

Le img.load () fonctionne autour d'un problème de mise en cache étrange dans PIL. Les données ne seraient pas chargées avant d'être explicitement nécessaires. L'exemple fonctionne toujours pour moi, à l'exception de la modification de "Import Image" en "from PIL import Image" lorsque vous travaillez avec Pillow (la fourche PIL).
David Poole

Vote favorable pour l'utilisation de PIL uniquement et non d'OpenCV. Mais je ne suis pas contre OpenCV.
progyammer


19

À partir d'aujourd'hui, votre meilleur pari est d'utiliser:

img = cv2.imread(image_path)   # reads an image in the BGR format
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)   # BGR -> RGB

Vous verrez imgsera un tableau numpy de type:

<class 'numpy.ndarray'>

12

Réponse tardive, mais j'ai fini par préférer le imageiomodule 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.


7

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)

Merci beaucoup ... Pourriez-vous s'il vous plaît aussi m'aider à découvrir que si je crée une image en utilisant 'cv.CreateImage (largeur, hauteur, canaux)' ... Comment pourrait-elle être convertie en tableau numpy?
Shan

Je pense que vous devez utiliser cv.CreateMat à la place ou utiliser cv.CreateMat et copier de l'image vers le tapis en utilisant cv.CvtColor ou quelque chose de similaire. Jetez un œil au lien que Paul a publié ci-dessus.
Justin Peel

3

Lorsque j'utilise la réponse de David Poole, j'obtiens une SystemError avec des PNG en é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 ne l'utilise que lorsque l'autre méthode échoue.


2

Le format d'image OpenCV prend en charge l'interface de tableau numpy. Une fonction d'assistance peut être créée pour prendre en charge les images en niveaux de gris ou en couleur. Cela signifie que la conversion BGR -> RVB peut être effectuée de manière pratique avec une tranche numérique et non une copie complète des données d'image.

Remarque: il s'agit d'une astuce, donc la modification du tableau de sortie changera également les données d'image OpenCV. Si vous voulez une copie, utilisez la .copy()méthode sur le tableau!

import numpy as np

def img_as_array(im):
    """OpenCV's native format to a numpy array view"""
    w, h, n = im.width, im.height, im.channels
    modes = {1: "L", 3: "RGB", 4: "RGBA"}
    if n not in modes:
        raise Exception('unsupported number of channels: {0}'.format(n))
    out = np.asarray(im)
    if n != 1:
        out = out[:, :, ::-1]  # BGR -> RGB conversion
    return out

1

J'ai également adopté imageio, mais j'ai trouvé les machines suivantes utiles pour le prétraitement 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 est que j'utilise numpy pour le traitement d'image, pas seulement pour l'affichage d'image. Dans ce but, les uint8 sont gênants, je les convertis donc en valeurs à virgule flottante allant de 0 à 1.

Lors de la sauvegarde des images, j'ai remarqué que je devais couper moi-même les valeurs hors plage, sinon je me suis retrouvé avec une sortie vraiment grise. (La sortie grise était le résultat de l'imageio compressant la plage complète, qui était en dehors de [0, 256), à des valeurs qui étaient à l'intérieur de la plage.)

Il y avait aussi quelques autres bizarreries, que j'ai mentionnées dans les commentaires.


1

Vous pouvez facilement obtenir un tableau numpy d'images rgb en utilisant numpyetImage from PIL

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

im = Image.open('*image_name*') #These two lines
im_arr = np.array(im) #are all you need
plt.imshow(im_arr) #Just to verify that image array has been constructed properly

0

charger l'image en utilisant la syntaxe suivante: -

from keras.preprocessing import image

X_test=image.load_img('four.png',target_size=(28,28),color_mode="grayscale"); #loading image and then convert it into grayscale and with it's target size 
X_test=image.img_to_array(X_test); #convert image into array
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.