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()
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()
请注意,这是只读方式的,即使在软件中对图像进行了编辑也无法直接保存 ,如果需要保存可以使用“另存为”。
加载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()
对于Image.blend(im1: Image, im2: Image, alpha: float)输出的图像:out = im1 * (1.0 - alpha) + im2 * alpha。
遮罩合成Image.composite()
用于将两张图像合成为一张新图像。具体来说,它会根据一个遮罩图像来决定哪里显示第一张图像(前景图),哪里显示第二张图像(背景图)。
from PIL import Image
# 打开第一幅图像(背景图像)
background = Image.open('d:/mask3/composite_background.png')
# 打开第二幅图像(前景图像)
foreground = Image.open('d:/mask3/composite_foreground.png')
# 创建一个图像遮罩,模式必须与 foreground 相同
mask = Image.open('d:/mask3/composite_mask.png')
# 使用 composite 方法合成图像,mask 参数是遮罩图像
result = Image.composite(foreground, background, mask)
# 显示合成后的图像
result.show()
background
:背景图foreground
:前景图mask
:遮罩图,是灰度图或带有 alpha 通道的图像。如果遮罩图是不带alpha 通道的灰度图,则白色表示完全选择 前景图,黑色表示完全选择image2
,灰色则表示逐渐变换。如果遮罩图是带alpha 通道的灰度图,则由lpha 通道的值决定前景图的显示比例。
注意
- 所有输入图像(
image1
,image2
和mask
)的尺寸必须相同。
demo:
前景图
背景图
遮罩图
输出:
类似的,还可以使用paste()实现同样的功能:
from PIL import Image
# 背景图像文件
background = Image.open('d:\\mask3\\composite_background.png')
# 前景图像文件
foreground = Image.open('d:\\mask3\\composite_foreground.png')
# 遮罩蒙版图像文件
mask = Image.open('d:\\mask3\\composite_mask.png')
background.paste(foreground, (0, 0), mask=mask)
background.show()
对图像逐像素操作Image.eval() 和point()
Image.eval()
Image.eval()
是一个用于对图像进行像素级操作的方法。它允许你通过传入一个函数来对图像中的每个像素进行操作,返回一个新的图像。
具体而言,PIL.Image.eval()
接受一个函数作为参数,该函数定义了对每个像素值的操作。该函数接受一个像素值作为参数,并返回一个新的像素值,以便对图像进行转换、调整或其他自定义操作。
例如,可以使用PIL.Image.eval()
方法对图像进行反转、亮度调整、对比度调整等操作。
from PIL import Image
# 打开一张图片
img = Image.open('d:/mask3/composite_background.png')
# 使用 Image.eval() 方法对图像进行亮度调整
adjusted_img = Image.eval(img, lambda x: min(255, x + 50)) # 对每个像素的值增加 50,限制在 0 到 255 之间
# 显示调整后的图像
adjusted_img.show()
point()
Image.eval()
方法和 img.point()
方法的作用实际上非常相似,都是用于对图像进行像素级别的操作。
img.point()
方法接受一个函数或者映射表格作为参数,然后将图像的每个像素都应用这个函数进行处理。
from PIL import Image
# 打开一张图片
img = Image.open('d:/mask3/composite_background.png')
# 定义一个函数,用于调整亮度
def adjust_brightness(pixel_value):
return min(255, max(0, pixel_value + 50)) # 增加亮度值 50,并确保像素值在 0 到 255 之间
# 使用 Image.eval() 方法对图像进行亮度调整
adjusted_img = img.point(adjust_brightness)
# 显示调整后的图像
adjusted_img.show()
通道合并Image.merge()
用于将多个图像通道合并成一个新的图像的方法。
from PIL import Image
# 创建三个随机的图像通道
channel_r = Image.new('L', (100, 100), color=100)
channel_g = Image.new('L', (100, 100), color=200)
channel_b = Image.new('L', (100, 100), color=255)
# 使用 PIL.Image.merge() 方法将三个通道合并成一张彩色图像
merged_img = Image.merge('RGB', (channel_r, channel_g, channel_b))
# 显示合并后的彩色图像
merged_img.show()
创建新的图像Image.new()
Image.new()用于创建新图像。
Image.new(mode, size, color)
-
Imode
:表示图像的模式,即图像的颜色表示方式。常见的模式包括:"L"
:灰度图像,每个像素用一个 8 位整数表示(0 表示黑色,255 表示白色)。"RGB"
:真彩色图像,每个像素用一个 RGB 元组表示(三个整数分别表示红、绿、蓝通道的值)。"RGBA"
:带有透明通道的图像,每个像素用一个 RGBA 元组表示(四个整数分别表示红、绿、蓝、透明度通道的值)。- 更多模式可以参考 Pillow 文档中的说明。
-
size
:表示图像的尺寸,是一个二元组(width, height)
,表示图像的宽度和高度。 -
color
:可选参数,表示创建图像时填充的颜色。对于不同的模式,color
的含义有所不同:- 对于灰度图像
"L"
,color
是一个 0 到 255 之间的整数,表示灰度值。 - 对于 RGB 或 RGBA 图像,
color
是一个长度为 3 或 4 的元组,分别表示 RGB 或 RGBA 颜色值。
- 对于灰度图像
通过 Image.new()
方法,我们可以方便地创建指定模式、尺寸和颜色的新图像。
from PIL import Image
# 创建一张白色 RGB 图像
new_img = Image.new('RGB', (200, 100), (255, 255, 255))
# 显示新创建的图像
new_img.show()
数组转换为图像Image.fromarray(),
图像转换为数组numpy.assarray()
Image.fromarray()
用于将 NumPy 数组转换为图像对象
from PIL import Image
import numpy as np
# 创建一个随机的 NumPy 数组作为图像数据
im_data = np.random.rand(200, 300, 3) * 255 # 创建一个形状为 (200, 300, 3) 的随机数组,表示一个 RGB 图像
# 将 NumPy 数组转换为 PIL 图像对象
img = Image.fromarray(im_data.astype('uint8')) # 将数据类型转换为 uint8 后转换为图像对象
# 显示转换后的图像
img.show()
from PIL import Image
import numpy as np
# 创建一个形状为 (200, 300, 3) 的黑色图像
im_data = np.zeros((200, 300, 3), dtype=np.uint8) # 使用 np.zeros() 创建全零数组,并指定数据类型为 uint8
# 将 NumPy 数组转换为 PIL 图像对象
img = Image.fromarray(im_data)
# 显示转换后的图像
img.show()
作为逆操作,可以利用numpy的asarray()将PIL的图像文件转为Numpy的数组
from PIL import Image
import numpy as np
# 读取图像
im = Image.open('d:\\mask3\\result.png')
# 图像转为NumPy数组
a = np.asarray(im)
# 将NumPy数组转换为PIL图像对象
img = Image.fromarray(a)
# 显示转换后的图像
img.show()
从像素数据创建图像Image.frombytes()
根据给定的像素数据和图像尺寸,创建一个新的 PIL 图像
from PIL import Image
# 定义图像的宽度和高度
width = 200
height = 100
# 创建一个像素数据(假设每个像素由三个通道组成)
pixels = bytes([255, 0, 0] * width * height) # 红色像素数据
# 使用 Image.frombytes() 方法创建图像对象
img = Image.frombytes("RGB", (width, height), pixels)
# 显示图像
img.show()
结合之前学过的tobytes():
from PIL import Image
# 读取图像
im = Image.open('d:\\mask3\\result.png')
# 获取图像信息
pixels = im.tobytes()
width = im.width
height = im.height
mode = im.mode
# 使用 Image.frombytes() 方法创建图像对象
img = Image.frombytes(mode, (width, height), pixels)
# 显示图像
img.show()
复制图像copy()
from PIL import Image
im1 = Image.open('d:\\mask3\\result.png') # 直接打开
im2 = im1.copy()
im2.show()
裁剪复制crop()
from PIL import Image
(left, upper, right, lower) = (20, 20, 100, 100) # 左上和右下的x,y坐标确定了一个方框
im = Image.open('d:\\mask3\\result.png')
im_crop = im.crop((left, upper, right, lower)) # 返回原图像指定方框中的图像
im_crop.show()
草图模式draft()
用于设置图像显示模式。
该方法可以帮助在处理大型图像时提高处理速度,因为它可以设置图像显示的模式,从而减少所需的内存和计算资源。
具体来说,Image.draft()
方法接受两个参数:mode 和 size。
mode
:指定图像的显示模式(如 “RGB”、“L” 等)。size
:一个元组,表示预览图像的大小。- 需要注意的是draft()目前只支持jpeg和MPO格式的图像。
from PIL import Image
(left, upper, right, lower) = (20, 20, 100, 100)
im = Image.open('d:\\mask3\\src.jpg')
# 设置预览模式和大小
im.draft("L", (50, 50))
# 显示图像
im.show()
另外,此方法会就地修改图像对象,如果图像已经加载,此方法无效。
例如下例,就无效。
from PIL import Image
(left, upper, right, lower) = (20, 20, 100, 100)
im = Image.open('d:\\mask3\\src.jpg')
# 设置预览模式和大小
im.load()
im.draft("L", (50, 50))
# 显示图像
im.show()
随机分布effect_spread()
将图像中的像素进行随机的分布
from PIL import Image
# 打开图像文件
im = Image.open('d:\\mask3\\src.jpg')
# 使用 effect_spread 方法,传入参数 10,这个参数决定了像素随机分布的范围
im1 = im.effect_spread(10)
# 显示处理后的图像
im1.show()
滤镜Image.filter()
应用各种滤镜效果,如模糊、轮廓、边缘增强等。
该方法的基本语法如下:
filtered_image = original_image.filter(filter_name, filter_parameter)
其中:
original_image
是要应用滤镜效果的原始图像对象。filter_name
是滤镜的名称,可以是预定义的滤镜效果,例如ImageFilter.BLUR
(模糊效果)。filter_parameter
是可选的参数,用于指定滤镜效果的参数,比如模糊效果的半径。
from PIL import Image, ImageFilter
# 打开图像文件
im = Image.open('d:\\mask3\\src.jpg')
# 自定义模糊效果的半径为 10
filtered_image = im.filter(ImageFilter.GaussianBlur(radius=10))
# 显示处理后的图像
filtered_image.show()
以下是一些常用的预定义滤镜效果:
ImageFilter.BLUR
- 普通模糊效果ImageFilter.BOX_BLUR
- 方框模糊效果ImageFilter.CONTOUR
- 轮廓效果ImageFilter.DETAIL
- 细节增强效果ImageFilter.EDGE_ENHANCE
- 边缘增强效果ImageFilter.EMBOSS
- 浮雕效果ImageFilter.FIND_EDGES
- 边缘检测效果ImageFilter.GaussianBlur(radius)
- 高斯模糊效果ImageFilter.MaxFilter(size)
- 最大值滤波效果ImageFilter.MedianFilter(size)
- 中值滤波效果ImageFilter.MinFilter(size)
- 最小值滤波效果ImageFilter.ModeFilter(size)
- 众数滤波效果ImageFilter.RankFilter(size, rank)
- 排名滤波效果ImageFilter.SHARPEN
- 锐化效果ImageFilter.SHARPEN
- 更强的锐化效果ImageFilter.SHARPEN_MORE
- 更强的锐化效果ImageFilter.SMOOTH
- 平滑效果ImageFilter.SMOOTH_MORE
- 更强的平滑效果ImageFilter.UNSHARP_MASK(radius, percent, threshold)
- 锐化掩蔽滤镜效果
获取颜色列表Image.getcolors()
getcolors() 方法通常用于获取图像中各种颜色及其出现次数的列表,并且返回一个包含颜色计数对的列表。在某些情况下,该方法可能返回 None,特别是对于包含大量颜色或渐变的图像。
from PIL import Image
# 打开图像文件
im = Image.open('d:\\mask3\\2020bmp.bmp')
colors = im.getcolors()
print(colors)
输出结果:
[(2, (255, 255, 255)), (2, (255, 0, 0))]
获取图像中每个像素的像素值数据getdata()
from PIL import Image
# 打开图像文件
im = Image.open('d:\\mask3\\2020bmp.bmp')
# 获取图像中每个像素的像素值数据getdata()
data = im.getdata()
print(list(data))
# [(255, 0, 0), (255, 255, 255), (255, 0, 0), (255, 255, 255)]
获取图像的exif数据getexif()
获取图像的像素值范围getextrema()
获取图像的像素值范围(最小值和最大值)。
返回一个包含两个元素的元组,第一个元素是图像中所有通道的最小像素值,第二个元素是图像中所有通道的最大像素值。这个方法可以帮助您了解图像像素值的范围,有助于后续的图像处理和分析。
from PIL import Image
# 打开图像文件
im = Image.open('d:\\mask3\\src.jpg')
# 获取图像像素值范围
extrema = im.getextrema()
print("图像像素值范围:", extrema)
获取调色板Image.getpalette()
用于获取调色板(Palette)。
在 PIL 中,调色板是一种颜色映射表,通常用于将索引颜色图像转换为真彩色图像。调色板是由一组颜色值组成的列表,每个颜色值包含红色、绿色和蓝色三个通道的数值。通过调色板,可以实现图像的色彩映射和优化。
当调色板被应用于某幅图像时,图像的每个像素值都将被视为一个索引,通过调色板中的相应索引值找到对应的颜色。Image.getpalette()
方法返回当前图像的调色板,以列表形式呈现。
from PIL import Image
# 打开图像文件
im = Image.open('d:\\mask3\\indexed_color.png')
# 获取图像的调色板
palette = im.getpalette()
print("图像的调色板:", palette)
如果 Image.getpalette()
方法返回 None,这可能表示图像并不使用调色板来进行颜色映射。
对于不使用调色板的真彩色图像,通常直接包含 RGB(红绿蓝)三通道的像素值,而不需要通过调色板进行颜色映射。因此,对于这种类型的图像,getpalette()
方法可能会返回 None。
获取某一坐标点(x,y)的像素值getpixel()
pixel = im.getpixel((100,100))
获得到x和y轴的投影getprojection()
新建图像文件,命名为1010bmp.bmp,5*5像素,共有4个像素点,如下图:
from PIL import Image
# 打开图像文件
im = Image.open('d:\\mask3\\1010bmp.bmp')
print(im.getprojection())
输出结果:([1, 0, 1, 0, 1], [1, 0, 0, 0, 1])
粘贴图像paste()
函数原型:
Image.paste(im: Image | str | float | tuple[float, ...], box: tuple[int, int, int, int] | tuple[int, int] | None = None, mask: Image | None = None) → None[source]
将另一个图像粘贴到此图像中。
box参数或者是给出左上角的2元组,或者是定义左、上、右和下像素坐标的4元组,或者是None(与(0,0)相同)。如果给定一个4元组,则粘贴图像的大小必须与区域的大小相匹配。 如果模式不匹配,粘贴的图像将转换为此图像的模式(有关详细信息,请参见convert()方法)。
源可以是包含像素值的整数或元组,而不是图像。然后,该方法用给定的颜色填充该区域。创建RGB图像时,也可以使用ImageColor模块支持的颜色字符串。
如果给定了掩码,此方法只更新掩码指示的区域。您可以使用“1”、“L”、“LA”、“RGBA”或“RGBa”图像(如果存在,alpha带用作遮罩)。
当蒙版为255时,给定图像按原样复制。当掩码为0时,保留当前值。中间值会将两个图像混合在一起,包括它们的alpha通道(如果有)。
from PIL import Image
# 背景图像文件
background = Image.open('d:\\mask3\\composite_background.png')
# 前景图像文件,它的大小是5*5像素
foreground = Image.open('d:\\mask3\\0505bmp.bmp')
# 使用2点定位粘贴
background.paste(foreground, (100, 100))
# 使用4点定位粘贴,4个点定出的方形区域必须与粘贴内容等大
background.paste(foreground, (200, 200, 205, 205))
background.show()
类似的,还可以使用paste()实现与composite()同样的功能:
from PIL import Image
# 背景图像文件
background = Image.open('d:\\mask3\\composite_background.png')
# 前景图像文件
foreground = Image.open('d:\\mask3\\composite_foreground.png')
# 遮罩蒙版图像文件
mask = Image.open('d:\\mask3\\composite_mask.png')
background.paste(foreground, (0, 0), mask=mask)
background.show()
像素级点操作point()
传入一个 LUT(Look-Up Table) 查找表或者函数作为参数,用于对图像进行像素级的转换。
可以使用一个查找表,包含图像中每个通道的256(或65536,如果self.mode=="I "和mode == "L ")个值。
也可以使用一个函数来代替,它应该有一个参数。对每个可能的像素值调用一次该函数,得到的表将应用于图像的所有通道。
from PIL import Image
# 打开图像文件
im = Image.open('d:\\mask3\\0505bmp.bmp')
# 自定义 LUT 函数,这里以颜色反转为例
def lut(pixel_value):
return 255 - pixel_value
# 或者自定义 LUT 表,这里以颜色反转为例
lut = [255-i for i in range(256 * 3)]
# 对图像进行像素级转换
result_im = im.point(lut)
result_im.show()
设置透明度putalpha()
添加或替换此图像中的alpha层。如果图像没有alpha层,它会被转换为“LA”或“RGBA”。新图层必须是“L”或“1”。
from PIL import Image
# 打开图像文件
im = Image.open('d:\\mask3\\src.png')
# 设置透明度
im.putalpha(100)
im.show()
设置像素值putdata()
使用像素值数据:
from PIL import Image
# 打开图像文件,这是一个RGBA格式的文件
im = Image.open('d:\\mask3\\src.png')
# 图像的像素数据长度
len_im = im.width * im.height
# 要写入的新数据
zeros_list = [(0, 0, 0, 100) for _ in range(len_im)]
im.putdata(zeros_list)
im.show()
使用字节数据:
from PIL import Image
# 打开图像文件,这是一个RGBA格式的文件
im = Image.open('d:\\mask3\\src.png')
# 图像的像素数据长度
len_im = im.width * im.height
# 要写入的新数据
R_channel, G_channel, B_channel, A_channel = im.split()
R = list(R_channel.getdata())
G = list(G_channel.getdata())
B = list(B_channel.getdata())
A = list(A_channel.getdata())
zeros = [0] * len_im
alphas = [255] * len_im
R[:] = zeros
G[:] = zeros
B[:] = zeros
A[:] = alphas
new_bytes = list(zip(R, G, B, A))
im.putdata(new_bytes)
im.show()
设置调色板putpalette()
将图像的调色板设置为提供的颜色列表 .图像必须是“P”、“PA”、“L”或“LA”图像。 调色板序列必须包含最多256种颜色,由raw模式下每个通道的一个整数值组成。例如,如果raw模式是“RGB”,那么它最多可以包含768个值,由256种颜色中对应像素索引的红色、绿色和蓝色值组成。如果raw模式是“RGBA”,那么它最多可以包含1024个值,包含红色、绿色、蓝色和alpha值。 或者,可以使用8位字符串来代替整数序列。
from PIL import Image
im = Image.open('d:\\mask3\\2020bmp.bmp') # 这是一个RGBA格式的图像
im.show()
# 转换图像为调色板(P)模式
im = im.convert('P')
# 创建一个调色板,这里示例提供了一组 RGB 色彩
palette = [255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255]
im.putpalette(palette)
# 保存处理后的图像
im.save('d:\\mask3\\2020bmp_with_palette.bmp')
修改给定位置的像素putpixel
修改给定位置的像素。对于单通道图像,颜色以单个数值的形式给出;对于多通道图像,颜色以元组的形式给出。除此之外,P和PA图像也接受RGB和RGBA元组。 请注意,这种方法相对较慢。对于大范围的更改,请改用paste()或ImageDraw模块。
from PIL import Image
im = Image.open('d:\\mask3\\0505bmp.bmp') # 这是一个RGBA格式的图像
im.putpixel((3, 3), (100, 100, 100))
im.show()
量化 quantize()
使用指定数量的颜色将图像转换为“P”模式。用于将一个图像量化为一个使用调色板的新图像。此方法的主要作用是减少图像的颜色数量,进而减小文件大小,同时尽量保持图像质量。这在人们需要优化图像以减少存储空间或加快加载速度的情况下特别有用。
函数原型:
Image.quantize(colors: int = 256, method: Quantize | None = None, kmeans: int = 0, palette=None, dither: Dither = Dither.FLOYDSTEINBERG) → Image[source]
colors: 所需的颜色数量,<= 256 方法
method: 方法
Quantize.MEDIANCUT-中值切割
Quantize.MAXCOVERAGE-最大覆盖率
Quantize.FASTOCTREE-快速八叉树
Quantize.LIBIMAGEQUANT- PNG 图像优化库
默认的方法是MEDIANCUT(中值切割),RGBA图像是个例外。
Quantize.MAXCOVERAGE不支持RGBA图像,因此RGBA图像默认情况下使用快速八叉树。
kmeans: 大于或等于零的整数。
palette: 量化到给定的调色板
Dithe: 从模式“RGB”转换为“P”或从“RGB”或“L”转换为“1”时使用的混色方法。可能的方法是Dither.NONE或Dither.FLOYDSTEINBERG(默认值)
from PIL import Image
from PIL.Image import Quantize
# 打开图像,可以是一个 RGBA 格式的图像
im = Image.open('d:\\mask3\\src.jpg')
# 对图像进行量化操作,使用最大色覆盖方法
quantized_im = im.quantize(method=Quantize.MAXCOVERAGE)
# 显示量化后的图像
quantized_im.show()
缩小图像reduce()
返回缩小倍数的图像副本。如果图像的大小不能被因子整除,则得到的大小将被向上舍入。
函数原型:
Image.reduce(factor: int | tuple[int, int], box: tuple[int, int, int, int] | None = None) → Image[source]
factor:当facor是一个大于0的整数,宽度和高度均为这个整数分之一,例如acor = 2,宽度和高度均为原图二分之一的尺寸。当facor是由两个大于0的整数组成的元组,则宽和高按照元组的两个元素缩小倍数。例如(2, 10),则宽是原图二分之一的尺寸,高是原图十分之一的尺寸。
from PIL import Image
# 打开图像,可以是一个 RGBA 格式的图像,原图是一个1024*1024的图像
im = Image.open('d:\\mask3\\66631f0e2ef53d591b914392.png')
# 使用reduc方法进行图像缩小,得到了一个64*64的图像
im1 = im.reduce(16)
# 显示量化后的图像
im1.show()
# 使用reduc方法进行图像缩小,得到了一个512*103的图像
im2 = im.reduce((2, 10))
im2.show()
重新排列调色板(remap_palette)
from PIL import Image
# 打开图像
im = Image.open('d:\\mask3\\src.png')
# 转换图像为调色板(P)模式
im = im.convert('P')
src_palette = im.getpalette()
# 新的调色板, 填充到 256 个颜色条目
new_palette = [
0, 0, 0, # 黑色
255, 0, 0, # 红色
0, 255, 0, # 绿色
0, 0, 255, # 蓝色
255, 255, 0, # 黄色
0, 128, 64, # 深绿
160, 160, 220, # 淡紫
0, 64, 128, # 深蓝
0, 128, 192, # 浅蓝
255, 128, 64, # 橙色
255, 0, 255, # 品红
0, 255, 255, # 青色
128, 64, 64, # 棕色
100, 64, 200, # 深紫
255, 255, 255, # 白色
192, 192, 192, # 灰色
] + [0] * (256*3 - 16*3) # 填充剩下的调色板
# 将图像的调色板重新映射到新的调色板
def remap_palette(img, new_palette):
# 获取当前图像的数据
data = img.getdata()
new_img = Image.new('P', img.size)
new_img.putdata(data)
new_img.putpalette(new_palette)
return new_img
remapped_im = remap_palette(im, new_palette)
remapped_im.show()
N更新中。。。