一:基本概念
1.1 颜色与RGBA值
计算机通常将图像表示为RGB值,或者再加上alpha值(通透度,透明度),称为RGBA值。
在Pillow中,RGBA的值表示为由4个整数组成的元组,分别是R、G、B、A。整数的范围0~255。RGB全0就可以表示黑色,全255代表黑色。可以猜测(255, 0, 0, 255)代表红色,因为R分量最大,G、B分量为0,所以呈现出来是红色。但是当alpha值为0时,无论是什么颜色,该颜色都不可见,可以理解为透明。
from PIL import ImageColor
print(ImageColor.getcolor('red', 'RGBA'))
# 也可以只以RBG的方式查看
print(ImageColor.getcolor('black', 'RGB'))
(255, 0, 0, 255)
(0, 0, 0)
1.2 图像的坐标表示
图像中
左上角
是坐标原点(0, 0),这和平常数学里的坐标系不太一样。这样定义的坐标系意味着,X轴是从左到右增长的,而Y轴是从上到下增长。
在Pillow中如何使用上述定义的坐标系表示一块矩形区域?许多函数或方法要求提供一个矩形元组参数。元组参数包含四个值,分别代表矩形四条边的距离X轴或者Y轴的距离。顺序是
(左,顶,右,底)
。右和底坐标稍微特殊,表示直到但不包括。可以理解为
[左, 右)
和
[顶, 底)
这样左闭右开的区间。比如(3, 2, 8, 9)就表示了横坐标范围[3, 7];纵坐标范围[2, 8]的矩形区域。
二:Pillow的安装
三:Pillow(PIL)简单的图像操作
3.1 使用Pillow操作图像
from PIL import Image
im_path = r'F:\Jupyter Notebook\csv_time_datetime_PIL\rabbit.jpg'
im = Image.open(im_path)
width, height = im.size
# 宽高
print(im.size, width, height)
# 格式,以及格式的详细描述
print(im.format, im.format_description)
im.save(r'C:\Users\Administrator\Desktop\rabbit_copy.jpg')
im.show()
(1920, 1080) 1920 1080
JPEG JPEG (ISO 10918)
im.size
返回一个元组,分别是宽和高。
show()
方法会调用系统默认图像查看软件,打开并显示。
im.format
可查看图像的格式。
save()
可保存处理后的图片,如果未经处理,保存后的图像占用的空间(字节数)一般也与原图像不一样,可能经过了压缩。
3.2新建图像
Pillow也可以新建空白图像, 第一个参数是mode即颜色空间模式,第二个参数指定了图像的分辨率(宽x高),第三个参数是颜色。
-
可以直接填入常用颜色的名称。如'red'
-
也可以填入十六进制表示的颜色,如
#FF0000
表示红色。
-
还能传入元组,比如(255, 0, 0, 255)或者(255, 0, 0)表示红色。
# 通常使用RGB模式就可以了
newIm= Image.new('RGB', (100, 100), 'red')
newIm.save(r'C:\Users\Administrator\Desktop\1.png')
# 也可以用RGBA模式,还有其他模式查文档吧
blcakIm = Image.new('RGB',(200, 100), 'red')
blcakIm.save(r'C:\Users\Administrator\Desktop\2.png')
# 十六进制颜色
blcakIm = Image.new('RGBA',(200, 100), '#FF0000')
blcakIm.save(r'C:\Users\Administrator\Desktop\3.png')
# 传入元组形式的RGBA值或者RGB值
# 在RGB模式下,第四个参数失效,默认255,在RGBA模式下,也可只传入前三个值,A值默认255
blcakIm = Image.new('RGB',(200, 100), (255, 255, 0, 120))
blcakIm.save(r'C:\Users\Administrator\Desktop\4.png')
3.3 裁剪图像
Image
有个
crop()
方法接收一个矩形区域元组(上面有提到)。返回一个新的Image对象,是裁剪后的图像,对原图没有影响。
im = Image.open(im_path)
cropedIm = im.crop((700, 100, 1200, 1000))
cropedIm.save(r'C:\Users\Administrator\Desktop\cropped.png')
3.4 复制与粘贴图像到另一个图像
Image
的
copy
函数如其名会产生一个原图像的副本,在这个副本上的任何操作不会影响到原图像。
paste()
方法用于将一个图像粘贴(覆盖)在另一个图像上面。谁调用它,他就在该Image对象上直接作修改。
im = Image.open(im_path)
cropedIm = im.crop((700, 100, 1200, 1000))
im.paste(cropedIm, (0, 0))
im.show()
im.save(r'C:\Users\Administrator\Desktop\paste.png')
im.show()
显示图像发现这时im(即原图)已经被改变。
这如果之后还会用到原图的信息,由于信息被改变就很麻烦。所以paste前最好使用
copy()
复制一个副本,在此副本操作,不会影响到原图信息。虽然在程序里原图信息已改变,但由于保存文件时用的其他文件名,相当于改变没有生效,所以查看的时候原图还是没有改变的。
im = Image.open(im_path)
cropedIm = im.crop((700, 100, 1200, 1000))
copyIm = im.copy()
copyIm.paste(cropedIm, (0, 0))
im.show()
copyIm.save(r'C:\Users\Administrator\Desktop\paste.png')
im = Image.open(im_path)
cropedIm = im.crop((700, 100, 1200, 1000))
crop_width, crop_height = cropedIm.size
width, height = im.size
copyIm = im.copy()
for left in range(0, width, crop_width):
for top in range(0, height, crop_height):
copyIm.paste(cropedIm, (left, top))
copyIm.save(r'C:\Users\Administrator\Desktop\dupli-rabbit.png')
以裁剪后的图像宽度和高度为间隔,在循环内不断粘贴在副本中,这有点像是在拍证件照。
3.5 调整图像的大小
resize
方法返回指定宽高度的新Image对象,接受一个含有宽高的元组作为参数。
宽高的值得是整数。
im = Image.open(im_path)
width, height = im.size
resizedIm = im.resize((width, height+(1920-1080)))
resizedIm.save(r'C:\Users\Administrator\Desktop\resize.png')
resize不是等比例缩放的。图像可能有宽度或者高度的压缩。
3.6 旋转和翻转图像
rotate()
返回旋转后的新Image对象, 保持原图像不变。逆时针旋转。
im = Image.open(im_path)
im.rotate(90).save(r'C:\Users\Administrator\Desktop\rotate90.png')
im.rotate(270).save(r'C:\Users\Administrator\Desktop\rotate270.png')
im.rotate(180).save(r'C:\Users\Administrator\Desktop\rotate180.png')
im.rotate(20).save(r'C:\Users\Administrator\Desktop\rotate20.png')
im.rotate(20, expand=True).save(r'C:\Users\Administrator\Desktop\rotate20_expand.png')
由上到下,分别是旋转了90°,180°, 270°、普通的20°,加了参数
expand=True
旋转的20°。
im90 = Image.open(r'C:\Users\Administrator\Desktop\rotate90.png')
im270 = Image.open(r'C:\Users\Administrator\Desktop\rotate270.png')
# 宽高信息并没有改变
print(im90.size, im270.size)
(1920, 1080) (1920, 1080)
图像的镜面翻转。
transpose()
函数可以实现,必须传入
Image.FLIP_LEFT_RIGHT
或者
Image.FLIP_TOP_BOTTOM
,第一个是水平翻转,第二个是垂直翻转。
im = Image.open(im_path)
im.transpose(Image.FLIP_LEFT_RIGHT).save(r'C:\Users\Administrator\Desktop\transepose_lr.png')
im.transpose(Image.FLIP_TOP_BOTTOM).save(r'C:\Users\Administrator\Desktop\transepose_tb.png')
3.7 图像过滤
Pillow使用ImageFilter可以简单做到图像的模糊、边缘增强、锐利、平滑等常见操作。
from PIL import Image, ImageFilter
im = Image.open(im_path)
# 高斯模糊
im.filter(ImageFilter.GaussianBlur).save(r'C:\Users\Administrator\Desktop\GaussianBlur.jpg')
# 普通模糊
im.filter(ImageFilter.BLUR).save(r'C:\Users\Administrator\Desktop\BLUR.jpg')
# 边缘增强
im.filter(ImageFilter.EDGE_ENHANCE).save(r'C:\Users\Administrator\Desktop\EDGE_ENHANCE.jpg')
# 找到边缘
im.filter(ImageFilter.FIND_EDGES).save(r'C:\Users\Administrator\Desktop\FIND_EDGES.jpg')
# 浮雕
im.filter(ImageFilter.EMBOSS).save(r'C:\Users\Administrator\Desktop\EMBOSS.jpg')
# 轮廓
im.filter(ImageFilter.CONTOUR).save(r'C:\Users\Administrator\Desktop\CONTOUR.jpg')
# 锐化
im.filter(ImageFilter.SHARPEN).save(r'C:\Users\Administrator\Desktop\SHARPEN.jpg')
# 平滑
im.filter(ImageFilter.SMOOTH).save(r'C:\Users\Administrator\Desktop\SMOOTH.jpg')
# 细节
im.filter(ImageFilter.DETAIL).save(r'C:\Users\Administrator\Desktop\DETAIL.jpg')
另外,若是要进行图案、文字的绘制,可使用ImageDraw。
Pillow还有其他强大功能,就不一一列举了。其实,Pillow只是个基础的图像处理库。若不深入图像处理,已经够用。专业人士使用opencv是更好地选择。
四:图像的格式种类以及转换
PIL中有九种不同模式。分别为
1,L,P,RGB,RGBA,CMYK,YCbCr,I,F
。
对于彩色图像,不管其图像格式是PNG,还是BMP,或者JPG,在PIL中,使用Image模块的open()函数打开后,返回的图像对象的模式都是“RGB”。
而对于灰度图像,不管其图像格式是PNG,还是BMP,或者JPG,打开后,其模式为“L”。
五:PIL进行图像转换具体转换
原图像:
5.1 模式“1”---二值图像
模式“1”为二值图像,非黑即白。但是它每个像素用8个bit表示,0表示黑,255表示白。下面我们将lena图像转换为“1”图像。
from PIL import Image
im = Image.open("./g.png")
print(im.mode)
print(im.size)
print(im.getpixel((0,0))) #获取指定点处的像素值
im_1 = im.convert("1")
print(im_1.mode)
print(im_1.size)
print(im_1.getpixel((0,0)))
print(im_1.getpixel((140,140)))
im_1.show()
RGB
(286, 289)
(156, 169, 193)
1
(286, 289)
255
0
5.2 模式“L”---灰度图像
模式“L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。在PIL中,从模式“RGB”转换为“L”模式是按照下面的公式转换的:
L = R * 299/1000 + G * 587/1000+ B * 114/1000
im_L = im.convert("L")
RGB
(286, 289)
(156, 169, 193)
L
(286, 289)
167
86 #156*299/1000+169*587/1000+193*114/1000 ---> 46.644+99.203+22.002 ---> 167.849 PIL中只取了整数部分
5.3 模式“P”---八位彩色图像,色彩值由调色板查询
模式“P”为8位彩色图像,它的每个像素用8个bit表示,其对应的彩色值是按照调色板查询出来的。
RGB
(286, 289)
(156, 169, 193)
P
(286, 289)
175
96
5.4 模式“RGBA”---4通道RGB和alpha透明道
模式“RGBA”为32位彩色图像,它的每个像素用32个bit表示,其中24bit表示红色、绿色和蓝色三个通道,另外8bit表示alpha通道,即透明通道。
im_RGBA = im.convert("RGBA")
RGB
(286, 289)
(156, 169, 193)
RGBA
(286, 289)
(156, 169, 193, 255) #4通道,默认将RGB图像转RGBA时,alpha通道为255
(91, 85, 83, 255)
5.5 模式“CMYK”---印刷四分色模式(C青色M品红Y黄色K黑色)
模式“CMYK”为32位彩色图像,它的每个像素用32个bit表示。模式“CMYK”就是印刷四分色模式,它是彩色印刷时采用的一种套色模式,利用色料的三原色混色原理,加上黑色油墨,共计四种颜色混合叠加,形成所谓“全彩印刷”。
四种标准颜色是:C:Cyan = 青色,又称为‘天蓝色’或是‘湛蓝’M:Magenta = 品红色,又称为‘洋红色’;Y:Yellow = 黄色;K:Key Plate(blacK) = 定位套版色(黑色)。
im_CMYK = im.convert("CMYK")
RGB
(286, 289)
(156, 169, 193)
CMYK
(286, 289)
(99, 86, 62, 0)
(164, 170, 172, 0)
转换公式
C = 255 - R
M = 255 - G
Y = 255 - B
K = 0
由于该转换公式比较简单,转换后的图像颜色有些失真。
5.6 模式“YCbCr”---24位(Y亮度Cb蓝色色度Cr红色色度)
模式“YCbCr”为24位彩色图像,它的每个像素用24个bit表示。YCbCr其中Y是指亮度分量,Cb指蓝色色度分量,而Cr指红色色度分量。人的肉眼对视频的Y分量更敏感,因此在通过对色度分量进行子采样来减少色度分量后,肉眼将察觉不到的图像质量的变化。
Y= 0.257*R+0.504*G+0.098*B+16
Cb = -0.148*R-0.291*G+0.439*B+128
Cr = 0.439*R-0.368*G-0.071*B+128
im_YCbCr = im.convert("YCbCr")
RGB
(286, 289)
(156, 169, 193)
YCbCr
(286, 289)
(167, 142, 119)
(86, 126, 131)
5.7 模式“I”---与上面灰度模式L一致
模式“I”为32位整型灰色图像,它的每个像素用32个bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。在PIL中,从模式“RGB”转换为“I”模式是按照下面的公式转换的
im_I = im.convert("I")
I = R * 299/1000 + G * 587/1000 + B * 114/1000
RGB
(286, 289)
(156, 169, 193)
I
(286, 289)
167
86
模式“I”与模式“L”的结果是完全一样,只是模式“L”的像素是8bit,而模式“I”的像素是32bit。
5.8模式“F”---32位浮点灰色图像
模式“F”为32位浮点灰色图像,它的每个像素用32个bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。在PIL中,从模式“RGB”转换为“F”模式是按照下面的公式转换的:
F = R * 299/1000+ G * 587/1000 + B * 114/1000
im_F = im.convert("F")
RGB
(286, 289)
(156, 169, 193)
F
(286, 289)
167.8489990234375
86.56600189208984
模式“F”与模式“L”的转换公式是一样的,都是RGB转换为灰色值的公式,但模式“F”会保留小数部分,如实验中的数据。