web-dev-qa-db-fra.com

comment convertir une image RVB en tableau numpy?

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.

58
Shan

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'>
80
Andrey Kamaev

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 )

'Image.fromarray' est un peu moche parce que je coupe les données entrantes dans [0,255], les convertit en octets, puis crée une image en niveaux de gris. Je travaille surtout en gris.

Une image RVB serait quelque chose comme:

 outimg = Image.fromarray( ycc_uint8, "RGB" )
 outimg.save( "ycc.tif" )
44
David Poole

Vous pouvez également utiliser matplotlib pour cela.

from matplotlib.image import imread

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

sortie: <class 'numpy.ndarray'>

21
Rishabh Agrahari

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
Justin Peel

Réponse tardive, mais j'ai fini par préférer le module imageio aux autres alternatives

import imageio
im = imageio.imread('abc.tiff')

Semblable à cv2.imread(), il produit un tableau numpy par défaut, mais sous forme RVB.

5
slizb
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
wim

À partir d’aujourd’hui, votre meilleur choix 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 que img sera un tableau numpy de type:

<class 'numpy.ndarray'>
1
belvederef

En utilisant la réponse de David Poole, j'obtiens un SystemError avec des PNG en niveaux 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 il est plus lent, je ne l'utilise donc que lorsque l'autre méthode échoue.

1
daign

J'ai aussi adopté imageio, mais j'ai trouvé les machines suivantes utiles pour le pré et 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 en est que j'utilise numpy pour le traitement des images, pas seulement pour l'affichage d'images. Pour cela, les uint8s sont maladroits, je me convertis donc en valeurs à virgule flottante allant de 0 à 1.

Lors de la sauvegarde des images, je me suis rendu compte que je devais réduire moi-même les valeurs hors limites, sinon je me retrouvais avec une sortie très grise. (La sortie grise est le résultat de l’imageio compressant l’ensemble de la plage, située en dehors de [0, 256) en valeurs comprises dans cette plage.)

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

0