Converter imagem de PIL para o formato openCV

101

Estou tentando converter a imagem PILpara o OpenCVformato. Estou usando OpenCV 2.4.3. aqui está o que tentei até agora.

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

Mas acho que a imagem não está sendo convertida para o formato CV. A janela me mostra uma grande imagem marrom. Onde estou errado ao converter imagem de PILpara CVformato?

Além disso, por que preciso digitar cv.cvpara acessar as funções?

md1hunox
fonte
Possível duplicata: stackoverflow.com/questions/1650568/…
Tim
Eu me referi à pergunta que você mencionou, mas a solução apresentada não parece funcionar para mim
md1hunox
Acho que você precisa converter a imagem RGB para BGR. verifique se funciona.
Froyo

Respostas:

172

usa isto:

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
fonte
2
Obrigado, você pode me explicar o que a última linha faz em detalhes?
md1hunox
17
Você tem uma imagem RGB representada por uma matriz 3D, como em ex = numpy.array([ [ [1, 2, 3], [4, 5, 6] ], [ [7, 8, 9], [0, 1, 2] ] ]). Assim ex[0]é a primeira linha da sua imagem, ex[0][0]é a primeira coluna da primeira linha, ex[0][0][0]é o componente vermelho do primeiro pixel, ex[0][0][1]é o componente verde e ex[0][0][2]é o componente azul. Como aparentemente você precisa de uma imagem BGR (a ordem inversa de RGB), você inverte cada elemento que descreve um pixel como em ex[0][0][::-1]. A última linha (exceto para o inútil .copy) é o equivalente a esta operação para a imagem inteira.
mmgp
16
Pode ser apenas uma ligeira melhoria de desempenho, mas cv2.cvtColor(open_cv_image, cv2.cv.CV_BGR2RGB) é um pouco mais eficiente.
GuillaumeDufay,
Qual foi o propósito de .convert ('RGB') em sua resposta? Estou trabalhando com uma imagem em tons de cinza de 16 bits (modo de imagem = I; 16) .. até agora o nparray está mantendo a imagem como um único objeto PIL.Image. (ou seja, uma matriz com apenas uma entrada, a PIL.Image original)
usuário391339
3
Se a imagem for binária (por exemplo, binária digitalizada TIF), o array numpy será boole, portanto, você não poderá usá-lo com o OpenCV. Neste caso, você precisa convertê-lo para a máscara OpenCV:if image.dtype == bool: image = image.astype(np.uint8) * 255
Maksym Ganenko
99

Esta é a versão mais curta que consegui encontrar, salvando / ocultando uma conversão extra:

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

Se estiver lendo um arquivo de um 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
fonte
2
Se estivesse baixando de url, eu iria com:import requests response = requests.get(url) opencvImage = imdecode(np.asarray(bytearray(response.content)), 1)
Lior
4
como faço para converter a imagem pil para tapete novamente?
nossa resposta retorna este erro: OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cvtColor
Färid Alijani
trabalho. Por que todo mundo no mundo python não declara suas importações?
pscheit
0

O código comentado também funciona

import numpy as np
from PIL import Image


def convert_from_cv2_to_image(img: np.ndarray) -> Image:
    # return Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    return Image.fromarray(img)


def convert_from_image_to_cv2(img: Image) -> np.ndarray:
    # return cv2.cvtColor(numpy.array(img), cv2.COLOR_RGB2BGR)
    return np.asarray(img)
Pedro Nunes
fonte
O solicitante queria converter uma imagem de PIL para OpenCV. Comentar essa seção não consegue isso. Em vez disso, ele simplesmente retorna a imagem no mesmo formato PIL
DapperDuck