Python的Pillow(图像处理库)非常详细的学习笔记

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()的区别

  1. tobytes() 方法:

    • tobytes() 方法用于将图像数据转换为原始字节序列。
    • 返回的是包含整个图像像素数据的字节序列,其中每个像素可能包含多个通道的值。
    • 如果图像是多通道的,tobytes() 方法将返回按照图像模式中通道的顺序排列的像素值序列。
    • 适用于需要处理原始图像数据的情况,比如图像数据的存储、传输等。
  2. 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: Imageim2: Imagealpha: 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 通道的值决定前景图的显示比例。

注意

  • 所有输入图像(image1image2 和 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)

  1. Imode:表示图像的模式,即图像的颜色表示方式。常见的模式包括:

    • "L":灰度图像,每个像素用一个 8 位整数表示(0 表示黑色,255 表示白色)。
    • "RGB":真彩色图像,每个像素用一个 RGB 元组表示(三个整数分别表示红、绿、蓝通道的值)。
    • "RGBA":带有透明通道的图像,每个像素用一个 RGBA 元组表示(四个整数分别表示红、绿、蓝、透明度通道的值)。
    • 更多模式可以参考 Pillow 文档中的说明。
  2. size:表示图像的尺寸,是一个二元组 (width, height),表示图像的宽度和高度。

  3. 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()

 以下是一些常用的预定义滤镜效果:

  1. ImageFilter.BLUR - 普通模糊效果
  2. ImageFilter.BOX_BLUR - 方框模糊效果
  3. ImageFilter.CONTOUR - 轮廓效果
  4. ImageFilter.DETAIL - 细节增强效果
  5. ImageFilter.EDGE_ENHANCE - 边缘增强效果
  6. ImageFilter.EMBOSS - 浮雕效果
  7. ImageFilter.FIND_EDGES - 边缘检测效果
  8. ImageFilter.GaussianBlur(radius) - 高斯模糊效果
  9. ImageFilter.MaxFilter(size) - 最大值滤波效果
  10. ImageFilter.MedianFilter(size) - 中值滤波效果
  11. ImageFilter.MinFilter(size) - 最小值滤波效果
  12. ImageFilter.ModeFilter(size) - 众数滤波效果
  13. ImageFilter.RankFilter(size, rank) - 排名滤波效果
  14. ImageFilter.SHARPEN - 锐化效果
  15. ImageFilter.SHARPEN - 更强的锐化效果
  16. ImageFilter.SHARPEN_MORE - 更强的锐化效果
  17. ImageFilter.SMOOTH - 平滑效果
  18. ImageFilter.SMOOTH_MORE - 更强的平滑效果
  19. 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 = Nonemask: 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更新中。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/700435.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【ARM Cache 及 MMU 系列文章 1.4 -- 如何判断 L3 Cache 是否实现?】

文章目录 Cluster Configuration Register代码实现什么是Single-Threaded Core?什么是PE(Processor Execution units)?Single-Threaded Core与PE的关系对比多线程(Multithreading)Cluster Configuration Register 同 L2 Cache 判断方法类似,ARMv9 中也提供了一个自定义…

for 、while循环

练习1&#xff1a;输入一个数&#xff0c;判断是否是完美数 完美数&#xff1a;正序和逆序的结果一致 练习2&#xff1a; * ** *** **** 练习3&#xff1a; **** *** ** * 练习4&#xff1a;输入一个数&#xff0c;计算最大公约数&#xff0c;以及最小公倍数 练习5&#xff…

程序设计实践--3

递推 一只小蜜蜂 有一只经过训练的蜜蜂只能爬向右侧相邻的蜂房&#xff0c;不能反向爬行。请编程计算蜜蜂从蜂房a爬到蜂房b的可能路线数。其中&#xff0c;蜂房的结构如图所示。 输入描述 输入数据的第一行是一个整数N(1<n<1,000,000),表示测试实例的个数&#xff0c;然…

python-windows10普通笔记本跑bert mrpc数据样例0.1.048

python-windows10普通笔记本跑bert mrpc数据样例0.1.000 背景参考章节获取数据下载bert模型下载bert代码windows10的cpu进行训练进行预测注意事项TODOLIST背景 看了介绍说可以在gpu或者tpu上去微调,当前没环境,所以先在windows10上跑一跑,看是否能顺利进行,目标就是训练的…

Java的自动装箱和自动拆箱

自动装箱和拆箱在Java开发中的应用与注意事项 在Java开发中&#xff0c;自动装箱&#xff08;Autoboxing&#xff09;和自动拆箱&#xff08;Unboxing&#xff09;是指基本数据类型与其对应的包装类之间的自动转换。这些特性可以使代码更加简洁和易读&#xff0c;但在实际项目…

【中颖】SH79F9202 串口通信

头文件 uart.h #ifndef UART_H #define UART_H#include "SH79F9202.h" #include "LCD.h" #include "timer2.h" #include "timer5.h" #include "cpu.h" #include "key.h" #include "io.h" #include &qu…

八股文系列Spark

为什么Spark 比 MapReduce 更快 DAG相比hadoop的mapreduce在大多数情况下可以减少磁盘I/O次数 因为mapreduce计算模型只能包含一个map和一个reduce,所以reduce完后必须进行落盘&#xff0c;而DAG可以连续shuffle的&#xff0c;也就是说一个DAG可以完成好几个mapreduce&#xf…

使用#sortablejs插件对表格中拖拽行排序#Vue3#后端接口数据

使用#sortablejs对表格中拖拽行排序#Vue3#后端接口数据 *效果&#xff1a; 拖动表格行排序 首先安装插件sortable npm install sortablejs --save代码&#xff1a; <template><!-- sortable.js 进行表格排序 --><!-- 演示地址 --><div class"dem…

【全开源】驾校练车管理系统源码(FastAdmin+ThinkPHP)

&#x1f698;驾校练车管理系统&#xff1a;让学车之路更顺畅&#xff01;&#x1f4c8; 一款基于FastAdminThinkPHP开发的驾校管理系统&#xff0c;驾校管理系统(DSS)主要面向驾驶学校实现内部信息化管理&#xff0c;让驾校管理者和工作人员更高效、更快捷的完成枯燥无味的工…

网球运动目标检测跟踪

基于yolo作为目标检测器实现目标检测&#xff0c;使用跟踪器进行跟踪&#xff0c;实现如下功能。 得到视频中的网球运动员&#xff0c;测量他们的速度、击球速度和平均值&#xff0c;方便球友。

我们离成功有多远呢?只要能完成自己阶段性的目标就算是一次成功

做起一个账号&#xff0c;带好一个团队&#xff0c;经营好一家公司&#xff0c;似乎这些都能叫成功&#xff0c;成功的定义可大可小&#xff0c;而我认为只要能完成自己阶段性的目标就算是一次成功&#xff0c;毕竟每个人学历、背景、阅历、资源、认知都不同&#xff0c;很难同…

RV32M指令集

RV32M指令集 1、乘法运算2、除法运算1、乘法运算 MUL 指令(得到整数32位乘积(64位中的低32位)) MUL 指令用于执行两个带符号或无符号整数之间的乘法运算。其语法如下: mul rd, rs1, rs2 它将寄存器 rs1 和 rs2 中的值相乘,并将结果写入寄存器 rd 中。如果 rs1 和 rs2 都是有…

Fiddler抓包工具详细使用教程

各位做测试的同学想必对抓包工具fiddler并不陌生&#xff0c;但是很多同学可能没有总结过它的用法&#xff0c;下面我总结了fiddler一些常用的用法。 Web端抓包配置 打开Fiddler&#xff0c;Tools -> Fiddler Options -> HTTPS 配置完后记得要重启Fiddler 选中Decrpt …

2024年智能制造行业CRM研究(附需求清单、市场格局、选型建议)

在国家大力鼓励智能制造行业与数字化转型这个大背景下&#xff0c;我们选择了2024年智能制造行业数字化的几个关键趋势做深入解读&#xff0c;并对智能制造行业核心的数字化系统CRM进行了全面评估与排名。本文不仅提供了详尽的需求清单&#xff0c;帮助企业明确自身对CRM系统的…

linux笔记8--安装软件

文章目录 1. PMS和软件安装的介绍2. 安装、更新、卸载安装更新ubuntu20.04更新镜像源&#xff1a; 卸载 3. 其他发行版4. 安装第三方软件5. 推荐 1. PMS和软件安装的介绍 PMS(package management system的简称)&#xff1a;包管理系统 作用&#xff1a;方便用户进行软件安装(也…

catia展开模型树

1 直接点号 2 选中零件&#xff0c;右击--命令--将图居中即可 一般都是上面这样有选择性的展开 如果要一次性都展开那

DDei在线设计器-DDeiCore-图形插件

DDei-Core-图形 DDei-Core-图形插件包含了基础绘图形状与基础流程形状两个分组&#xff0c;大约100来个图形&#xff0c;能够满足很基本的框图、架构图、流程图的绘制。 图形以分组的形式组织&#xff0c;一个分组中包含多个图形&#xff0c;一个图形也能够同时存在于多个分组。…

一张试卷

目录 问题 1: 1.时间 题目描述1 输入1 输出1 样例输入1 样例输出1 提示1 代码1 问题 2: 超酷的电话号码 题目描述2 输入2 输出2 样例输入2 样例输出2 提示2 代码2 问题 3:3.爸爸的数学题 题目描述3 输入3 输出3 样例输入3 样例输出3 提示3 代码3 问题 4: 4. 营养膳食 题目描述4…

几首音乐怎么合成一首?值得推荐的四个几首音乐合成一首的方法

几首音乐怎么合成一首&#xff1f;合成几首音乐成一首新的作品是一项创造性而充满挑战的任务。通过将不同的音乐元素融合在一起&#xff0c;可以创造出独特的音乐体验&#xff0c;展示多样化的音乐风格和个性。将多首音乐合成一首可以创造出独特的音乐体验&#xff0c;融合不同…

盲盒小程序开发:传统与当代的创新融合

谈起盲盒&#xff0c;许多人并不陌生。近几年&#xff0c;盲盒一直是年轻人首选的娱乐消费方式&#xff0c;小小的盲盒为消费者带来了极大的欢乐。 盲盒小程序是将传统的盲盒玩法与线上购物方式相融合&#xff0c;对拆盲盒进行创新&#xff0c;为盲盒消费者带来全新的盲盒体验…