2009-10-30 22 views
10

Ich möchte einige Bildverarbeitung mit OpenCV (in Python), aber ich muss mit einem PIL Image Objekt beginnen, so kann ich nicht den cvLoadImage() Aufruf verwenden, da das einen Dateinamen nimmt.Wie erstelle ich ein OpenCV-Bild aus einem PIL-Bild?

Dieses Rezept (angepasst von http://opencv.willowgarage.com/wiki/PythonInterface) funktioniert nicht, weil cvSetData klagt argument 2 of type 'void *'. Irgendwelche Ideen?

from opencv.cv import * 
from PIL import Image 

pi = Image.open('foo.png')      # PIL image 
ci = cvCreateImage(pi.size, IPL_DEPTH_8U, 1)  # OpenCV image 
data = pi.tostring() 
cvSetData(ci, data, len(data)) 

Ich denke, das letzte Argument der cvSetData auch falsch ist, aber ich bin nicht sicher, was es sein sollte.

+1

Der Code, den Sie in oben getippt einen nicht definierten Namen hat in ihm (cvSetData), so ist es schwer zu wissen, ob du es tatsächlich versucht hast. –

+0

@ Jonathan: Ich bekomme nicht den Fehler, den Sie erwähnten. cvSetData ist in der Tat eine gültige Funktion definiert in opencv.cv – Arkady

+0

Was ist der Status der Antwort, derzeit? –

Antwort

8

Das Beispiel, das Sie anpassen wollten, ist für die neue Python-Schnittstelle für OpenCV 2.0. Dies ist wahrscheinlich die Quelle der Verwechslung zwischen den vorangestellten und nicht vorangestellten Funktionsnamen (cv.cvSetData() gegenüber cv.SetData()).

OpenCV 2.0 jetzt Schiffe mit zwei Sätzen von Python-Bindungen:

  • Die "old-style" python wrapper, ein Python-Paket mit dem opencv.{cv,highgui,ml} Module
  • Die new interface, ein Python C Verlängerung (cv.pyd), die wickelt alle OpenCV Funktionen (einschließlich der highgui und ml Modulen.)

der Grund für die Fehlermeldung ist, dass der Wickel SWIG per behandelt keine Konvertierung von einer Python-Zeichenfolge in einen einfachen alten C-Puffer. Der SWIG-Wrapper wird jedoch mit dem Modul opencv.adaptors geliefert, das Konvertierungen von numpy und PIL Images zu OpenCV unterstützt.

Der folgende (getestet) Code sollte Ihr ursprüngliches Problem (Umwandlung von PIL zu OpenCV) unter Verwendung der SWIG Schnittstelle lösen:

# PIL to OpenCV using the SWIG wrapper 
from opencv import cv, adaptors, highgui 
import PIL 

pil_img = PIL.Image.open(filename) 

cv_img = adaptors.PIL2Ipl(pil_img) 

highgui.cvNamedWindow("pil2ipl") 
highgui.cvShowImage("pil2ipl", cv_img) 

Dies ist jedoch nicht die Tatsache löst, dass die cv.cvSetData() Funktion wird immer scheitern (mit der aktuellen SWIG-Wrapper-Implementierung). Sie könnten dann den neuen Stil-Wrapper verwenden, mit dem Sie die cv.SetData() Funktion verwenden können, wie man erwarten würde:

# PIL to OpenCV using the new wrapper 
import cv 
import PIL 

pil_img = PIL.Image.open(filename)  

cv_img = cv.CreateImageHeader(pil_img.size, cv.IPL_DEPTH_8U, 3) # RGB image 
cv.SetData(cv_img, pil_img.tostring(), pil_img.size[0]*3) 

cv.NamedWindow("pil2ipl") 
cv.ShowImage("pil2ipl", cv_img) 

Ein dritter Ansatz wäre Ihre OpenCV Python-Schnittstelle zum ctypes-based wrapper zu wechseln. Es kommt mit Hilfsfunktionen zur expliziten Datenkonvertierung zwischen z.B. Python-Strings und C-Puffer. Ein kurzer Blick auf google code search scheint darauf hinzuweisen, dass dies eine Arbeitsmethode ist.

Bezüglich des dritten Parameters der cvSetData() Funktion, Größe des Bildpuffers, aber der Bildschritt. Der Schritt ist die Anzahl der Bytes in einer Zeile Ihres Bildes, also pixel_depth * number_of_channels * image_width. Der Parameter pixel_depth ist die Größe der Daten in Byte, die einem Kanal zugeordnet sind. In Ihrem Beispiel wäre es einfach die Bildbreite (nur ein Kanal, ein Byte pro Pixel).

+0

@sevas: Ich habe deine Antwort (noch) nicht akzeptiert, weil ich Version 2.0 von OpenCV verwende. Das Rezept auf der Seite, mit der ich verlinkt habe, funktionierte überhaupt nicht, bis ich cv.CreateImageHeader zu cvCreateImage und cv.SetData zu cvSetData änderte, also bin ich immer noch verwirrt darüber. Ich werde Ihren Ansatz mit ctypes-opencv versuchen und wenn das funktioniert, werde ich meine Ergebnisse hier veröffentlichen. – Arkady

+0

@scrible: Ich habe Informationen über die zwei gleichzeitigen Sätze von Bindungen hinzugefügt, die mit OpenCV 2.0 ausgeliefert werden. Ich werde wahrscheinlich weiterhin nach einer besseren Lösung suchen. –

+0

@ scrible: Ich aktualisierte die Antwort mit den neuesten Informationen, die ich finden konnte (speziell das Modul Adaptoren und die zwei Sätze von Python-Bindungen.) –

4

Es ist wirklich verwirrend, sowohl swig als auch neue Python-Bindung zu haben. Zum Beispiel kann cmake in OpenCV 2.0 sowohl BUILD_SWIG_PYTHON_SUPPORT als auch BUILD_NEW_PYTHON_SUPPORT akzeptieren. Aber irgendwie habe ich die meisten Fallstricke herausgefunden.

Wenn "Import cv" (die neue Python-Bindung) verwendet wird, ist ein weiterer Schritt erforderlich.

Die Konvertierung ist für RGB-Bilder erforderlich, da die Reihenfolge in PIL und IplImage unterschiedlich ist. Gleiches gilt für Ipl zu PIL.

Aber wenn Sie opencv.adaptors verwenden, ist es schon erledigt. Wenn Sie interessiert sind, können Sie sich die Details in adaptors.py ansehen.

3

Ich tat dies die python2.6 Bindungen von OpenCV2.1 mit:

... 
    cv_img = cv.CreateImageHeader(img.size, cv.IPL_DEPTH_8U, 3) 
    cv.SetData(cv_img, img.rotate(180).tostring()[::-1]) 
    ... 

Die Bilddrehung und Reversion der Zeichenfolge RGB in BGR zu tauschen, dass in OpenCV Videocodierung verwendet wird. Ich nehme an, dass dies auch für jede andere Verwendung eines von PIL nach OpenCV konvertierten Bildes notwendig wäre.

0

Ich bin kein Experte, aber ich schaffte es mit diesem Code ein opencv Bild von einem PIL Bild zu bekommen:

import opencv 

img = opencv.adaptors.PIL2Ipl(pilimg) 
Verwandte Themen