Python的Pillow库是一个非常强大的图像处理库。
安装Pillow库:
在终端或命令行中输入以下命令来安装Pillow:
pip install pillow
安装后查看是否安装成功以及当前版本
pip show Pillow
升级库:
pip install pillow --upgrade
一些基础的应用
1、图像文件方面的:
打开文件
1)直接打开文件:
这种方式是最常见的直接打开图片文件的方法,以文件路径作为参数,PIL 库会自动打开并加载图片。
from PIL import Image
import io
im1 = Image.open('d:\\mask3\\type_ARGB32.png') # 直接打开
2) 从文件对象中打开:
这种方式是先使用 open() 函数以二进制只读模式打开文件,然后将文件对象传递给 PIL 中的 Image.open() 方法进行加载并创建 Image 对象。
with open("d:\\mask3\\type_ARGB32.png", "rb") as f:
im2 = Image.open(f)
3) 将文件内容读取为内存中的字节流后再打开:
这种方式先将文件内容读取为内存中的字节流(通过 io.BytesIO() 创建字节流对象并使用 read() 方法读取文件内容),然后再通过 Image.open() 打开这个内存中的字节流来创建 Image 对象。
with open("d:\\mask3\\type_ARGB32.png", "rb") as f:
image_memory = io.BytesIO(f.read())
im3 = Image.open(image_memory)
打开文件时需要注意文件的生命周期:
看代码:
from PIL import Image
import io
with open("d:\\mask3\\type_ARGB32.png", "rb") as f:
im2 = Image.open(f)
im2.show()
# 出错:ValueError: seek of closed file
在这里,通过 Image.open()
直接打开了图片文件并使用 with
语句来确保资源正确关闭,创建了图片对象 im2
。然而,在 with
语句块外部访问 im2.load()
操作时,虽然图片对象仍然存在,但由于已超出 with
语句的范围,此时访问图片对象已经不再可用,导致失败。
with open("d:\\mask3\\type_ARGB32.png", "rb") as f:
im2 = Image.open(f)
im2.show()
改成如上后就可以正确执行了。
类似的例子:
from PIL import Image
import io
f= open("d:\\mask3\\type_ARGB32.png", "rb")
im2 = Image.open(f)
f.close()
im2.show()
由于文件已经被手动关闭了,PIL 试图从已关闭的文件对象中读取图像数据。所以会出错。如果正常运行,需要将im2.show()挪到f.close()前面。
或者将文件存储在内存中,也可以不受文件周期的影响:
import io
from PIL import Image
f = open("d:\\mask3\\type_ARGB32.png", "rb")
image_memory = io.BytesIO(f.read())
im3 = Image.open(image_memory)
f.close()
im3.show()
或者在关闭文件之前使用load()将图像数据加载到内存中的图像对象中:
from PIL import Image
f = open("d:\\mask3\\type_ARGB32.png", "rb")
im2 = Image.open(f)
im2.load()
f.close()
im2.show()
获取图像的窗口位置和大小getbbox()
bbox = im.getbbox()
图像的特性(格式、大小、宽高、透明度)
from PIL import Image
# 读取硬盘中的图像文件
file_path = 'd:\\mask3\\type_ARGB32.png'
im = Image.open(file_path)
print(im.size) # 图像几何尺寸:(1920, 1080)
print(im.mode) # 图像模式:RGBA
print(im.format) # 图像格式:PNG
print(im.width, im.height) # 图像宽高:1920 1080
print(im.has_transparency_data) # 是否有透明度: True
图像的字节数据tobytes()
Image.tobytes(encoder_name: str = 'raw', *args: Any) → bytes[source]
参数:
encoder_name –使用什么编码器。默认使用标准的“raw”编码器。 在函数数组in _imaging.c的编解码器部分可以看到C编码器的列表。Python编码器在相关插件中注册。
args - 编码器的额外参数。
img_bytes = im.tobytes()
获取图像所有的通道getbands()
bands = im.getbands()
getbands() 返回的值:灰度图的通道:('L',),二值黑白('1',),彩图('R', 'G', 'B')或('R', 'G', 'B', 'A')
获取指定通道的图像getchannel()
R_channel = im.getchannel("R")
获取图像中每个像素的像素值数据getdata()
data = R_channel.getdata()
tobytes()和getdata()的区别
-
tobytes()
方法:tobytes()
方法用于将图像数据转换为原始字节序列。- 返回的是包含整个图像像素数据的字节序列,其中每个像素可能包含多个通道的值。
- 如果图像是多通道的,
tobytes()
方法将返回按照图像模式中通道的顺序排列的像素值序列。 - 适用于需要处理原始图像数据的情况,比如图像数据的存储、传输等。
-
getdata()
方法:getdata()
方法用于获取图像中每个像素的像素值数据。- 返回的是图像中每个像素的像素值数据,通常是一个包含像素值的序列,每个像素值可能包含多个通道的值。
- 如果图像是多通道的,
getdata()
方法将返回像素值按照通道顺序组织的序列,而不是一个连续的字节序列。 - 适用于需要逐像素访问图像数据的情况,比如进行像素级操作、分析等。
总的来说,tobytes()
返回的是整个图像的原始字节序列,而 getdata()
返回的是图像中每个像素的像素值数据序列。根据具体的需求,你可以选择使用这两个方法来获取和处理图像数据。
demo:
用画图软件画一个 2*2像素的bmp文件,如图:
图像文件总共有4个像素,
第一行:(255,0 , 0) (255,255,255)
第二行:(255,0 , 0) (255,255,255)
from PIL import Image
file_path = 'd:\\mask3\\2020bmp.bmp'
im = Image.open(file_path) # 打开文件
img_bytes = im.tobytes() # 图像的字节数据
img_datas = im.getdata() # 图像的像素值数据
print('img_bytes=',list(img_bytes)) # img_bytes= [255, 0, 0, 255, 255, 255, 255, 0, 0, 255, 255, 255], 返回的是整个图像的原始字节序列
print('img_datas=',list(img_datas)) # img_datas= [(255, 0, 0), (255, 255, 255), (255, 0, 0), (255, 255, 255)], 返回的是图像中每个像素的像素值数据序列
再比如:
from PIL import Image
file_path = 'd:\\mask3\\2020bmp.bmp'
im = Image.open(file_path) # 打开文件
B_channel = im.getchannel("B") # 获取指定通道的图像
img_bytes = B_channel.tobytes() # 图像的字节数据
img_datas = B_channel.getdata() # 图像的像素值数据
print('img_bytes=',list(img_bytes)) # img_bytes= [0, 255, 0, 255]
print('img_datas=',list(img_datas)) # img_datas= [0, 255, 0, 255]
由于是单通道数据,所以上述两个函数的返回结果是相同的。
2、编辑和显示方面
显示show()
from PIL import Image
# 打开文件,Windows系统可以设置默认的打开程序,比如画图
with Image.open('d:\\mask3\\type_ARGB32.png') as im:
im.show()
图像首先保存到一个临时文件中。默认情况下,它将是PNG格式。 在Windows上,使用标准的PNG显示实用程序打开图像。
请注意,这是只读方式的,即使在软件中对图像进行了编辑也无法直接保存 ,如果需要保存可以使用“另存为”。
加载load()和seek()
将图像文件加载到内存中,以供后续的处理和操作。
load()
from PIL import Image
f = open('d:\\mask3\\type_ARGB32.png', "rb")
im2 = Image.open(f)
im2.load()
f.close()
im2.show()
对于单帧图片,可以在load()之后将文件关闭,然而对于多帧的图像格式,比如gif,就要等load()之后所有的操作完成后才能将文件关闭。比如下面的代码就会报错:
from PIL import Image
f = open('d:\\mask3\\2.gif', "rb")
im2 = Image.open(f)
im2.load()
f.close()
im2.show()
需要改成:
from PIL import Image
f = open('d:\\mask3\\2.gif', "rb")
im2 = Image.open(f)
im2.load()
im2.show()
f.close()
seek()
与load()方式类似,区别在于seek()方法用于定位到图像中的特定帧,特别是针对多帧图像(例如 GIF 动画)。
from PIL import Image
f = open('d:\\mask3\\2.gif', "rb")
im2 = Image.open(f)
im2.seek(2)
im2.show()
f.close()
同样的,seek()在使用中也要注意图像文件的生命周期。
下面的代码就会报错:
from PIL import Image
f = open('d:\\mask3\\2.gif', "rb")
im2 = Image.open(f)
im2.seek(2)
f.close()
im2.show()
转换图像格式convert()
convert()用于将图像转换为指定的格式。
可选的格式:
1. '1':二值图像(1 位像素,黑白)
2. 'L':灰度图像
3. 'RGB': 彩色图像
4. 'RGBA': 带有透明通道的彩色图像
5. 'CMYK: CMYK 颜色模式的图像
6. 'HSV': HSV格式的图像(色相、饱和度、值)
7. 'I': 整型灰度图像
8. 'YCbCr': 颜色空间的图像
from PIL import Image
# 打开一张彩色图像
img = Image.open("color_image.jpg")
# 将图像转换为灰度图像
gray_img = img.convert('L')
# 显示灰度图像
gray_img.show()
透明度混合Image.alpha_composite()与Image.blend()
alpha_composite()将两个本身具有透明度参数的半透明的图片叠加在一起,并根据 透明度(alpha) 通道的数值进行合成,实现透明效果。 要确保两个图像的像素尺寸一致,并且它们都是 RGBA 模式的图像。
from PIL import Image
im1_path = 'd:\\mask3\\type_ARGB32_alpha1.png'
im2_path = 'd:\\mask3\\type_ARGB32_alpha2.png'
im1 = Image.open(im1_path)
im2 = Image.open(im2_path)
im3 = Image.alpha_composite(im2, im1)
im3.show()
blend()方法是用于对两幅图像进行混合,根据函数中给定的透明度参数对两幅图像进行加权混合。
from PIL import Image
im1_path = 'd:\\mask3\\type_ARGB32_alpha1.png'
im2_path = 'd:\\mask3\\type_ARGB32_alpha2.png'
im1 = Image.open(im1_path)
im2 = Image.open(im2_path)
im3 = Image.blend(im1, im2, 0.2)
im3.show()