Python图像读取方式对比:PIL、OpenCV、Matplotlib与skimage
在Python图像处理中,不同库提供的图像读取函数在返回值类型、通道顺序及数值范围上存在显著差异。本文深入对比PIL、OpenCV、Matplotlib和skimage的读取行为,提供统一显示与通道转换的完整代码方案,解决因通道顺序(RGB/BGR)不同导致的图像显示异常问题。
常见图像读取方式概览
在Python生态中,读取图像文件有多种主流方式。理解它们的底层行为是进行后续处理(如深度学习、图像分析)的基础。主要涉及的库包括PIL、OpenCV、Matplotlib和skimage。
- PIL (Pillow):通过
PIL.Image.open读取,不直接返回NumPy数组,需手动转换。 - OpenCV (cv2):通过
cv2.imread读取,直接返回NumPy数组,但通道顺序为BGR。 - Matplotlib:通过
matplotlib.image.imread读取,直接返回NumPy数组,通道顺序为RGB。 - skimage:通过
skimage.io.imread读取,直接返回NumPy数组,通道顺序为RGB。 - Caffe:通过
caffe.io.load_image读取,本质调用skimage,返回0-1范围的float型数据。
各库读取行为详细对比
为了清晰展示差异,我们将重点分析返回对象类型、通道顺序以及像素值范围。
1. PIL.Image.open
PIL是Python图像处理的标准库之一。调用 Image.open() 时,它返回的是一个PIL Image对象,而非NumPy数组。这意味着如果需要直接使用NumPy进行矩阵运算,必须显式调用 np.array() 进行转换。其通道顺序为标准的RGB,像素值范围通常为0-255(uint8)。
2. OpenCV (cv2.imread)
OpenCV的 cv2.imread() 函数直接返回一个NumPy数组(numpy.ndarray),这简化了后续处理。然而,OpenCV默认以BGR(蓝绿红)顺序读取图像,这与大多数其他库及显示标准(RGB)不同。像素值范围同样为0-255。若直接使用OpenCV读取的图像进行显示,需注意通道转换。
3. Matplotlib (matplotlib.image.imread)
Matplotlib的 mpimg.imread() 函数行为类似于MATLAB,直接返回NumPy数组。其通道顺序为标准的RGB,像素值范围0-255。由于Matplotlib主要用于显示,其读取方式与显示预期一致,通常无需额外转换。
4. skimage (skimage.io.imread)
skimage的 io.imread() 同样直接返回NumPy数组,通道顺序为RGB,像素值范围0-255。值得注意的是,Caffe框架中的 caffe.io.load_image() 函数内部调用了skimage,但它返回的是0-1范围内的float型数据,这在深度学习预处理中较为常见。
完整代码示例与显示处理
以下代码演示了如何统一使用这几种方式读取图像,并通过Matplotlib进行显示。重点展示了如何处理OpenCV读取的BGR图像,使其在显示时正确呈现。
#encoding=utf8
from PIL import Image
import numpy as np
import cv2
import matplotlib.pyplot as plt # plt 用于显示图片
import matplotlib.image as mpimg # mpimg 用于读取图片
import skimage
from skimage import io
# 设置测试图像路径
imagepath='test1.jpg'
# 1. PIL读取
# 注意:PIL.Image.open不直接返回numpy对象,需转换
im1 = Image.open(imagepath)
im1 = np.array(im1) # 转换为numpy对象,通道为RGB
print('PIL Type:', type(im1))
print('PIL Shape:', im1.shape)
# 2. OpenCV读取
# 直接返回numpy.ndarray,但通道顺序为BGR
im2 = cv2.imread(imagepath)
print('OpenCV Type:', type(im2))
print('OpenCV Shape:', im2.shape) # 形状通常为 [width, height, 3]
# 3. Matplotlib读取
# 直接返回numpy.ndarray,通道顺序为RGB
im3 = mpimg.imread(imagepath)
print('Matplotlib Type:', type(im3))
print('Matplotlib Shape:', im3.shape)
# 4. skimage读取
# 直接返回numpy.ndarray,通道顺序为RGB
im4 = io.imread(imagepath)
print('skimage Type:', type(im4))
print('skimage Shape:', im4.shape)
# 统一使用plt进行显示
# 注意:cv2.imshow内部会将BGR转换为RGB显示,但plt.imshow期望RGB
# 因此,对于cv2读取的im2,直接plt.imshow会显示为蓝红颠倒
plt.subplot(221)
plt.title('PIL read (RGB)')
plt.imshow(im1)
plt.subplot(222)
plt.title('OpenCV read (BGR->RGB fix needed for plt)')
# 若要用plt正确显示OpenCV读取的图像,需转换通道:im2[:,:,::-1]
plt.imshow(im2)
plt.subplot(223)
plt.title('Matplotlib read (RGB)')
plt.imshow(im3)
plt.subplot(224)
plt.title('skimage read (RGB)')
plt.imshow(im4)
# plt.axis('off') # 可选:不显示坐标轴
plt.show()运行上述代码后,控制台将输出各库读取图像的类型(均为 <class 'numpy.ndarray'>)和形状(如 (851, 1279, 3))。通过Matplotlib的 plt.show(),可以直观对比不同库读取的图像。需要注意的是,OpenCV读取的图像在Matplotlib中直接显示时,由于通道顺序差异(BGR vs RGB),颜色会出现异常(如蓝色和红色互换)。若需正确显示OpenCV读取的图像,应在显示前进行通道转换:im2[:,:,::-1]。
总结
选择合适的图像读取库取决于具体需求。若需与OpenCV后续处理集成,直接使用 cv2.imread 最为便捷,但需注意BGR通道。若需与Matplotlib显示或大多数深度学习框架兼容,PIL、Matplotlib和skimage提供的RGB通道更为直接。理解这些差异并掌握通道转换技巧,是高效进行Python图像处理的关键。
以上就是Python imread函数详解:PIL、OpenCV、Matplotlib与skimage读取差异对比的详细内容,更多关于Python图像处理库使用技巧的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









