在研究深度学习计算机视觉的时候,经常需要进行图像读取,但是各种第三方库的方法又不一样,用的时候又有点萌萌的,不知道有什么区别,比较常用的就是 OpenCV
和 PIL
的 Image
,但是在格式上也总是有各种各样的问题,所以这一次就好好总结主流Python图像库的一些基本使用方法和需要注意的地方。
1. Opencv
2. PIL(pillow)
3. matplotlib.image
4. scipy.misc
5. skimage
6. Tensorflow
OpenCV作为最常用的图像处理库,实现了图像处理和计算机视觉方面的很多通用算法,可以说是很全面和强大了。如果你只想掌握一个图像库的话,OpenCV是你的最佳选择。
注意:
import cv2
import matplotlib.pyplot as plt
# 读入图片:默认彩色图,cv2.IMREAD_GRAYSCALE灰度图,cv2.IMREAD_UNCHANGED包含alpha通道
img = cv2.imread('2.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换为灰度图
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 转换为RGB
# plt显示图像
plt.subplot(131)
plt.imshow(img)
plt.title('img')
plt.axis('off')
plt.subplot(132)
plt.imshow(gray)
plt.title('gray')
plt.axis('off')
plt.subplot(133)
plt.imshow(img_rgb)
plt.title('img_rgb')
plt.axis('off')
plt.show()
# cv2显示图像
cv2.imshow('src', img)
cv2.imshow('gray', gray)
cv2.imshow('RGB', img_rgb)
print(img.shape) # (h,w,c)
print(img.size) # 像素总数目
print(img.dtype) # 像素类型
print(gray.shape)
print(gray.size)
print(gray.dtype)
cv2.imwrite('test.jpg', img_rgb) # 保存图像
cv2.waitKey() # 一直显示
# (336, 500, 3)
# 504000
# uint8
# (336, 500)
# 168000
# uint8
plt
显示图像:
cv2
显示图像:
细心的同学发现一个问题,plt
和cv2
显示图像颜色恰好是相反的,这是一个接口的问题,因为plt
是RGB接口的,但是cv2
是BGR接口的,所以plt
显示的是正确的颜色,也就是‘BGR’、灰度图、‘RGB’,但是cv2
显示就是相反的颜色。
除此之外,OpenCV 对于读进来的图片的通道排列是 BGR ,而不是主流的 RGB ,这也是它最被人诟病的地方,容易出错,千万要注意。
# opencv读入的矩阵是BGR,转为RGB
# img_cv2(BGR) --> img_rgb(RGB)
img_cv2 = cv2.imread('1.jpg')
img_rgb = cv2.cvtColor(img_cv2, cv2.COLOR_BGR2RGB)
OpenCV 读取灰度图的时候,可以直接参数读取灰度图;或者先读入彩色图,再转灰度图。
import cv2
# 直接参数读取灰度图
gray1 = cv2.imread('1.jpg', cv2.IMREAD_GRAYSCALE) # 灰度图
cv2.imshow('gray1', gray1)
# 也可以这么写,先读入彩色图,再转灰度图
src = cv2.imread('1.jpg')
gray2 = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray2', gray2)
cv2.waitKey()
两种读取灰度图方法的结果是完全相同的。
正常情况下,我们的图片是0-255的,但是有时候我们需要归一化处理为0~1。
# opencv读入的图片矩阵数值是0到255
import cv2
img_norm = cv2.imread('1.jpg')
img_norm = img_norm.astype("float") / 255.0 # 注意需要先转化数据类型为float
print(img_norm.dtype)
print(img_norm)
cv2.imshow('img_norm', img_norm)
cv2.waitKey()
# float64
[[[0.88235294 0.89019608 0.86666667]
[0.88235294 0.88627451 0.87058824]
[0.8745098 0.87843137 0.8627451 ]
...
...
[0. 0.08235294 0.10588235]
[0. 0.02745098 0.04705882]
[0. 0.03137255 0.04313725]]]
OpenCV如何进行存储图片呢?使用cv2.imwrite
函数即可。
# 存储图片
cv2.imwrite('test1.jpg',img_norm) # 得到的是全黑的图片,因为我们把它归一化了
# 所以要得到可视化的图,需要先*255还原
img_test = img_norm * 255
cv2.imwrite('test2.jpg',img_test) # 这样就可以看到彩色原图了
PIL 即 Python Imaging Library,也即为我们所称的 Pillow,已经是 Python 平台事实上的图像处理标准库了。PIL 功能非常强大,但API却非常简单易用。它比 OpenCV 更为轻巧,正因如此,它深受大众的喜爱。
from PIL import Image
import numpy as np
img = Image.open('1.jpg')
print(img.format)
print(img.size) # 注意,省略了通道。 (w,h)
print(img.mode) # L为灰度图,RGB为真彩色,RGBA为加了透明通道
img.show() # 显示图片
gray = img.convert('L') # 转化为灰度图
print(gray.mode) # L为灰度图,RGB为真彩色,RGBA为加了透明通道
gray.show()
# pillow读进来的图片不是矩阵,我们将图片转矩阵
arr = np.array(img)
print(arr.shape)
print(arr.dtype)
print(arr)
# 灰度图的转化与彩图转化一样
arr_gray = np.array(gray)
print(arr_gray.shape)
print(arr_gray.dtype)
print(arr_gray)
# 矩阵再转为图像,进行存储
new_im = Image.fromarray(arr)
new_im.save('test.png')
# JPEG
# (500, 336)
# RGB
# L
# (336, 500, 3)
# uint8
[[[221 227 225]
[222 226 225]
[220 224 223]
...
...
[ 27 21 0]
[ 12 7 0]
[ 11 8 0]]]
# (336, 500)
# uint8
[[224 224 222 ... 223 223 223]
[226 225 224 ... 222 222 222]
[225 225 225 ... 222 222 222]
...
[240 242 245 ... 1 1 5]
[242 239 242 ... 10 2 5]
[236 229 232 ... 20 7 7]]
Matplotlib 是 Python 的 2D 绘图库,它以各种硬拷贝格式和跨平台的交互式环境生成出版质量级别的图形。 它可与 NumPy 一起使用,提供了一种有效的 MatLab 开源替代方案。
import matplotlib.pyplot as plt
image = plt.imread('1.jpg')
plt.imshow(image)
plt.show()
image2 = plt.imread('1.jpg')
plt.imshow(image2)
plt.axis('off') # 也可以关闭显示x,y轴上的数字
plt.show()
# plt.imread读入的就是一个矩阵,跟opencv一样,但彩图读进的是RGB,与opencv有区别
print(image.shape) # (h,w,c)
print(image.size)
print(image.dtype)
print(image)
# (336, 500, 3)
# 504000
# uint8
[[[221 227 225]
[222 226 225]
[220 224 223]
...
...
[ 27 21 0]
[ 12 7 0]
[ 11 8 0]]]
import matplotlib.pyplot as plt
image = plt.imread('1.jpg')
im_r = image[:, :, 0] # 红色通道
plt.imshow(im_r)
plt.show()
# 此时会发现显示的是热量图,不是我们预想的灰度图,可以添加 cmap 参数解决
plt.imshow(im_r, cmap='Greys_r')
plt.show()
# 与opencv结合使用
import cv2
import matplotlib.pyplot as plt
image2 = cv2.imread('1.jpg')
plt.imshow(image2)
plt.axis('off')
plt.show()
# 发现图像颜色怪怪的,原因是我们前面提到的cv2读取图片时的RGB顺序不同的原因,转换一下就可以了
image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2RGB)
plt.imshow(image2)
plt.axis('off')
plt.show()
# 所以无论用什么库读进图片,只要把图片改为矩阵,那么matplotlib就可以处理了
# pillow和matplotlib结合
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
image3 = Image.open('1.jpg')
image3 = np.array(image3)
plt.figure()
plt.imshow(image3)
plt.axis('off')
# 存储图像,注意,必须在show之前savefig,否则存储的图片一片空白
plt.savefig('timo.jpg')
plt.show()
如果先plt.show
,再plt.savefig
,保存的图片就是全白色的。
import matplotlib.pyplot as plt
im_1 = plt.imread('1.jpg')
im_2 = plt.imread('2.jpg')
figure = plt.figure(figsize=(10, 5)) # 调整显示图片的大小
''' figsize参数:指定绘图对象的宽度和高度,单位为英寸; dpi参数指定绘图对象的分辨率,即每英寸多少个像素,缺省值为80。 因此本例中所创建的图表窗口的宽度为10*80 = 800像素 '''
plt.axis("off") # 不显示刻度
ax = figure.add_subplot(121) # 图片以1行2列的形式显示
plt.axis('off')
ax.imshow(im_1) # 第一张图
ax.set_title('image 1') # 给图片加titile
ax = figure.add_subplot(122)
plt.axis('off')
ax.imshow(im_2) # 第二张图
ax.set_title('image 2') # 给图片加titile
plt.savefig('twp.jpg')
plt.show()
from scipy import misc
import matplotlib.pyplot as plt
im = misc.imread('1.jpg')
print(im.dtype)
print(im.size)
print(im.shape)
# 存储图像,这个不需要先存储,和前面不一样
misc.imsave('misc1.png', im)
plt.imshow(im)
plt.show()
print(im)
# uint8
# 504000
# (336, 500, 3)
[[[221 227 225]
[222 226 225]
[220 224 223]
...
...
[ 27 21 0]
[ 12 7 0]
[ 11 8 0]]]
from skimage import io
image = io.imread('1.jpg')
print(image.shape) # numpy矩阵,(h,w,c)
print(image.dtype)
print(image.size)
io.imshow(image)
# 存储图像,这个不需要先存储,和前面不一样
io.imsave('sk.png', image)
io.show()
print(image)
# (336, 500, 3)
# uint8
# 504000
[[[221 227 225]
[222 226 225]
[220 224 223]
...
...
[ 27 21 0]
[ 12 7 0]
[ 11 8 0]]]
from skimage import io
# from skimage import color
image2 = io.imread('1.jpg',as_grey=True) # 读入灰度图
# image3 = io.imread('1.jpg')
# image3 = color.rgb2grey(image3)
''' skimage.color.rgb2grey(rgb) skimage.color.rgb2hsv(rgb) skimage.color.rgb2lab(rgb) skimage.color.gray2rgb(image) skimage.color.hsv2rgb(hsv) skimage.color.lab2rgb(lab) '''
print(image2.dtype)
print(image2.size)
print(image2.shape)
io.imshow(image2)
io.imsave('sk_gray.png',image2)
io.show()
print(image2)
# float64
# 168000
# (336, 500)
[[0.88463059 0.88265843 0.87481529 ... 0.87390667 0.87390667 0.87390667]
[0.89247373 0.88658 0.88265843 ... 0.87307333 0.87307333 0.87307333]
[0.88658 0.88658 0.8843251 ... 0.87253765 0.87253765 0.87253765]
...
[0.94454039 0.95238353 0.96414824 ... 0.00333333 0.00361608 0.01876667]
[0.95238353 0.94061882 0.95238353 ... 0.04138824 0.01061098 0.01872196]
[0.92885412 0.90140314 0.91316784 ... 0.08141529 0.02963843 0.03161059]]
tf.image.decode
是一系列的函数:
tf.image.decode_bmp
channels = ?
0:使用BMP编码图像中的通道数量。
3:输出RGB图像。
4:输出RGBA图像。
tf.image.decode_jpeg
channels = ?
0:使用JPEG编码图像中的通道数量。
1:输出灰度图像。
3:输出RGB图像。
tf.image.decode_png
channels = ?
0:使用PNG编码图像中的通道数量。
1:输出灰度图像。
3:输出RGB图像。
4:输出RGBA图像。
实例推荐博客——TensorFlow图像数据处理函数——图像大小调整(最全面的可运行的代码)
TensorFlow 的读取方式使用的比较少,除了 TensorFlow 之外,大都是比较热门的方法。
除了 OpenCV 读入的彩色图片以 BGR 顺序存储外,其他所有图像库读入彩色图片都以 RGB 存储。
除了 PIL 读入的图片是 img 类之外,其他库读进来的图片都是以 numpy 矩阵。
综合来看,还是 OpenCV 的性能更好,更推荐使用。