【问题标题】:Convert image from PIL to openCV format将图像从 PIL 转换为 openCV 格式
【发布时间】:2012-12-17 13:52:37
【问题描述】:

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

【问题讨论】:

  • 我提到了你提到的问题,但那里给出的解决方案似乎对我不起作用
  • 我认为您需要将图像从 RGB 转换为 BGR。检查它是否有效。

标签: python image-processing opencv python-imaging-library


【解决方案1】:

使用这个:

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

【讨论】:

  • 谢谢,你能详细解释一下最后一行的作用吗?
  • 您有一个由 3d 数组表示的 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)相当于整个图片的这个操作。
  • 这可能只是轻微的性能提升,但cv2.cvtColor(open_cv_image, cv2.cv.CV_BGR2RGB) 效率更高。
  • 您回答中 .convert('RGB') 的目的是什么?我正在使用 16 位灰度图像(图像模式=I;16).. 到目前为止,nparray 将图像保持为单个 PIL.Image 对象。 (即,只有一个条目的数组,原始 PIL.Image)
  • 如果图像是二进制的(例如,扫描的二进制TIF),那么 numpy 数组将为bool,因此您将无法在 OpenCV 中使用它。在这种情况下,您需要将其转换为 OpenCV 掩码:if image.dtype == bool: image = image.astype(np.uint8) * 255
【解决方案2】:

这是我能找到的最短的版本,保存/隐藏额外的转换:

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)

【讨论】:

  • 如果从 url 下载,我会选择:import requestsresponse = requests.get(url)opencvImage = imdecode(np.asarray(bytearray(response.content)), 1)
  • 如何将 pil 图像再次转换为 mat?
  • 你的答案返回此错误:OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cvtColor
  • 有效。为什么 python 世界中的每个人都没有说明它的导入?
【解决方案3】:

注释的代码也可以,只需选择您喜欢的代码

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)

【讨论】:

  • 第二种方法就是将图像从 PIL 转换为 cv2。我已经发布了两种方法,一种是在评论中。只需选择您喜欢的。我还发布了一个相反的方法,女巫是第一个,这也显示了两种方法,一种是评论,选择你喜欢的。
【解决方案4】:

这里有两个函数可以在 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 img 转换为 PIL img 会丢失透明通道。虽然将 PIL img 转换为 OpenCV img 将能够保持透明通道,虽然 cv2.imshow 不显示它但保存为 png 会正常给出结果。

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

【讨论】:

    猜你喜欢
    • 2017-08-31
    • 2014-05-21
    • 2016-05-29
    • 1970-01-01
    • 2014-05-24
    • 2020-07-13
    • 2012-11-14
    • 2015-12-31
    相关资源
    最近更新 更多