PIL(Python Imaging Library)是Python中一个强大的图像处理库,尽管其已不再更新,但其后续版本Pillow提供了更多的功能和更好的兼容性。本文将重点介绍Pillow库中的open()
函数、fromarray()
函数以及save()
函数,并通过示例代码展示它们的用法。
文章目录
一、open()
函数
open()
函数用于打开一个图像文件,并返回一个Image对象。其基本用法如下:
from PIL import Image
# 打开图像文件
img = Image.open('path_to_image.jpg')
# 显示图像
img.show()
二、fromarray()
函数
fromarray()
函数用于将NumPy数组转换为Image对象。这在处理大量图像数据或需要与其他库(如OpenCV)交互时非常有用。其基本用法如下:
import numpy as np
from PIL import Image
# 创建一个NumPy数组
array = np.random.rand(100, 100, 3) * 255 # 生成一个100x100的随机RGB图像
# 将NumPy数组转换为Image对象
img = Image.fromarray(array.astype('uint8'))
# 显示图像
img.show()
三、save()
函数
save()
函数用于将Image对象保存为指定格式的图像文件。其基本用法如下:
from PIL import Image
# 打开图像文件
img = Image.open('example.jpg')
# 保存图像为PNG格式
img.save('example.png')
四、point()
函数
在Python的Pillow库(即PIL的升级版本)中,Image
对象的point
方法是一种用于对图像中的每个像素值应用特定操作的工具。它的作用是将一个函数(或查找表)映射到图像的每个像素,从而对图像进行点运算(点操作)。
Image.point(function=None, mode=None)
参数:
-
function
- 一个可以接收像素值并返回新像素值的函数(或查找表)。
- 例如:
- 如果传入的是函数,函数会对每个像素的值执行一次映射。
- 如果传入的是一个查找表(列表或其他可迭代对象),那么查找表的长度必须为256,表示对每个可能的像素值(0-255)进行直接替换。
-
mode
- 可选参数,表示结果图像的模式(如
"L"
、"RGB"
等)。如果未指定,结果图像将与输入图像的模式相同。
- 可选参数,表示结果图像的模式(如
返回值:
返回一个新的 Image
对象,其中每个像素都已根据提供的函数或查找表进行了修改。
使用场景:
- 图像亮度调整
- 图像对比度调整
- 图像反色
- 色彩分量调整
- 自定义点操作
示例1:像素值线性变换
将每个像素值增加50(确保结果在0-255范围内)。
from PIL import Image
# 打开图像
img = Image.open("example.jpg")
# 使用 point 方法
new_img = img.point(lambda p: min(255, p + 50))
# 显示结果
new_img.show()
示例2:图像反色
from PIL import Image
# 打开图像
img = Image.open("example.jpg")
# 对每个像素值进行反色操作
negative_img = img.point(lambda p: 255 - p)
# 显示结果
negative_img.show()
示例3:调整红色通道
对彩色图像中的红色通道应用线性函数,其它通道保持不变。
from PIL import Image
# 打开图像
img = Image.open("example.jpg")
# 拆分为 R、G、B 通道
r, g, b = img.split()
# 调整红色通道
r = r.point(lambda p: p * 0.5) # 将红色通道值减半
# 合并通道
new_img = Image.merge("RGB", (r, g, b))
# 显示结果
new_img.show()
示例4:使用查找表
使用查找表对像素值进行非线性映射。
from PIL import Image
# 创建一个查找表,使亮度提高到平方
lookup_table = [min(255, int((i / 255) ** 2 * 255)) for i in range(256)]
# 打开图像
img = Image.open("example.jpg")
# 应用查找表
new_img = img.point(lookup_table)
# 显示结果
new_img.show()
注意事项:
- 如果传入的是函数,该函数需要对每个像素值逐一操作,这在处理大图像时可能较慢。
- 查找表更高效,但需要提前生成。
- 对于多通道图像(如
"RGB"
模式),point
会逐通道处理。
point
方法是对图像每个像素点逐一操作的有效工具,尤其适合实现基于像素的自定义处理逻辑。
五、convert()
函数
在Pillow库中,Image
对象的convert
函数用于将图像从一种模式转换为另一种模式。它非常灵活,常用于图像模式的转换(如从彩色图像转为灰度图像或二值图像),也可以用于改变图像的调色板。
Image.convert(mode=None, matrix=None, dither=None, palette=0, colors=256)
参数说明:
-
mode:
- 字符串类型,指定目标图像模式。例如:
"1"
: 1位像素,黑白二值图像。"L"
: 8位像素,灰度图像。"P"
: 8位像素,使用调色板的彩色图像。"RGB"
: 24位像素,真彩色图像。"RGBA"
: 32位像素,真彩色加透明通道。"CMYK"
: 32位像素,CMYK色彩模型。
- 如果省略或为
None
,则默认使用原图像模式。
- 字符串类型,指定目标图像模式。例如:
-
matrix:
- 一个可选的4×4或3×3矩阵,用于指定颜色转换的变换规则。
- 常用于自定义颜色转换,例如将图像从一种颜色空间映射到另一种颜色空间。
-
dither:
- 整数类型,指定抖动模式。常见值:
Image.NONE
: 无抖动。Image.FLOYDSTEINBERG
: Floyd-Steinberg抖动(默认值)。
- 仅在模式从高位转换到低位时有效,例如从
"RGB"
转换为"P"
或"1"
。
- 整数类型,指定抖动模式。常见值:
-
palette:
- 指定用于
"P"
模式的调色板。常见值:Image.ADAPTIVE
: 自适应调色板,基于图像内容动态生成调色板。Image.WEB
: 使用标准WEB调色板。
- 指定用于
-
colors:
- 用于调色板的颜色数量(仅在模式为
"P"
且调色板为Image.ADAPTIVE
时生效)。默认为 256。
- 用于调色板的颜色数量(仅在模式为
返回值:
返回一个新的 Image
对象,其模式根据指定参数进行了转换。
使用场景:
- 转换图像为灰度模式(
L
模式)。 - 生成二值化图像(
1
模式)。 - 将图像从
RGB
转为RGBA
以支持透明通道。 - 对调色板图像重新生成自适应调色板。
- 自定义颜色映射规则的颜色空间转换。
示例1:彩色图像转换为灰度图像
from PIL import Image
# 打开彩色图像
img = Image.open("example.jpg")
# 转换为灰度模式
gray_img = img.convert("L")
# 显示结果
gray_img.show()
示例2:生成黑白二值图像
from PIL import Image
# 打开彩色图像
img = Image.open("example.jpg")
# 转换为黑白二值模式
bw_img = img.convert("1")
# 显示结果
bw_img.show()
示例3:自适应调色板
from PIL import Image
# 打开图像
img = Image.open("example.jpg")
# 转换为调色板模式,使用自适应调色板
palette_img = img.convert("P", palette=Image.ADAPTIVE, colors=16)
# 显示结果
palette_img.show()
示例4:使用自定义颜色矩阵
将图像从RGB模式转换为灰度模式,并自定义灰度计算规则:
from PIL import Image
# 打开图像
img = Image.open("example.jpg")
# 定义颜色转换矩阵(自定义灰度公式)
matrix = (0.5, 0.5, 0.0, 0, # R权重
0.5, 0.5, 0.0, 0, # G权重
0.0, 0.0, 0.0, 1) # B权重 + 偏移量
custom_gray_img = img.convert("L", matrix)
# 显示结果
custom_gray_img.show()
示例5:从 RGB
转换为 CMYK
from PIL import Image
# 打开图像
img = Image.open("example.jpg")
# 转换为 CMYK 模式
cmyk_img = img.convert("CMYK")
# 显示结果
cmyk_img.show()
注意事项:
- 数据丢失:
- 模式转换可能会导致数据丢失。例如,从
"RGB"
转为"L"
会丢失颜色信息。
- 模式转换可能会导致数据丢失。例如,从
- 矩阵使用:
- 矩阵仅适用于某些模式转换(如
RGB
到L
),并且需要提供正确的维度。
- 矩阵仅适用于某些模式转换(如
- 性能影响:
- 转换较大的图像时可能需要较长时间,尤其是使用自定义矩阵或自适应调色板时。
总结:
convert
方法是一个强大的工具,用于模式转换、颜色调整和调色板优化。在图像处理中,convert
常被用作预处理步骤,以满足特定任务的图像模式要求。
六、crop()
函数
Image.crop()
是 Python 的 Pillow(PIL 的升级版)库中用于裁剪图像的方法。它可以从图像中截取一个矩形区域并返回一个新的图像对象,常用于对图像的局部操作或提取特定区域。
Image.crop(box)
参数:
- box:
- 类型:一个包含四个整数的元组
(left, upper, right, lower)
。 - 描述:定义裁剪区域的矩形框。
- left:裁剪区域左边界的 x 坐标。
- upper:裁剪区域上边界的 y 坐标。
- right:裁剪区域右边界的 x 坐标。
- lower:裁剪区域下边界的 y 坐标。
- 注意:坐标的原点 (0, 0) 位于图像的左上角。
- 类型:一个包含四个整数的元组
返回值:
- 返回一个新的
Image
对象,表示裁剪后的图像。
使用场景:
- 提取图像的一部分:裁剪出感兴趣的区域。
- 图像预处理:在机器学习中裁剪图像以适应模型输入要求。
- 图像编辑:去除不需要的边缘部分。
示例 1:裁剪固定区域
from PIL import Image
# 打开图像
img = Image.open("example.jpg")
# 定义裁剪区域 (left, upper, right, lower)
box = (100, 100, 400, 400)
# 裁剪图像
cropped_img = img.crop(box)
# 显示裁剪后的图像
cropped_img.show()
示例 2:动态裁剪(根据图像尺寸)
from PIL import Image
# 打开图像
img = Image.open("example.jpg")
# 获取图像尺寸
width, height = img.size
# 定义裁剪区域:裁剪图像中心区域
left = width // 4
upper = height // 4
right = 3 * width // 4
lower = 3 * height // 4
box = (left, upper, right, lower)
# 裁剪图像
cropped_img = img.crop(box)
# 显示结果
cropped_img.show()
示例 3:裁剪后保存
from PIL import Image
# 打开图像
img = Image.open("example.jpg")
# 定义裁剪区域
box = (50, 50, 200, 200)
# 裁剪并保存
cropped_img = img.crop(box)
cropped_img.save("cropped_example.jpg")
示例 4:循环裁剪多个区域
from PIL import Image
# 打开图像
img = Image.open("example.jpg")
# 定义多个裁剪区域
regions = [(0, 0, 100, 100), (100, 100, 200, 200), (200, 200, 300, 300)]
# 裁剪并保存每个区域
for i, box in enumerate(regions):
cropped_img = img.crop(box)
cropped_img.save(f"cropped_region_{i + 1}.jpg")
注意事项:
-
坐标范围:
- 裁剪区域的坐标必须在图像范围内,否则会抛出错误或返回空白图像。
-
返回值是新的图像对象:
- 原图像不会被修改,
crop()
返回的是裁剪后的新图像。
- 原图像不会被修改,
-
坐标单位是像素:
- 所有参数的单位为像素,以左上角为坐标原点。
-
区域定义:
- 如果
left == right
或upper == lower
,裁剪结果为空。
- 如果
常见问题:
- 裁剪区域超出图像范围
- 原因:裁剪区域的坐标超出了图像的宽高。
- 解决方法:在定义裁剪区域时,确保坐标值不超过图像尺寸。
width, height = img.size
box = (0, 0, width, height) # 确保裁剪范围有效
- 裁剪结果为空
- 原因:
box
的宽度或高度为零。 - 解决方法:确保
right > left
且lower > upper
。
总结:
Image.crop()
是 Pillow 中常用的方法,用于从图像中裁剪特定区域。- 通过设置裁剪框
(left, upper, right, lower)
,可以精确控制裁剪的区域。 - 它广泛用于图像编辑、处理和机器学习中的预处理工作。
七、ImageEnhance.Contrast()
类+enhance()
方法
在Pillow库(即PIL的升级版本)中,ImageEnhance
模块提供了用于增强图像的工具,其中 Contrast
类用于调整图像的对比度。
ImageEnhance.Contrast(image)
参数:
- image:
- 需要调整对比度的图像对象(
Image
类的实例)。 - 支持多种模式的图像(如
"L"
、"RGB"
等)。
- 需要调整对比度的图像对象(
返回值:
返回一个 ImageEnhance.Contrast
对象,通过其 enhance(factor)
方法可以生成调整后对比度的新图像。
enhance(factor)
用于根据指定的增强因子调整图像的对比度。
参数:
- factor:
- 一个浮点数,用于控制对比度的调整。
- 常见取值范围:
factor = 1.0
: 保持原始对比度(无变化)。factor < 1.0
: 降低对比度,直到完全灰度(factor = 0
时,图像变成单一灰度)。factor > 1.0
: 增强对比度,值越高,对比度越强烈。
返回值:
返回一个新的 Image
对象,其中的对比度已根据给定的因子调整。
使用场景:
- 增强图像细节(提高对比度)。
- 降低对比度以实现柔和效果。
- 图像预处理(为进一步分析或处理准备图像)。
示例 1:增强对比度
from PIL import Image, ImageEnhance
# 打开图像
img = Image.open("example.jpg")
# 创建对比度增强对象
contrast = ImageEnhance.Contrast(img)
# 增强对比度
enhanced_img = contrast.enhance(1.5) # 对比度增强 1.5 倍
# 显示结果
enhanced_img.show()
示例 2:降低对比度
from PIL import Image, ImageEnhance
# 打开图像
img = Image.open("example.jpg")
# 创建对比度增强对象
contrast = ImageEnhance.Contrast(img)
# 降低对比度
reduced_contrast_img = contrast.enhance(0.5) # 对比度降低到 50%
# 显示结果
reduced_contrast_img.show()
示例 3:完全去除对比度
from PIL import Image, ImageEnhance
# 打开图像
img = Image.open("example.jpg")
# 创建对比度增强对象
contrast = ImageEnhance.Contrast(img)
# 设置对比度因子为 0(完全灰度)
gray_img = contrast.enhance(0)
# 显示结果
gray_img.show()
注意事项:
- 输入模式要求:
- 支持多种图像模式(如
"L"
、"RGB"
等),但不支持模式"P"
(调色板模式),需要先转换为"RGB"
。
- 支持多种图像模式(如
- 图像质量:
- 如果对比度因子过高,可能会导致图像细节丢失或颜色溢出。
- 性能:
- 操作会对整幅图像进行逐像素处理,对于较大的图像可能需要更多的处理时间。
实现原理(简述):
对比度调整基于图像的亮度均值,通过调整像素与均值之间的差异幅度来改变对比度:
- 如果因子大于 1,像素值向均值两端扩展,增加对比度。
- 如果因子小于 1,像素值向均值靠近,降低对比度。
ImageEnhance.Contrast
是一个强大的工具,可在对比度调整方面提供灵活性,非常适合在图像增强和预处理任务中使用。
八、综合示例
下面是一个综合示例,展示了如何使用open()
、fromarray()
和save()
函数完成一系列图像处理任务:
import numpy as np
from PIL import Image
# 打开图像文件
img = Image.open('example.jpg')
# 将Image对象转换为NumPy数组
array = np.array(img)
# 对数组进行处理(例如:灰度化)
gray_array = np.dot(array[..., :3], [0.2989, 0.5870, 0.1140])
# 将处理后的数组转换回Image对象
gray_img = Image.fromarray(gray_array.astype('uint8'))
# 保存处理后的图像
gray_img.save('example_gray.png')
通过以上示例,我们可以看到Pillow库在图像处理中的强大功能。希望本文对你有所帮助!