Python PIL Image.open和cv2.imdecode之间的差异
我试图理解这两种使用PIL和OpenCV从字节加载图像的方法之间的区别Python PIL Image.open和cv2.imdecode之间的差异,python,opencv,image-processing,python-imaging-library,Python,Opencv,Image Processing,Python Imaging Library,我试图理解这两种使用PIL和OpenCV从字节加载图像的方法之间的区别 def bytes_to_ndarray(bytes): bytes_io = bytearray(bytes) img = Image.open(BytesIO(bytes_io)) return np.array(img) 及 问题是,对于使用OpenCV创建的图像,它们似乎给出了不同的答案。如果image是ndarray,则 bytes = cv2.imencode('.jpg', image
def bytes_to_ndarray(bytes):
bytes_io = bytearray(bytes)
img = Image.open(BytesIO(bytes_io))
return np.array(img)
及
问题是,对于使用OpenCV创建的图像,它们似乎给出了不同的答案。如果image
是ndarray
,则
bytes = cv2.imencode('.jpg', image)
这两种方式将提供不同的输出,例如skimage.data.audion()
PIL将提供:
而OpenCV将返回正确的图像:
简而言之:这只是RGB和BGR通常的订购方式——但是,结合使用OpenCV的
imencode
和imdecode
以及这个特定的图像,一切都变得非常复杂。;-)
skimage.data.audion()
返回带有RGB排序的ndarray
,因为RGB排序是skimage
中的标准。相反,OpenCV在内部使用BGR排序。因此,当我们在保存的PNG图像上使用cv2.imread
时,我们会得到一个带有BGR排序的ndarray
。此外,OpenCV始终假定其所有操作的BGR排序ndarrays
现在,使用cv2.imencode
生成字节流。如上所述,OpenCV假定馈送到该函数的ndarray
具有BGR顺序。这很重要,因为生成的字节流将具有RGB顺序(cv2.imencode
mimicscv2.imwrite
,并且OpenCV正确写入RGB图像)。因此,创建的字节流具有错误的BGR顺序
对于解码,Pillow和OpenCV采用RGB有序字节流。因此,由“枕头方式”创建的ndarray
实际上具有BGR排序(这不是枕头标准),而由OpenCV的imdecode
创建的ndarray
具有RGB排序(这不是OpenCV标准)
最后,Matplotlib(或pyplot)的imshowimshow
假设RGB有序ndarrays
用于可视化。因此,将发生以下情况:
- 显示
中的原始skimage.data.audion()
应该是正确的(RGB顺序)ndarray
- 显示枕式PNG应正确(RGB订购)
- 显示OpenCV加载的PNG应该不正确(BGR已订购)
- 显示解码字节流应不正确(BGR已订购)
- 显示OpenCV解码字节流应该是正确的(RGB顺序)
导入cv2
从io导入字节io
从matplotlib导入pyplot作为plt
将numpy作为np导入
从PIL导入图像
进口撇渣
定义字节到数组(字节):
字节\ io=字节数组(字节)
img=Image.open(字节数)
返回np.array(img)
#skimage返回带有RGB排序的数据数组
img_sk=skiliage.data.audion()
#使用Pillow打开此图像的已保存PNG文件将返回带有RGB排序的ndarray
img_pil=Image.open('automotor.png'))
#使用OpenCV打开此图像的已保存PNG文件将返回带有BGR顺序的ndarray
img_cv=cv2.imread('automation.png',cv2.imread_COLOR)
#OpenCV使用BGR排序,因此OpenCV的编码将img_sk[:,:,0]视为蓝色通道,
#虽然它是实际的红色通道(img_sk[:,:,2]也是如此)
#这意味着,编码的字节流现在具有BGR顺序!!
_,bytes=cv2.imencode('.png',img_sk)
#OpenCV使用BGR排序,但OpenCV的解码假设是RGB排序的字节流,所以
#蓝色通道和红色通道在这里再次交换,这样img_cv再次与
#RGB订购!!
img\u byte\u cv=cv2.imdecode(bytes,cv2.IMREAD\u ANYCOLOR)
#Pillow使用RGB排序,并且还假设RGB排序的字节流,但实际字节
#流是BGR排序的,因此img_pil实际上是BGR排序的一个数组
img_byte_pil=字节到数组(字节)
#Matplotlib pyplot imshow使用RGB排序进行可视化!!
plt.图(figsize=(8,12))
plt.子地块(3,2,1),plt.imshow(img_pil),plt.ylabel(‘PNG加载枕头’)
plt.subplot(3,2,2),plt.imshow(img_cv),plt.ylabel('PNG加载了OpenCV')
plt.子地块(3,2,3),plt.imshow(img_sk),plt.ylabel('装载了撇渣')
plt.subplot(3,2,5),plt.imshow(img_byte_pil),plt.ylabel('用枕头解码')
plt.subplot(3,2,6),plt.imshow(img_byte_cv),plt.ylabel('用OpenCV解码')
plt.show()
等等:
下面是用于复制代码的图像的PNG副本:
底线:当使用OpenCV的imencode
时,确保传递的ndarray
具有BGR顺序
希望有帮助
bytes = cv2.imencode('.jpg', image)