众所周知,Python 中有关图像处理的库有很多,常见的有:
- cv2(pip install opencv-python, import cv2)
- skimage(pip install scikit-image, import skimage)
- PIL(pip install Pillow, import PIL)
等等
各个深度学习框架对图像库的偏好
- Pytorch中使用PIL的多,TensorFlow生态中使用OpenCV的多,Caffe和scikit-learn中使用skimage的多;OpenVINO基本使用OpenCV
- 在表示一组彩色图片的问题上,Theano和Caffe使用(样本数,通道数,行或称为高,列或称为宽)通道在前的方式,称为channels_first; TensorFlow使用(样本数,行或称为高,列或称为宽,通道数)通道在后的方式,称为channels_last
PIL vs OpenCV
- PIL以RGB顺序载入图像,OpenCV以BGR顺序载入图像。OpenCV的早期开发人员选择BGR彩色格式的原因是,那时BGR彩色格式在相机制造商和软件提供商中很流行。例如在Windows中,当使用COLORREF指定颜色值时,它们使用BGR格式0x00bbggrr。OpenCV这种反直觉设计是出于历史原因而做出的选择,现在我们必须忍受它。
- 性能上OpenCV吊打PIL,参考benchmark测试数据,请将PIL升级为高性能图像处理库Pillow-SIMD
- 无论如何,学好OpenCV是王道
图像通道顺序的范例程序
from PIL import Image
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 构建彩色图像数据
r = np.ones((20, 10), dtype=np.uint8) * 1
g = np.ones((20, 10), dtype=np.uint8) * 10
b = np.ones((20, 10), dtype=np.uint8) * 100
# 直觉建立起来的图像数据是通道在前
img_np = np.array([r,g,b])
print(img_np.shape) # channels * rows * cols
# PIL要求图像格式是通道在后,即 rows(高)*cols(宽)*Channels(通道数)
img_np = np.moveaxis(img_np, 0, -1)
print(img_np.shape) # rows * cols * channels
img_pil = Image.fromarray(img_np)
print(img_pil) # PIL中的Size是 宽(cols)*高(cols)
#显示图像
plt.imshow(img_pil)
plt.show()
# 将数据写入文件
img_pil.save('img_pil.png')
运行结果:
(3, 20, 10)
(20, 10, 3)
<PIL.Image.Image image mode=RGB size=10x20 at 0x21E54706288>
OpenCV通道范例
img_cv = cv2.imread('img_pil.png')
b,g,r = cv2.split(img_cv) # 分割通道
print(type(img_cv))
print(img_np.shape, r.shape, b.shape, g.shape)
print(r[0],g[0],b[0])
运行结果:
<class 'numpy.ndarray'>
(20, 10, 3) (20, 10) (20, 10) (20, 10)
[1 1 1 1 1 1 1 1 1 1] [10 10 10 10 10 10 10 10 10 10] [100 100 100 100 100 100 100 100 100 100]
结论:
- cv2返回的数据类型是:numpy.ndarray;
- 通道顺序(Channel-Last):rows(高) * cols(宽)* channels(通道数)
- 颜色顺序:BGR