相关文章推荐
大力的充电器  ·  pd.concat出现unnamed:0 ...·  2 月前    · 
刚毅的皮带  ·  WebSocket + ...·  2 月前    · 
刚毅的斑马  ·  Winform实战 | ...·  6 月前    · 
粗眉毛的电脑桌  ·  【前端】js ...·  8 月前    · 


一:基本概念

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的安装

pip install 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进行图像转换具体转换

原图像:

Python图像处理库PIL的基本操作 & 利用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中只取了整数部分

Python图像处理库PIL的基本操作 & 利用PIL进行图像格式转换_彩色图像_02

5.3 模式“P”---八位彩色图像,色彩值由调色板查询

模式“P”为8位彩色图像,它的每个像素用8个bit表示,其对应的彩色值是按照调色板查询出来的。

im_P = im.convert("P")
RGB
(286, 289)
(156, 169, 193)
P
(286, 289)
175
96

Python图像处理库PIL的基本操作 & 利用PIL进行图像格式转换_元组_03

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)

Python图像处理库PIL的基本操作 & 利用PIL进行图像格式转换_元组_04

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

Python图像处理库PIL的基本操作 & 利用PIL进行图像格式转换_desktop_05

​由于该转换公式比较简单,转换后的图像颜色有些失真。​

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。​

Python图像处理库PIL的基本操作 & 利用PIL进行图像格式转换_彩色图像_06

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


Python图像处理库PIL的基本操作 & 利用PIL进行图像格式转换_desktop_07

​模式“F”与模式“L”的转换公式是一样的,都是RGB转换为灰色值的公式,但模式“F”会保留小数部分,如实验中的数据。​