将图像从PIL格式转换为openCV格式

167
我正在尝试将图像从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来访问函数?

可能是重复问题:https://dev59.com/PHI-5IYBdhLWcg3w1sTi - Tim
1
我参考了你提到的问题,但是那里给出的解决方案似乎对我不起作用。 - md1hunox
我认为你需要将图像从RGB转换为BGR。检查一下是否有效。 - Froyo
5个回答

266
使用这个:
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()

3
谢谢,请问您能详细解释一下最后一行的作用吗? - md1hunox
22
你有一张由三维数组表示的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
24
虽然只有轻微的性能提升,但是使用 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 - Maksym Ganenko
显示剩余5条评论

166

这是我能找到的最短版本,可以省略/隐藏一个额外的转换:

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)

2
如果从URL下载,我会使用以下代码:import requests response = requests.get(url) opencvImage = imdecode(np.asarray(bytearray(response.content)), 1) - Lior
5
如何将PIL图像转换回mat格式? - user3600801
1
您的答案返回以下错误:OpenCV错误:在cvtColor中断言失败(scn == 3 || scn == 4) - Farid Alijani
1
为什么Python世界中的每个人都不声明其导入,但代码还是能正常工作呢? - pscheit

25
代码被注释后同样有效,选择哪种方式取决于您的个人喜好。
import numpy as np
from PIL import Image


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


def convert_from_image_to_cv2(img: Image) -> np.ndarray:
    # return np.asarray(img)
    return cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)

1
第二种方法可以将PIL中的图像转换为cv2格式。我已经发布了两种方法,其中一种在注释中。只需选择您喜欢的即可。我还发布了一种相反的方法,即第一种方法,它也展示了两种方法,其中一种被注释了。只需选择您喜欢的即可。 - Pedro Nunes

2
将Pillow图像转换为OpenCV图像:
cv2_img = np.array(pil_img)
cv2_img = cv2.cvtColor(cv2_img, cv2.COLOR_RGB2BGR)

将OpenCV图像转换为Pillow图像:

cv2_img = cv2.cvtColor(cv2_img, cv2.COLOR_BGR2RGB)
pil_img = Image.fromarray(cv2_img)

来源:https://medium.com/analytics-vidhya/the-ultimate-handbook-for-opencv-pillow-72b7eff77cd7

这是一本关于OpenCV和Pillow的终极手册。OpenCV是一个流行的计算机视觉库,而Pillow是Python中最常用的图像处理库之一。本手册旨在帮助读者了解如何使用这两个库来完成各种图像处理任务。


1
以下是两个函数,用于在PIL和OpenCV之间转换图像:
def toImgOpenCV(imgPIL): # Conver imgPIL to imgOpenCV
    i = np.array(imgPIL) # After mapping from PIL to numpy : [R,G,B,A]
                         # numpy Image Channel system: [B,G,R,A]
    red = i[:,:,0].copy(); i[:,:,0] = i[:,:,2].copy(); i[:,:,2] = red;
    return i; 

def toImgPIL(imgOpenCV): return Image.fromarray(cv2.cvtColor(imgOpenCV, cv2.COLOR_BGR2RGB));

将OpenCV图像转换为PIL图像会丢失透明通道。而将PIL图像转换为OpenCV图像则能保留透明通道,尽管cv2.imshow不能显示它,但保存为png格式将正常显示结果。

  • 您可以调用cv2.imwrite("./" + "fileName.png", img);导出并检查OpenCV图像的透明结果。
  • 或者toImgPIL(img).save('test.png', 'PNG')来检查PIL图像。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接