come convertire un'immagine RGB in un array numpy?


113

Ho un'immagine RGB. Voglio convertirlo in array numpy. Ho fatto quanto segue

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

Crea un array senza forma. Presumo sia un oggetto iplimage.


2
Se cvè il modulo OpenCV, dovresti etichettarlo come tale. Questo collegamento può aiutare: opencv.willowgarage.com/documentation/python/…
Paul

Risposte:


142

Puoi usare la nuova interfaccia OpenCV python (se non sbaglio è disponibile da OpenCV 2.2). Utilizza nativamente array numpy:

import cv2
im = cv2.imread("abc.tiff",mode='RGB')
print type(im)

risultato:

<type 'numpy.ndarray'>

95
Attenzione che cv2.imread () restituisce un array numpy in BGR non RGB.
pnd

6
@pnd il tuo commento è sacro!
Eduardo Pignatelli

4
Per riferimento futuro: $ pip install opencv-pythoninstallare opencv
Kyle C

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

8
OpenCV sembra aver abbandonato l' modeargomento. Vedi la mia risposta di seguito per un metodo aggiornato.
belvedere del

73

PIL (Python Imaging Library) e Numpy funzionano bene insieme.

Uso le seguenti funzioni.

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" è un po 'brutto perché ritaglio i dati in entrata in [0,255], li converto in byte, quindi creo un'immagine in scala di grigi. Lavoro principalmente in grigio.

Un'immagine RGB sarebbe qualcosa del tipo:

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

1
Questo fallisce con un errore TypeError: long() argument must be a string or a number, not 'PixelAccess'e , guardando la documentazione per la PixelAccessclasse PIL , non sembra offrire metodi che consentirebbero np.arraydi convertire i dati sottostanti in un ndarrayformato. È necessario omettere l'uso di img.load()e trattare solo il risultato di Image.open(...).
ely

Img.load () risolve uno strano problema di memorizzazione nella cache in PIL. I dati non sarebbero stati caricati fino a quando non fosse esplicitamente necessario. L'esempio funziona ancora per me, ad eccezione della modifica di "import Image" in "from PIL import Image" quando si lavora con Pillow (il fork PIL).
David Poole

Voto positivo per l'utilizzo solo di PIL e non di OpenCV. Tuttavia, non sono contro OpenCV.
progyammer


19

Ad oggi, la soluzione migliore è utilizzare:

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

Vedrai imgsarà un array numpy di tipo:

<class 'numpy.ndarray'>

12

Risposta tardiva, ma sono arrivato a preferire il imageiomodulo alle altre alternative

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

Simile a cv2.imread(), produce un array numpy per impostazione predefinita, ma in formato RGB.


7

Devi usare cv.LoadImageM invece di 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)

Grazie mille ... Potresti anche aiutarmi a scoprire che se creo un'immagine usando 'cv.CreateImage (larghezza, altezza, canali)' ... Come potrebbe essere convertita in un array numpy?
Shan

Penso che tu debba usare cv.CreateMat invece o usare cv.CreateMat e copiare dall'immagine al mat usando cv.CvtColor o qualcosa di simile. Dai un'occhiata al link che Paul ha pubblicato sopra.
Justin Peel

3

Quando utilizzo la risposta di David Poole ottengo un SystemError con PNG in scala di grigi e forse altri file. La mia soluzione è:

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' )

In realtà img.getdata () funzionerebbe per tutti i file, ma è più lento, quindi lo uso solo quando l'altro metodo fallisce.


2

Il formato immagine OpenCV supporta l'interfaccia array numpy. È possibile creare una funzione di supporto per supportare immagini in scala di grigi oa colori. Ciò significa che la conversione BGR -> RGB può essere comodamente eseguita con una sezione numpy, non una copia completa dei dati dell'immagine.

Nota: questo è un trucco da passo, quindi la modifica dell'array di output cambierà anche i dati dell'immagine OpenCV. Se vuoi una copia, usa il .copy()metodo sull'array!

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

Ho adottato anche imageio, ma ho trovato utili i seguenti macchinari per la pre e la post-elaborazione:

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 logica è che sto usando numpy per l'elaborazione delle immagini, non solo per la visualizzazione delle immagini. A questo scopo, gli uint8 sono scomodi, quindi converto in valori in virgola mobile che vanno da 0 a 1.

Durante il salvataggio delle immagini, ho notato che dovevo tagliare i valori fuori intervallo da solo, oppure ho ottenuto un output molto grigio. (L'output in grigio era il risultato della compressione di imageio dell'intero intervallo, che era al di fuori di [0, 256), a valori che erano all'interno dell'intervallo.)

C'erano anche un paio di altre stranezze, che ho menzionato nei commenti.


1

Puoi ottenere facilmente un array numpy di immagini rgb usando numpyeImage 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

caricare l'immagine utilizzando la seguente sintassi: -

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.