Convertir imagen de formato PIL a openCV

95

Estoy tratando de convertir una imagen PILa OpenCVformato. Estoy usando OpenCV 2.4.3. esto es lo que he intentado hasta ahora.

>>> from PIL import Image
>>> import cv2 as cv
>>> pimg = Image.open('D:\\traffic.jpg')                           #PIL Image
>>> cimg = cv.cv.CreateImageHeader(pimg.size,cv.IPL_DEPTH_8U,3)    #CV Image
>>> cv.cv.SetData(cimg,pimg.tostring())
>>> cv.cv.NamedWindow('cimg')
>>> cv.cv.ShowImage('cimg',cimg)
>>> cv.cv.WaitKey()

Pero creo que la imagen no se convierte al formato CV. La ventana me muestra una gran imagen marrón. ¿Dónde me equivoco al convertir una imagen PILa CVformato?

Además, ¿por qué necesito escribir cv.cvpara acceder a las funciones?

md1hunox
fuente
Me referí a la pregunta que mencionaste, pero la solución dada allí no parece funcionar para mí
md1hunox
Creo que necesitas convertir la imagen de RGB a BGR. compruebe si funciona.
Froyo

Respuestas:

163

utilizar esta:

pil_image = PIL.Image.open('Image.jpg').convert('RGB') 
open_cv_image = numpy.array(pil_image) 
# Convert RGB to BGR 
open_cv_image = open_cv_image[:, :, ::-1].copy() 
Abhishek Thakur
fuente
2
Gracias, ¿podría explicarme en detalle qué hace la última línea?
md1hunox
17
Tiene una imagen RGB representada por una matriz 3d, como en ex = numpy.array([ [ [1, 2, 3], [4, 5, 6] ], [ [7, 8, 9], [0, 1, 2] ] ]). Entonces, ex[0]es la primera línea de su imagen, ex[0][0]es la primera columna de la primera línea, ex[0][0][0]es el componente rojo del primer píxel, ex[0][0][1]es el componente verde y ex[0][0][2]es el componente azul. Dado que aparentemente necesita una imagen BGR (el orden inverso de RGB), invierte cada elemento que describe un píxel como en ex[0][0][::-1]. La última línea (excepto las inútiles .copy) es el equivalente de esta operación para toda la imagen.
mmgp
16
Puede ser solo una ligera mejora en el rendimiento, pero cv2.cvtColor(open_cv_image, cv2.cv.CV_BGR2RGB) es un poco más eficiente.
GuillaumeDufay
¿Cuál fue el propósito de .convert ('RGB') en su respuesta? Estoy trabajando con una imagen en escala de grises de 16 bits (modo de imagen = I; 16) ... hasta ahora, nparray mantiene la imagen como un solo objeto PIL.Image. (es decir, una matriz con una sola entrada, el PIL.Image original)
user391339
3
Si la imagen es binaria (por ejemplo, binaria escaneada TIF), entonces la matriz numpy lo será, boolpor lo que no podrá usarla con OpenCV. En este caso, debe convertirlo a la máscara OpenCV:if image.dtype == bool: image = image.astype(np.uint8) * 255
Maksym Ganenko
90

Esta es la versión más corta que pude encontrar, guardando / ocultando una conversión adicional:

pil_image = PIL.Image.open('image.jpg')
opencvImage = cv2.cvtColor(numpy.array(pil_image), cv2.COLOR_RGB2BGR)

Si lee un archivo de una URL:

import cStringIO
import urllib
file = cStringIO.StringIO(urllib.urlopen(r'http://stackoverflow.com/a_nice_image.jpg').read())
pil_image = PIL.Image.open(file)
opencvImage = cv2.cvtColor(numpy.array(pil_image), cv2.COLOR_RGB2BGR)
Berthier Lemieux
fuente
1
Si descarga desde la url, iría con:import requests response = requests.get(url) opencvImage = imdecode(np.asarray(bytearray(response.content)), 1)
Lior
4
¿Cómo convierto la imagen pil a mat de nuevo?
Nuestra respuesta devuelve este error: OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cvtColor
Färid Alijani
trabajos. ¿Por qué todo el mundo en el mundo de las pitones no declara sus importaciones?
pscheit