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.

Shan
la source
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'>
Andrey Kamaev
la source
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" )
David Poole
la source
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
54

Vous pouvez également utiliser matplotlib pour cela.

from matplotlib.image import imread

img = imread('abc.tiff')
print(type(img))

production: <class 'numpy.ndarray'>

Rishabh Agrahari
la source
2
C'est très simple. J'aime ça :)
jeongmin.cha
@Mrinal Oui, c'est vrai.
Rishabh Agrahari
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'>
belvédère
la source
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.

slizb
la source
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)
Justin Peel
la source
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.

campagne
la source
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
wim
la source
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.

énigmatiquePhysicien
la source
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
joker007
la source
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
Disha Doshi
la source