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?

md1hunox
źródło
Odniosłem
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() 
Abhishek Thakur
źródło
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)
Berthier Lemieux
źródło
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)
Pedro Nunes
źródło
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