Konwertuj obraz z PIL do formatu openCV


101

Próbuję przekonwertować obraz z PILdo OpenCVformatu. Używam OpenCV 2.4.3. oto co próbowałem do tej pory.

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

Ale myślę, że obraz nie jest konwertowany do formatu CV. Okno pokazuje duży brązowy obraz. Gdzie popełniam błąd podczas konwertowania obrazu z PILna CVformat?

Dlaczego muszę pisać, cv.cvaby uzyskać dostęp do funkcji?




Myślę, że musisz przekonwertować obraz z RGB na BGR. sprawdź, czy działa.
Froyo,

Odpowiedzi:


172

Użyj tego:

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

2
Dzięki, czy możesz mi wyjaśnić szczegółowo, co robi ostatnia linijka?
md1hunox

17
Masz obraz RGB reprezentowany przez tablicę 3D, jak w ex = numpy.array([ [ [1, 2, 3], [4, 5, 6] ], [ [7, 8, 9], [0, 1, 2] ] ]). Podobnie ex[0]jak pierwsza linia obrazu, ex[0][0]pierwsza kolumna pierwszej linii, ex[0][0][0]to czerwony składnik pierwszego piksela, ex[0][0][1]zielony i ex[0][0][2]niebieski. Ponieważ najwyraźniej potrzebujesz obrazu BGR (odwrotna kolejność RGB), odwracasz każdy element, który opisuje piksel, tak jak w ex[0][0][::-1]. Ostatnia linia (oprócz bezużytecznych .copy) jest odpowiednikiem tej operacji dla całego obrazu.
mmgp,

16
Może to być tylko niewielka poprawa wydajności, ale cv2.cvtColor(open_cv_image, cv2.cv.CV_BGR2RGB) jest nieco wydajniejsza.
Guillaume

Jaki był cel wpisania .convert („RGB”) w Twojej odpowiedzi? Pracuję z 16-bitowym obrazem w skali szarości (tryb obrazu = I; 16) .. póki co nparray utrzymuje obraz jako pojedynczy obiekt PIL.Image. (tj. tablica z tylko jednym wpisem, oryginalny PIL.Image)
user391339

3
Jeśli obraz jest binarny (na przykład zeskanowany plik binarny TIF), to tablica numpy będzie taka, boolwięc nie będziesz mógł jej używać z OpenCV. W takim przypadku musisz przekonwertować ją na maskę OpenCV:if image.dtype == bool: image = image.astype(np.uint8) * 255
Maksym Ganenko

99

To najkrótsza wersja, jaką udało mi się znaleźć, zapisująca / ukrywająca dodatkową konwersję:

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

Jeśli czytasz plik z adresu 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)

2
Jeśli pobierasz z adresu URL, import requests response = requests.get(url) opencvImage = imdecode(np.asarray(bytearray(response.content)), 1)
wybrałbym

4
jak ponownie przekonwertować obraz pil na mat?

OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cvtColor
Twoja

Pracuje. Dlaczego wszyscy w świecie Pythona nie podają swojego importu?
pscheit

0

Skomentowany kod również działa, po prostu wybierz, który wolisz

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)

druga metoda polega na konwersji obrazu z PIL na cv2. Opublikowałem dwa sposoby, aby to zrobić, jeden jest w komentarzu. po prostu wybierz, co wolisz. Wysłałem również metodę odwrotną, wiedźma jest pierwszą, która również pokazuje dwa sposoby na zrobienie tego, jeden jest skomentowany, po prostu wybierz to, co wolisz.
Pedro Nunes
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.