Преобразование изображения из PIL в формат openCV

95

Я пытаюсь преобразовать изображение из PILв OpenCVформат. Я использую OpenCV 2.4.3. вот что я пытался до сих пор.

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

Но я думаю, что изображение не конвертируется в формат CV. Окно показывает мне большое коричневое изображение. Где я ошибаюсь при преобразовании изображения из PILв CVформат?

Кроме того, почему мне нужно печатать cv.cvдля доступа к функциям?

md1hunox
источник
Возможный дубликат: stackoverflow.com/questions/1650568/…
Тим
Я сослался на вопрос, который вы упомянули, но решение, данное там, похоже, не работает для меня
md1hunox 03
Думаю нужно преобразовать изображение из RGB в BGR. проверьте, работает ли.
Froyo

Ответы:

163

использовать это:

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
Спасибо, не могли бы вы подробно объяснить, что делает последняя строчка?
md1hunox 03
17
У вас есть изображение RGB, представленное трехмерным массивом, как в ex = numpy.array([ [ [1, 2, 3], [4, 5, 6] ], [ [7, 8, 9], [0, 1, 2] ] ]). Итак, ex[0]это первая строка вашего изображения, ex[0][0]это первый столбец первой строки, ex[0][0][0]это красный компонент первого пикселя, ex[0][0][1]зеленый компонент и ex[0][0][2]синий компонент. Поскольку вам, очевидно, нужно изображение BGR (обратный порядок RGB), вы инвертируете каждый элемент, описывающий пиксель, как в ex[0][0][::-1]. Последняя строка (за исключением бесполезной .copy) является эквивалентом этой операции для всего изображения.
mmgp 03
16
Это может быть лишь небольшое улучшение производительности, но cv2.cvtColor(open_cv_image, cv2.cv.CV_BGR2RGB) оно немного более эффективно.
GuillaumeDufay
Какова была цель .convert ('RGB') в вашем ответе? Я работаю с 16-битным изображением в оттенках серого (режим изображения = I; 16) .. пока nparray сохраняет изображение как один объект PIL.Image. (т.е. массив только с одной записью, исходный PIL.Image)
user391339
3
Если изображение двоичное (например, отсканированное двоичное TIF), тогда будет массив numpy, boolи вы не сможете использовать его с OpenCV. В этом случае вам нужно преобразовать его в маску OpenCV:if image.dtype == bool: image = image.astype(np.uint8) * 255
Максим Ганенко
90

Это самая короткая версия, которую я смог найти, с сохранением / скрытием лишнего преобразования:

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

При чтении файла по 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)
Бертье Лемье
источник
1
При загрузке с URL-адреса я бы пошел с:import requests response = requests.get(url) opencvImage = imdecode(np.asarray(bytearray(response.content)), 1)
Лиор
4
как мне снова преобразовать изображение пилота в мат?
Ваш ответ возвращает эту ошибку: OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cvtColor
Ферид Алиджани
работает. Почему все в мире питонов не заявляют о своем импорте?
pscheit