Pillow 基础图像操作与数据预处理

Pillow 基础图像操作与数据预处理

图像的读取、显示、保存、裁剪、旋转与缩放,是所有高级图像分析任务的基础。这些看似简单的操作,实际上构成了特征提取、图像增强、以及机器学习模型输入准备的核心步骤。只有从最初的像素数据开始,理解图像在计算机中的表达方式,才能真正掌握数据分析与建模中的"图像底层逻辑"。

在图像分析和机器学习任务中,数据预处理的质量往往决定了最终结果的好坏。通过科学的预处理手段,可以有效提升输入数据的均衡性与鲁棒性,从而提高模型的泛化能力。本篇文章将带你系统掌握 Pillow 的基础图像操作与数据预处理技巧,从文件读取到数据转化的全过程,一步步构建完整的图像处理链条。


1. 图像读取与显示

1.1 打开图像

Pillow 提供了直观的图像加载方式。使用 Image.open() 函数即可打开图像文件。

下面以 scikit-image 库自带的经典"宇航员"图为例:

python 复制代码
from PIL import Image
from skimage import data

# 使用 scikit-image 的示例图片
img_array = data.astronaut()  # 经典"宇航员"示例图
img = Image.fromarray(img_array)

# 输出图像信息
print('format: {}\nsize: {}\nmode: {}'.format(
    img.format, img.size, img.mode
))

运行后可看到图像的基本属性,包括格式、尺寸与颜色模式:

txt 复制代码
format: None
size: (512, 512)
mode: RGB

format: 文件格式(如 JPEG、PNG)

size: 图像宽高(像素)

mode: 颜色模式(如 RGB、L、RGBA)

这说明该图像为标准 RGB 彩色图像,宽高均为 512 像素。

1.2 显示图像

在不同环境中显示图像的方式略有不同:

python 复制代码
img.show()

该方法会打开系统自带的图片查看器。

如果你在 Jupyter Notebook 中运行,则推荐:

python 复制代码
from IPython.display import display
display(img)

你将看到一张清晰的宇航员照片(RGB 彩色),适合后续图像操作实验。


2. 图像保存与格式转换

读取后的图像可通过 save() 方法保存为新文件。

2.1 保存为新文件

下面的示例将图像保存为 PNG 文件:

python 复制代码
img.save('output.png')

同样也可以调整保存格式与参数。例如,将图像保存为 JPEG 格式,并设定较高的质量参数:

python 复制代码
img.save('output.jpg', quality=90)

quality 参数仅对 JPEG 有效,控制压缩质量(0--100,默认 75)。

数值越大,文件体积越大但图像更清晰。

2.2 格式转换

当目标格式不支持透明通道(如 JPEG),需先将图像转换为 RGB 模式:

python 复制代码
img.convert('RGB').save('converted.jpg')

若目标格式不支持透明度(如 JPEG),需先转为 RGB 模式。


3. 几何变换:裁剪、旋转与缩放

这些是最常见的图像几何变换操作。

3.1 图像裁剪

图像几何操作是最直观的预处理方式。使用 crop() 方法可以截取特定区域(左、上、右、下),例如::

python 复制代码
box = (100, 100, 400, 400)
cropped = img.crop(box)

display(cropped)

此处 box 参数定义了裁剪矩形的左、上、右、下边界,输出的结果是一幅截取后的局部图像。

3.2 图像旋转

当我们想让图像朝某个角度旋转时,可以使用 rotate() 方法。参数为旋转角度(单位为度):

python 复制代码
rotated1 = img.rotate(45)

display(rotated1)

expand=True 的设置确保旋转后的图像不会被裁剪,使得完整图像得以保留。

python 复制代码
rotated2 = img.rotate(45, expand=True)

display(rotated2)

3.3 图像缩放

若要调整图像的尺寸,可使用 resize() 函数指定目标大小,例如将其缩小为 300×200 像素:

python 复制代码
resized = img.resize((300, 200))
resized.show()

或按比例缩放:

python 复制代码
w, h = img.size
scaled = img.resize((int(w*0.5), int(h*0.5)))

display(scaled)

在缩放时,可选参数如 Image.BILINEARImage.ANTIALIAS 可以帮助提升插值质量,使结果更加平滑自然。


4. 图像模式与通道

图像的"模式"决定了其数据结构。RGB 图像包含三个通道,而灰度图仅有一个。

4.1 查看图像模式

通过 img.mode 可查看当前模式,convert() 方法则用于模式转换。例如:

python 复制代码
print(img.mode)
txt 复制代码
RGB

常见模式包括:

模式 含义 通道数
L 灰度图 1
RGB 真彩色 3
RGBA 含透明通道 4
CMYK 印刷色彩模式 4

4.2 模式转换

python 复制代码
gray = img.convert('L')
gray.show()

上述代码将彩色图像转为灰度图,其视觉效果更简洁,常用于特征提取或边缘检测任务。

若需要用于印刷或 CMYK 色彩空间的任务,可使用:

python 复制代码
cmyk = img.convert('CMYK')

print(cmyk.mode)
txt 复制代码
CMYK

每个模式代表着不同的应用场景。RGB 用于显示设备,CMYK 常见于印刷出版,而 RGBA 额外包含透明度信息。

4.3 拆分与合并通道

Pillow 允许直接拆分通道以便单独分析:

python 复制代码
r, g, b = img.split()  # 拆分
merged = Image.merge('RGB', (r, g, b))  # 合并

为了更直观地理解三个通道的作用,可以通过 matplotlib 将它们分别可视化:

python 复制代码
from PIL import Image
from skimage import data
import matplotlib.pyplot as plt
import seaborn as sns

sns.set_theme(style="whitegrid", font="SimHei", rc={"axes.unicode_minus": False})

# 加载示例图像
img = Image.fromarray(data.astronaut())

# 拆分 RGB 通道
r, g, b = img.split()

# 可视化展示
fig, axes = plt.subplots(1, 3, figsize=(16, 5))

# 将单通道转为彩色可视化形式
axes[0].imshow(r, cmap="Reds")
axes[0].set_title("红色通道 (R)")
axes[0].axis("off")

axes[1].imshow(g, cmap="Greens")
axes[1].set_title("绿色通道 (G)")
axes[1].axis("off")

axes[2].imshow(b, cmap="Blues")
axes[2].set_title("蓝色通道 (B)")
axes[2].axis("off")

plt.tight_layout()
plt.show()

可以清晰地看到红、绿、蓝三种通道对整体图像色彩的贡献。拆分后的通道也能重新组合回完整图像:

python 复制代码
merged = Image.merge('RGB', (r, g, b))

display(merged)

这证明图像的彩色信息实质上是多个单通道数据叠加的结果。


5. 批量图像处理

在深度学习或大规模图像分析任务中,往往需要对整个文件夹中的图像执行统一的操作。Pillow 的接口设计非常简洁,能够方便地完成批处理。例如,下面的代码将一个目录中的所有图片缩放至 256×256 像素,并统一转换为灰度图:

python 复制代码
import os
from PIL import Image

# 定义输入与输出文件夹路径
input_dir = 'images/'       # 原始图片所在目录
output_dir = 'processed/'   # 处理后图片保存目录

# 如果输出目录不存在则自动创建
os.makedirs(output_dir, exist_ok=True)

# 定义要处理的图片扩展名集合
valid_exts = ('.jpg', '.png', '.bmp')

# 遍历输入文件夹中的所有文件
for file in os.listdir(input_dir):
    # 判断文件扩展名是否符合要求
    if file.lower().endswith(valid_exts):
        # 构建文件路径
        file_path = os.path.join(input_dir, file)

        # 打开图像文件
        img = Image.open(file_path)

        # 调整图像尺寸为256x256像素
        resized = img.resize((256, 256))

        # 将图像转换为灰度模式(L表示8位灰度)
        gray = resized.convert('L')

        # 构建输出文件路径并保存
        output_path = os.path.join(output_dir, file)
        gray.save(output_path)

        # 打印处理进度
        print(f"已处理: {file}")

所有图片统一缩放为 256×256;

转为灰度图;

保存到 processed 文件夹中。

这段脚本能自动遍历整个文件夹并完成批量预处理。执行后,你将得到格式统一、尺寸一致的图像数据集,这对于后续特征提取与模型训练至关重要。


6. 图像数据与 NumPy 的融合

Pillow 图像与 NumPy 数组可以无缝互转,从而实现像素级运算或与深度学习框架(如 TensorFlow、PyTorch)的对接。通过 np.array(img) 可将图像转换为数组:

python 复制代码
import numpy as np

array = np.array(img)
print(array.shape)
txt 复制代码
(512, 512, 3)

输出结果 (512, 512, 3) 表示图像的高、宽与通道数。反向操作也同样简单:

python 复制代码
img2 = Image.fromarray(array)
display(img2)

这样,Pillow 成为了连接传统图像处理与数值分析的桥梁。你可以使用 NumPy 对像素值进行归一化、滤波或其他矩阵操作,然后再返回到图像空间。


7. 图像归一化与增强准备

在模型训练或特征学习阶段,通常需要将像素值标准化到 [0,1] 区间,以消除亮度差异带来的影响。通过简单的数组运算即可实现:

python 复制代码
array = np.array(img) / 255.0

print(array)
txt 复制代码
[[[0.60392157 0.57647059 0.59215686]
  [0.42745098 0.40392157 0.48627451]
  [0.24705882 0.22745098 0.4       ]
  ...
  [0.49803922 0.47058824 0.45098039]
  [0.47058824 0.45882353 0.41568627]
  [0.49019608 0.46666667 0.43137255]]

 [[0.69411765 0.67058824 0.67058824]
  [0.56470588 0.55294118 0.56078431]
  [0.44313725 0.44705882 0.48627451]
  ...
  [0.49803922 0.4627451  0.43921569]
  [0.48627451 0.45098039 0.42352941]
  [0.4745098  0.45490196 0.41176471]]

 ...

 [[0.71764706 0.6627451  0.66666667]
  [0.71372549 0.65490196 0.67058824]
  [0.7254902  0.64313725 0.69019608]
  ...
  [0.         0.         0.00392157]
  [0.00392157 0.00392157 0.00392157]
  [0.         0.         0.        ]]

 [[0.72156863 0.65490196 0.6745098 ]
  [0.71764706 0.64705882 0.6627451 ]
  [0.70588235 0.63529412 0.67058824]
  ...
  [0.         0.         0.        ]
  [0.00392157 0.00392157 0.00392157]
  [0.         0.         0.        ]]]

归一化后的结果可以被视为浮点型矩阵,方便后续输入神经网络或进行特征统计。若结合图像增强方法(如旋转、翻转、噪声扰动),还可以有效提升模型的泛化能力。

或使用随机翻转、旋转等增强方法:

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
from skimage import data
from PIL import Image

# 载入示例图像并转换为数组
img = Image.fromarray(data.astronaut())
array = np.array(img)

# 进行归一化处理:将像素值缩放到 [0, 1] 区间
normalized = array / 255.0

# 可视化原图与归一化结果对比
fig, axes = plt.subplots(1, 2, figsize=(10, 4))
axes[0].imshow(array.astype(np.uint8))
axes[0].set_title("原始图像(像素0-255)")
axes[0].axis("off")

axes[1].imshow(normalized)
axes[1].set_title("归一化后图像(像素0-1)")
axes[1].axis("off")

plt.tight_layout()
plt.show()
python 复制代码
# 输出示例像素值,观察归一化效果
print("原始像素示例:", array[0, 0])
print("归一化像素示例:", normalized[0, 0])
txt 复制代码
原始像素示例: [154 147 151]
归一化像素示例: [0.60392157 0.57647059 0.59215686]

经过归一化处理后,原始图像中的每个像素值由 0--255 的整数变为 0--1 的浮点数,这不仅让模型更快收敛,也有助于避免梯度爆炸或消失的问题。


8. 可视化与结果展示

为了方便比对原始与处理后的图像,可使用 Matplotlib:

python 复制代码
import matplotlib.pyplot as plt

gray = img.convert('L')

plt.figure(figsize=(8,4))
plt.subplot(1,2,1)
plt.title('原始图像')
plt.imshow(img)
plt.axis('off')

plt.subplot(1,2,2)
plt.title('灰度图像')
plt.imshow(gray, cmap='gray')
plt.axis('off')
plt.show()

9. 总结

Pillow 以其简洁的接口和强大的功能,成为 Python 图像处理的基础工具。从读取到保存、从几何变换到通道分解、再到批量化处理与数值融合,它覆盖了图像预处理的全流程。

掌握这些操作,不仅能帮助你更高效地准备数据集,也能让你更深入地理解图像的数学本质与结构特征。

相关推荐
素素.陈3 小时前
向RAGFlow中上传文档到对应的知识库
开发语言·python
小宁爱Python3 小时前
Django Web 开发系列(一):视图基础与 URL 路由配置全解析
后端·python·django
GIS数据转换器3 小时前
带高度多边形,生成3D建筑模型,支持多种颜色或纹理的OBJ、GLTF、3DTiles格式
数据库·人工智能·机器学习·3d·重构·无人机
空影星3 小时前
SiriKali,一款跨平台的加密文件管理器
python·编辑器·电脑·智能硬件
阿_旭4 小时前
基于深度学习的甲状腺结节智能检测分割与诊断系统【python源码+Pyqt5界面+数据集+训练代码】
人工智能·python·深度学习·甲状腺结节检测
woshihonghonga4 小时前
PyTorch矩阵乘法函数区别解析与矩阵高级索引说明——《动手学深度学习》3.6.3、3.6.4和3.6.5 (P79)
人工智能·pytorch·python·深度学习·jupyter·矩阵
CLubiy4 小时前
【研究生随笔】Pytorch中的线性代数(微分)
人工智能·pytorch·深度学习·线性代数·梯度·微分
美狐美颜SDK开放平台4 小时前
直播美颜SDK功能开发实录:自然妆感算法、人脸跟踪与AI美颜技术
人工智能·深度学习·算法·美颜sdk·直播美颜sdk·美颜api
明朝百晓生5 小时前
强化学习【Monte Carlo Learning][MC Basic 算法]
人工智能·机器学习