2009-10-30 14 views
10

Quiero hacer algo de procesamiento de imágenes con OpenCV (en Python), pero tengo que comenzar con un objeto PIL Image, por lo que no puedo usar la llamada cvLoadImage(), ya que toma un nombre de archivo.¿Cómo creo una imagen de OpenCV desde una imagen de PIL?

Esta receta (adaptada de http://opencv.willowgarage.com/wiki/PythonInterface) no funciona porque cvSetData se queja argument 2 of type 'void *'. ¿Algunas ideas?

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

creo que el último argumento de la cvSetData está mal también, pero no estoy seguro de lo que debería ser.

+1

El código que ha escrito en el anterior tiene un nombre no definido en el mismo (cvSetData), por lo que es Es difícil saber si realmente lo probaste. –

+0

@Jonathan: No entiendo el error que mencionaste. cvSetData es de hecho una función válida definida en opencv.cv – Arkady

+0

¿Cuál es el estado de la respuesta, actualmente? –

Respuesta

8

El ejemplo que intentó adaptar es para la nueva interfaz de Python para OpenCV 2.0. Esta es probablemente la fuente de la confusión entre los nombres de funciones prefijadas y no prefijadas (cv.cvSetData() versus cv.SetData()).

OpenCV 2.0 ahora se envía con dos conjuntos de enlaces Python:

  • El "old-style" python wrapper, un paquete de pitón con los opencv.{cv,highgui,ml} módulos
  • El new interface, una extensión pitón C (cv.pyd), que envuelve todo el OpenCV funcionalidades (incluyendo los módulos highgui y ml.)

la razón detrás del mensaje de error es que la envoltura TRAGO per no maneja la conversión de una cadena de python a un búfer C simple. Sin embargo, el contenedor SWIG viene con el módulo opencv.adaptors, que está diseñado para admitir las conversiones de las imágenes numpy y PIL en OpenCV.

La siguiente (probado) código debe resolver su problema original (conversión de PIL a OpenCV), utilizando la interfaz SWIG:

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

Sin embargo, esto no resuelve el hecho de que la función cv.cvSetData() siempre fallará (con la implementación actual de SWIG wrapper). A continuación, puede utilizar la envoltura de nuevo estilo, que le permite utilizar la función cv.SetData() como era de esperar:

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

Un tercer enfoque sería la de cambiar la interfaz de OpenCV pitón a la ctypes-based wrapper. Viene con funciones de utilidad para la conversión explícita de datos entre, p. Ej. cadenas de pitón y almacenamientos intermedios de C Una mirada rápida en google code search parece indicar que este es un método de trabajo.

En cuanto al tercer parámetro de la función cvSetData(), el tamaño del búfer de imagen, pero el paso de la imagen. El paso es la cantidad de bytes en una fila de su imagen, que es pixel_depth * number_of_channels * image_width. El parámetro pixel_depth es el tamaño en bytes de los datos asociados a un canal. En su ejemplo, sería simplemente el ancho de la imagen (solo un canal, un byte por píxel).

+0

@sevas: No he aceptado su respuesta (todavía), porque * estoy * usando la versión 2.0 de OpenCV. La receta de la página a la que me vinculé no funcionó en absoluto hasta que cambié cv.CreateImageHeader a cvCreateImage y cv.SetData a cvSetData, por lo que todavía estoy confundido al respecto. Voy a probar tu enfoque con ctypes-opencv y si eso funciona, publicaré mis hallazgos aquí. – Arkady

+0

@scrible: Agregué información acerca de los dos conjuntos concurrentes de enlaces que se envían con OpenCV 2.0. Sin embargo, probablemente continuaré buscando una mejor solución. –

+0

@scrible: actualicé la respuesta usando la información más reciente que pude encontrar (específicamente, el módulo de adaptadores y los dos conjuntos de enlaces de python.) –

4

Es realmente confuso tener tanto swig como el nuevo enlace de pitón. Por ejemplo, en OpenCV 2.0, cmake puede aceptar tanto BUILD_SWIG_PYTHON_SUPPORT como BUILD_NEW_PYTHON_SUPPORT. Pero de todos modos, descubrí la mayoría de las trampas.

En el caso de utilizar "import cv" (el nuevo enlace de python), se necesita un paso más.

La conversión es necesaria para las imágenes RGB porque la secuencia es diferente en PIL e IplImage. Lo mismo se aplica a Ipl a PIL.

Pero si usa opencv.adaptors, ya está solucionado. Puede mirar los detalles en adaptors.py si está interesado.

3

lo hice utilizando los enlaces de python2.6 OpenCV2.1:

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

La rotación de la imagen y la reversión de la cadena es intercambiar RGB en BGR, que se utiliza en OpenCV de codificación de vídeo. Supongo que esto también sería necesario para cualquier otro uso de una imagen convertida de PIL a OpenCV.

0

no soy un experto, pero me las arreglé para conseguir una imagen de OpenCV partir de una imagen PIL con este código:

import opencv 

img = opencv.adaptors.PIL2Ipl(pilimg) 
Cuestiones relacionadas