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.