【AI基础】OpenCV,PIL,Skimage你pick谁
汤兴旺
就读于吉林大学汽车工程学院,计算机视觉爱好者,言有三弟子
作者 | 汤兴旺
编辑 | 汤兴旺/言有三
如何对图像进行处理是深度学习图像处理的基础,我们常常需要对图像进行读取、保存、缩放、裁剪、旋转、颜色转换等基本操作。
本文将讲解如何利用opencv、PIL、 scikit-image等进行图像处理,并比较它们之间微小的差异。
01
三大包的基础操作
本节讲解如何利用opencv、PIL、 scikit-image等工具进行图像读取、图像保存、图像缩放、裁剪、旋转、颜色转换等基本操作。
下面将基于下面这张图片演示如何对图形进行基本的处理
1.1 利用PIL处理图像
我们首先从读取图片开始,很多图像处理库(如opencv、skimage)都以imread()读取图片,但是PIL用open方法。
如果我们想要使用PIL来处理图像,必须先导入Image模块,这是进行一切操作的前提。导入方法如下:
from PIL import Image
读取一幅图像
#我的图片是保存在d盘picture文件夹下
img = Image.open('d:/picture/cat.jpg')
执行上述代码返回的结果如下:
怎样才能可视化这个图像呢?
我们需要调用matplotlib这个库,如果没有matplotlib.pyplot中的show()方法,图像只会在内存中,我们当然看不见了。话不多说,代码如下
from PIL import Image
import matplotlib.pyplot as plt
img = Image.open('d:/picture/cat.jpg')
plt.imshow(img)
plt.show()
结果如下:
查看图片信息
哈哈!图片我们已经看到了,这是万里长征的第一步。如果我们想要了解图片格式,大小应该怎么办呢?方法如下:
print(img.format)#查看图片格式
print(img.size)#查看图片大小
print(img.mode)#查看图片模式
我只列举了常用的三个其实还有很多,可以自行搜索
更改图像形式
使用PIL中的crop()方法可以从一幅图像中裁剪指定区域,该区域使用四元组来指定,四元组的的坐标依次是(b1,a1,b2,a2),通常一张图片的左上角为0。示意图如下:
如何对图像进行裁剪,具体代码如下:
裁剪后的图片
调整图片尺寸和旋转
我们可以使用resize()来调整图片尺寸,该方法的参数是一个元组,用来指定图像的大小,代码如下:
#把图片的尺寸改为400x400,tuple里面是图像的weight和height
Img2 = img1.resize((400,400))
调整大小后的图片
要旋转一幅图像,可以使用逆时针方法表示角度,调用rotate()方法,代码如下:
img2 = img1.rotate((45))
旋转后的图片
对图像旋转(旋转90度的整数倍)和翻转也可以用transpose,方法如下:
#左右对换。
img2=img1.transpose(Image.FLIP_LEFT_RIGHT)
#上下对换。
img2=img1.transpose(Image.FLIP_TOP_BOTTOM)
#旋转 90 度角。注意只能旋转90度的整数倍
img2=img1.transpose(Image.ROTATE_90)
左右翻转
上下翻转
图像颜色变化
PIL中可以使用convet()方法来实现图像一些颜色的变化,convert()函数会根据传入参数的不同将图片变成不同的模式。在PIL中有9种模式,如下表所示:
下面我们以灰度图像为例,将目标图像转换成灰度图像,方法如下:
img1 = img.convert('F')#将图片转化为32位浮点灰色图像,结果如下图:
下面再使用skimage和opencv对图像进行基本操作,只附上具体实现代码和注释,效果和上面的其实没什么差别。
1.2 使用skimage对图像处理
#导入io模块
from skimage import io
#以彩色模式读取图片
img=io.imread('d:/picture/cat.jpg')
#以灰色图像模式读取图片
img=io.imread('d:/picture/cat.jpg',as_grey=True)
#将图片保存在c盘,picture文件夹下
io.imsave('c:/picture/cat.jpg')
#将图片的大小变为500x500
img1 = transform.resize(img, (500,500))
#缩小为原来图片大小的0.1
img2 = transform.rescale(img, 0.1)
#缩小为原来图片行数一半,列数四分之一
img3 = transform.rescale(img, [0.5,0.25])
#放大为原来图片大小的2倍
img4 =transform.rescale(img, 2)
#旋转60度,不改变大小
img5 =transform.rotate(img, 60)
#旋转60度,同时改变大小
img6=transform.rotate(img, 60,resize=True)
#将图片调暗,。如果gamma大于1,新图像比原图像暗,如果gamma<1,新图像比原图像亮
img7= exposure.adjust_gamma(img, 4)
#将图片调亮
img8= exposure.adjust_gamma(img, 0.3)
1.3使用opencv对图像进行处理
#导入opencv
import cv2
#读取图片返回的是numpy.array格式
#cv2.imread共两个参数,第一个参数为要读入的图片文件名,第二个参数为如何读取图片,包括cv2.IMREAD_COLOR:读入一副彩色图片;cv2.IMREAD_GRAYSCALE:以灰度模式读入图片;cv2.IMREAD_UNCHANGED:读入一幅图片,并包括其alpha通道。
img = cv2.imread('d:/picture/cat.jpg')
#获取图片属性
print(img.shape)#返回图片的长,宽和通道数
#保存图片,共两个参数,第一个为保存文件名,第二个为读入图片
cv2.imwrite('c:/picture/cat4.jpg',img)
#创建一个窗口显示图片,共两个参数,第一个参数表示窗口名字,可以创建多个窗口中,但是每个窗口不能重名;第二个参数是读入的图片。
cv2.imshow()
#键盘绑定函数,共一个参数,表示等待毫秒数,将等待特定的几毫秒,看键盘是否有输入,返回值为ASCII值。如果其参数为0,则表示无限期的等待键盘输入
cv2.waitKey()
#删除建立的全部窗口
cv2.destroyAllWindows()
删除指定的窗口
cv2.destroyWindows()
#opencv中图像彩色空间变换函数cv2.cvtColor
cv2.cvtColor(input_image,fiag)
参数一: input_image表示将要变换色彩的图像ndarray对象
参数二: 表示图像色彩空间变换的类型,以下介绍常用的两种:
· cv2.COLOR_BGR2GRAY: 表示将图像从BGR空间转化成灰度图,最常用
· cv2.COLOR_BGR2HSV: 表示将图像从RGB空间转换到HSV空间
如果想查看参数flag的全部类型,请执行以下程序便可查阅,总共有274种空间转换类型:
import cv2
flags = [i for i in dir(cv2) if i.startswith('COLOR_')]
print(flags)
02
比较细节差异
2.1读取方式上的不同
我们首先从读取图片开始,PIL用open方法来读取图片,但opencv、skimage都以imread()读取图片。
2.2读进来内容的差异
opencv读进来的图片已经是一个numpy矩阵了,彩色图片维度是(高度,宽度,通道数)。数据类型是uint8;
opencv对于读进来的图片的通道排列是BGR,而不是主流的RGB!谨记!
opencV存储的格式:BGR
PIL读进来的图像是一个对象,而不是我们所熟知的numpy 矩阵
PIL储存的格式
针对PIL读进来的图像是一个对象,那么如何才能将读进来的图片转为矩阵呢,方法如下:
from PIL import Image
import numpy as np
img1 = Image.open('d:/picture/cat.jpg')
arr = np.array(img1)
转换后的格式
skimage读取一张图像时也是以numpy array形式读入skimage的存储格式是RGB。如下图所示:
skimage的存储格式RGB
skimage有一个巨大的不同是读取灰度图时其图像的矩阵的值被归一化了,注意注意!
我们skimage先看读取灰度图的方式,代码如下:
from skimage import io
img=io.imread('d:/picture/cat.jpg',as_grey=True)
读取的结果如下图所示,明显看到被归一化了!
我们再看opencv和PIL读取灰度图时会不会被归一化呢?代码和对比如下:
opencv读取灰度图
import cv2
img=cv2.imread('d:/picture/cat.jpg',cv2.IMREAD_GRAYSCALE)
opencv读取灰度图格式
PIL读取灰度图
from PIL import Image
import numpy as np
img1 = Image.open('d:/picture/cat.jpg').convert('L')
arr = np.array(img1)
PIL读取灰度图格式
从上面的对比可以看出skimage读取灰度图时的巨大不同就是其图像的矩阵的值被归一化了!!!
03
总结
总的来说OpenCV、Skimage、PIL各有千秋。各种框架中进行进行混用,所以我们都必须要掌握,而且要注意区分他们之间微小的差异。