一、imread() 是什么?
imread()方法是 Matplotlib 库中的一个函数,用于从图像文件中读取图像数据。
核心用途:
| 用途 | 说明 |
|---|---|
| 读取图像 | 将图片文件转为 NumPy 数组 |
| 图像分析 | 对像素数据进行统计与处理 |
| 图像变换 | 调整亮度、裁剪、修改通道 |
| 数据准备 | 为机器学习提供图像输入 |
与 imsave() 的关系:
| 函数 | 作用 | 方向 |
|---|---|---|
imread() | 读取图像为数组 | 文件 → 数组 |
imsave() | 保存数组为图像 | 数组 → 文件 |
二、imread() 函数语法
python
matplotlib.pyplot.imread(fname, format=None)
参数说明:
| 参数 | 说明 |
|---|---|
fname | 要读取的图像文件名或路径,可以是相对路径或绝对路径 |
format | 图像文件格式,不指定则默认根据文件后缀名自动识别 |
返回值:numpy.ndarray对象,形状为(nrows, ncols, nchannels),表示读取的图像的行数、列数和通道数。
通道数含义:
| 图像类型 | nchannels | 说明 |
|---|---|---|
| 灰度图像 | 1 | 单一亮度通道 |
| 彩色图像 | 3 | 红、绿、蓝三个颜色通道 |
| 带透明图像 | 4 | RGB + alpha 通道 |
三、基础实例:读取并显示图像
python
import matplotlib.pyplot as plt # 读取图像文件 img = plt.imread('map.jpeg') # 显示图像 plt.imshow(img) plt.show()
以上实例中我们首先使用imread()方法从名为map.jpeg的图像文件中读取了图像数据,并将其存储在img变量中。然后使用imshow()方法显示了这张图像。
注意:我们在显示图像时没有指定颜色映射,这是因为
imread()方法已经将图像数据按照正确的颜色映射转换成了 RGB 格式,因此我们可以直接使用默认的颜色映射来显示图像。
检查图像数组信息:
python
import matplotlib.pyplot as plt img = plt.imread('map.jpeg') print(type(img)) # <class 'numpy.ndarray'> print(img.shape) # (高度, 宽度, 通道数) print(img.dtype) # uint8 或 float32 print(img.min(), img.max()) # 值域范围
常见 dtype:
| dtype | 值域 | 说明 |
|---|---|---|
uint8 | 0-255 | JPEG、PNG 常见 |
float32 | 0.0-1.0 | 部分 PNG、浮点图像 |
四、图像的本质:NumPy 数组
我们可以通过更改 NumPy 数组来修改图像。
1. 调整亮度
例如,如果我们将数组乘以一个数 0≤x≤10≤x≤1,我们将图像变暗:
python
import matplotlib.pyplot as plt # 读取图像文件 img_array = plt.imread('tiger.jpeg') tiger = img_array / 255 # 归一化到 0-1 # 显示图像 plt.figure(figsize=(10, 6)) for i in range(1, 5): plt.subplot(2, 2, i) x = 1 - 0.2 * (i - 1) # 1.0, 0.8, 0.6, 0.4 plt.axis('off') # 隐藏坐标轴 plt.title('x={:.1f}'.format(x)) plt.imshow(tiger * x) plt.show()
代码解析:
| 代码 | 作用 |
|---|---|
img_array / 255 | 将 0-255 归一化到 0-1 |
tiger * x | 乘以系数,降低亮度 |
plt.axis('off') | 隐藏坐标轴 |
plt.subplot(2, 2, i) | 创建 2×2 子图 |
亮度系数效果:
| 系数 x | 效果 |
|---|---|
| 1.0 | 原始亮度 |
| 0.8 | 稍微变暗 |
| 0.6 | 明显变暗 |
| 0.4 | 很暗 |
为什么除以 255?因为
uint8类型的值域是 0-255,直接乘以小数会出问题。归一化到 0-1 后,乘法才有平滑的调暗效果。
2. 裁剪图像
python
import matplotlib.pyplot as plt # 读取图像文件 img_array = plt.imread('tiger.jpeg') tiger = img_array / 255 # 显示裁剪后的图像 plt.figure(figsize=(6, 6)) plt.imshow(tiger[:300, 100:400, :]) plt.axis('off') plt.show()
切片语法解析:
text
tiger[:300, 100:400, :] ↑ ↑ ↑ 行 0-299 列 100-399 所有通道
| 切片 | 含义 |
|---|---|
[:300] | 取前 300 行(高度) |
[100:400] | 取第 100 到 399 列(宽度) |
[:] | 取所有通道 |
图像坐标记忆:数组形状为
(高度, 宽度, 通道),所以第一个维度是行(y 方向),第二个维度是列(x 方向)。
3. 修改颜色通道
如果我们将 RGB 颜色的绿色和蓝色坐标的数组元素设置为 0,我们将得到红色的图像:
python
import matplotlib.pyplot as plt # 读取图像文件 img_array = plt.imread('tiger.jpeg') tiger = img_array / 255 # 显示红色图像 red_tiger = tiger.copy() red_tiger[:, :, [1, 2]] = 0 # 绿色和蓝色通道置 0 plt.figure(figsize=(10, 10)) plt.imshow(red_tiger) plt.axis('off') plt.show()
通道索引说明:
| 索引 | 通道 |
|---|---|
[:, :, 0] | 红色(R) |
[:, :, 1] | 绿色(G) |
[:, :, 2] | 蓝色(B) |
常见颜色效果:
| 操作 | 效果 |
|---|---|
img[:, :, [1, 2]] = 0 | 只保留红色 |
img[:, :, [0, 2]] = 0 | 只保留绿色 |
img[:, :, [0, 1]] = 0 | 只保留蓝色 |
img[:, :, 1] = 0 | 去掉绿色(偏品红) |
img.mean(axis=2) | 转为灰度 |
为什么要用 copy()?直接修改会改变原数组,用
copy()保留原始数据,便于对比。
五、灰度转换
python
import matplotlib.pyplot as plt img_array = plt.imread('tiger.jpeg') tiger = img_array / 255 # 方法一:对通道求平均 gray = tiger.mean(axis=2) # 方法二:加权平均(符合人眼感知) gray_weighted = (0.299 * tiger[:, :, 0] + 0.587 * tiger[:, :, 1] + 0.114 * tiger[:, :, 2]) plt.figure(figsize=(12, 5)) plt.subplot(1, 3, 1) plt.imshow(tiger) plt.title('Original') plt.axis('off') plt.subplot(1, 3, 2) plt.imshow(gray, cmap='gray') plt.title('Average Gray') plt.axis('off') plt.subplot(1, 3, 3) plt.imshow(gray_weighted, cmap='gray') plt.title('Weighted Gray') plt.axis('off') plt.show()
灰度转换公式:
| 方法 | 公式 |
|---|---|
| 简单平均 | (R + G + B) / 3 |
| 加权平均 | 0.299R + 0.587G + 0.114B |
推荐:加权平均更符合人眼对颜色的感知,绿色权重最高,蓝色最低。
六、常用图像操作速查
| 操作 | 代码 |
|---|---|
| 读取图像 | img = plt.imread('file.png') |
| 查看形状 | img.shape |
| 归一化 | img / 255 |
| 调暗 | img * 0.5 |
| 调亮 | np.clip(img * 1.5, 0, 1) |
| 裁剪 | img[100:300, 200:400] |
| 翻转(上下) | img[::-1] |
| 翻转(左右) | img[:, ::-1] |
| 旋转 90° | np.rot90(img) |
| 转灰度 | img.mean(axis=2) |
| 只留红色 | img[:, :, [1, 2]] = 0 |
| 保存图像 | plt.imsave('out.png', img) |
调亮时为什么要用 np.clip?
python
import numpy as np # 错误:超过 1 的部分会被截断或异常 bright = img * 1.5 # 正确:限制在 0-1 之间 bright = np.clip(img * 1.5, 0, 1)
七、完整实战:图像处理流水线
python
import matplotlib.pyplot as plt import numpy as np # 中文配置 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False # 1. 读取图像 img = plt.imread('tiger.jpeg') / 255 # 2. 处理 original = img.copy() dark = np.clip(img * 0.5, 0, 1) # 调暗 cropped = img[100:400, 150:450, :] # 裁剪 red_only = img.copy() red_only[:, :, [1, 2]] = 0 # 只留红色 gray = img.mean(axis=2) # 灰度 # 3. 展示 fig, axes = plt.subplots(1, 5, figsize=(20, 4)) titles = ['原图', '调暗', '裁剪', '只留红色', '灰度'] images = [original, dark, cropped, red_only, gray] for ax, title, image in zip(axes, titles, images): ax.imshow(image, cmap='gray' if image.ndim == 2 else None) ax.set_title(title, fontsize=14) ax.axis('off') plt.tight_layout() plt.show()
效果:一张图展示五种处理结果,对比清晰。
八、imread() 处理流程图
九、常见问题排查
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
FileNotFoundError | 文件路径错误 | 检查路径,使用绝对路径或确认文件存在 |
| 图像显示异常 | 未归一化 | uint8需/255转为 0-1 |
| 调暗后全黑 | 系数过小 | 调整系数,或用np.clip |
| 调亮后过曝 | 超过 1 未截断 | 使用np.clip(img, 0, 1) |
| 通道操作无效 | 未用 copy | 添加.copy() |
| 中文路径报错 | 编码问题 | 使用英文路径 |
| 格式识别错误 | 扩展名与实际不符 | 显式指定format参数 |
| 显示为负片 | 数据被错误处理 | 检查数组值域 |
十、小结
本篇你掌握了 Matplotlib imread() 的完整用法:
imread() 函数:
fname文件名,返回 NumPy 数组。数组结构:形状
(高度, 宽度, 通道),dtype 通常为uint8。归一化:
img / 255将值域转到 0-1。亮度调整:乘以系数,配合
np.clip防止越界。图像裁剪:数组切片
img[行范围, 列范围, :]。通道操作:
img[:, :, [1, 2]] = 0只保留红色。灰度转换:
img.mean(axis=2)或加权平均。
imread() 让图像变成可编程的数组,打开了图像处理的大门。下一篇我们将学习Matplotlib 箱线图,用箱体展示数据的统计特征。