Wie konvertiere ich ein RGB-Bild in ein Numpy-Array?

113

Ich habe ein RGB-Bild. Ich möchte es in ein Numpy-Array konvertieren. Ich habe folgendes getan

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

Es wird ein Array ohne Form erstellt. Ich nehme an, es ist ein iplimage-Objekt.

Shan
quelle
2
Wenn cves sich um das OpenCV-Modul handelt, sollten Sie es als solches kennzeichnen. Dieser Link kann helfen: opencv.willowgarage.com/documentation/python/…
Paul

Antworten:

142

Sie können eine neuere OpenCV-Python-Oberfläche verwenden (wenn ich mich nicht irre, ist sie seit OpenCV 2.2 verfügbar). Es werden nativ Numpy-Arrays verwendet:

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

Ergebnis:

<type 'numpy.ndarray'>
Andrey Kamaev
quelle
93
Beachten Sie, dass cv2.imread () ein numpy-Array in BGR und nicht in RGB zurückgibt.
25.
6
@pnd dein Kommentar ist heilig!
Eduardo Pignatelli
4
Zum späteren Nachschlagen: $ pip install opencv-pythonOpenCV installieren
Kyle C
2
TypeError: 'mode' is an invalid keyword argument for imread()
Rishabh Agrahari
7
OpenCV scheint das modeArgument fallen gelassen zu haben . In meiner Antwort unten finden Sie eine aktualisierte Methode.
Belvederef
72

PIL (Python Imaging Library) und Numpy arbeiten gut zusammen.

Ich benutze die folgenden Funktionen.

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 )

Das 'Image.fromarray' ist etwas hässlich, weil ich eingehende Daten in [0,255] schneide, in Bytes konvertiere und dann ein Graustufenbild erstelle. Ich arbeite meistens in grau.

Ein RGB-Bild wäre ungefähr so:

 outimg = Image.fromarray( ycc_uint8, "RGB" )
 outimg.save( "ycc.tif" )
David Poole
quelle
1
Dies schlägt mit einem Fehler fehl. In TypeError: long() argument must be a string or a number, not 'PixelAccess'der Dokumentation zur PIL- PixelAccessKlasse werden anscheinend keine Methoden angeboten, np.arraymit denen die zugrunde liegenden Daten in ein ndarrayFormat konvertiert werden können. Sie müssen die Verwendung von weglassen img.load()und sich nur mit dem Ergebnis von befassen Image.open(...).
ely
Die Datei img.load () umgeht ein seltsames Caching-Problem in PIL. Die Daten werden erst geladen, wenn sie explizit benötigt werden. Das Beispiel funktioniert immer noch für mich, mit der Ausnahme, dass "Bild importieren" in "Bild aus PIL importieren" geändert wird, wenn mit Pillow (der PIL-Gabel) gearbeitet wird.
David Poole
Upvote für die Verwendung nur von PIL und nicht von OpenCV. Ich bin allerdings nicht gegen OpenCV.
Progyammer
54

Sie können hierfür auch matplotlib verwenden .

from matplotlib.image import imread

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

Ausgabe: <class 'numpy.ndarray'>

Rishabh Agrahari
quelle
2
Das ist sehr einfach. Ich mag es :)
jeongmin.cha
@Mrinal Ja, das tut es.
Rishabh Agrahari
18

Ab heute ist es am besten, Folgendes zu verwenden:

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

Sie werden sehen, dass imges sich um ein numpy-Array vom Typ handelt:

<class 'numpy.ndarray'>
belvederef
quelle
12

Späte Antwort, aber ich bin gekommen, um das imageioModul den anderen Alternativen vorzuziehen

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

Ähnlich wie bei der cv2.imread()Erstellung wird standardmäßig ein Numpy-Array erstellt, jedoch in RGB-Form.

slizb
quelle
7

Sie müssen cv.LoadImageM anstelle von cv.LoadImage verwenden:

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
quelle
Vielen Dank ... Könnten Sie mir bitte auch helfen, herauszufinden, ob ich ein Bild mit 'cv.CreateImage (Breite, Höhe, Kanäle)' erstelle ... Wie könnte es in ein Numpy-Array konvertiert werden?
Shan
Ich denke, dass Sie stattdessen cv.CreateMat oder cv.CreateMat verwenden und mit cv.CvtColor oder ähnlichem vom Bild auf die Matte kopieren müssen. Schauen Sie sich den Link an, den Paul oben gepostet hat.
Justin Peel
3

Wenn ich die Antwort von David Poole verwende, erhalte ich einen SystemError mit Graustufen-PNGs und möglicherweise anderen Dateien. Meine Lösung ist:

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

Eigentlich würde img.getdata () für alle Dateien funktionieren, aber es ist langsamer, daher verwende ich es nur, wenn die andere Methode fehlschlägt.

daign
quelle
2

Das OpenCV-Bildformat unterstützt die Numpy-Array-Schnittstelle. Es kann eine Hilfsfunktion eingerichtet werden, die entweder Graustufen- oder Farbbilder unterstützt. Dies bedeutet, dass die BGR -> RGB-Konvertierung bequem mit einem Numpy Slice durchgeführt werden kann, nicht mit einer vollständigen Kopie der Bilddaten.

Hinweis: Dies ist ein Schritttrick. Wenn Sie also das Ausgabearray ändern, werden auch die OpenCV-Bilddaten geändert. Wenn Sie eine Kopie wünschen, verwenden Sie die .copy()Methode für das 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
wim
quelle
1

Ich habe auch imageio übernommen, aber ich fand die folgenden Maschinen nützlich für die Vor- und Nachbearbeitung:

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)

Das Grundprinzip ist, dass ich numpy für die Bildverarbeitung verwende, nicht nur für die Bildanzeige. Zu diesem Zweck sind uint8s umständlich, daher konvertiere ich in Gleitkommawerte zwischen 0 und 1.

Beim Speichern von Bildern fiel mir auf, dass ich die Werte außerhalb des Bereichs selbst schneiden musste, da ich sonst eine wirklich graue Ausgabe erhielt. (Die Grauausgabe war das Ergebnis der Bildkomprimierung des gesamten Bereichs, der außerhalb von [0, 256) lag, auf Werte, die innerhalb des Bereichs lagen.)

Es gab noch ein paar andere Kuriositäten, die ich in den Kommentaren erwähnt habe.

rätselhafter Physiker
quelle
1

Sie können ganz einfach numpy Array von rgb Bild erhalten durch die Verwendung numpyundImage 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
quelle
0

Laden Sie das Bild mit folgender Syntax: -

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
quelle