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

47
demandé sur Shan 2011-10-14 08:13:07

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'>
70
répondu Andrey Kamaev 2018-09-16 09:18:40

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" )
41
répondu David Poole 2018-02-26 16:52:45

Vous pouvez aussi utiliser matplotlib pour ce.

import matplotlib.image as mpimg

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

Sortie: <class 'numpy.ndarray'>

10
répondu Rishabh Agrahari 2017-10-06 11:30:25

, 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)
6
répondu Justin Peel 2011-10-14 04:57:12

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.

3
répondu slizb 2018-04-24 20:28:55
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
2
répondu wim 2011-10-14 05:08:47

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.

1
répondu daign 2016-11-28 19:58:42

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.

0
répondu enigmaticPhysicist 2018-05-10 23:44:40