Python受欢迎的原因之一就是其计算生态丰富,据不完全统计,Python 目前为止有约13万+的第三方库。
本系列将会陆续整理分享一些有趣、有用的第三方库。
-
通过百度网盘获取:
链接:https://pan.baidu.com/s/1FSGLd7aI_UQlCQuovVHc_Q?pwd=mnsj提取码:mnsj
-
前往GitHub获取:
https://github.com/returu/Python_Ecosystem
pip install imageio
-
imageio-ffmpeg(用于处理视频文件); -
pyav(用于处理视频文件); -
tifffile(用于处理 TIFF 文件); -
itk 或 SimpleITK(用于 ITK 插件); -
astropy(用于 FITS 插件); -
imageio-flif(用于处理 FLIF 图像文件)。
https://github.com/imageio/imageio
Imageio 的核心 API主要为以下几个函数:
imread() # 用于读取
imwrite() # 用于写入
imiter() # 用于迭代图像序列(动画/视频/OME-TIFF/...)
improps() # 用于获取标准化的元数据
immeta() # 用于获取特定于格式的元数据
imopen() # 用于高级用法
以下是一些Imageio 使用示例:
-
1、读取元数据:
ImageIO 区分两种类型的元数据:特定于格式的元数据和标准化的元数据。
特定于格式的元数据以 Python 字典的形式出现,旨在暴露图像中包含的所有元数据:
import imageio.v3 as iio
metadata = iio.immeta("./data/example.jpg")
print(metadata)
# 输出:{'jfif': 257, 'jfif_version': (1, 1), 'dpi': (96, 96), 'jfif_unit': 1, 'jfif_density': (96, 96), 'mode': 'RGB', 'shape': (478, 299)}
print(metadata["mode"])
# 输出:"RGB"
另一方面,标准化的元数据以 ImageProperties 数据类的形式出现,旨在以标准化的名称和格式独立于底层容器或插件,暴露一组精选的元数据:
import imageio.v3 as iio
props = iio.improps("./data/example.jpg")
print(props)
# 输出:ImageProperties(shape=(299, 478, 3), dtype=dtype('uint8'), n_images=None, is_batch=False, spacing=None)
print(props.shape)
# 输出:(300, 451, 3)
-
2、处理图像:
import imageio.v3 as iio
image = iio.imread('./data/example.jpg') # 读取图像
print(type(image))
# 输出:<class 'numpy.ndarray'>
print(image.shape)
# 输出:(299, 478, 3)
# 写入图像,并转换为 PNG 格式
iio.imwrite('./data/example.png', image)
# 结合 matplotlib 显示图像
import matplotlib.pyplot as plt
plt.imshow(image)
plt.axis('off') # 隐藏坐标轴
plt.show()
如果图像是 GIF 格式,需要设置index 参数用于指定要读取的帧的索引。当 index 设置为 None 时,意味着读取 GIF 动画的所有帧。如果指定一个具体的整数索引,比如 index = 2,则只会读取 GIF 动画中的第 3 帧(索引从 0 开始计数):
import imageio.v3 as iio
# index=None 表示:读取文件中的所有图像,并沿第一轴堆叠
frames = iio.imread("./data/example.gif", index=None)
# ndarray 的形状为
print(frames.shape) # (num_frames, height, width, channel)
# 输出:(38, 230, 434, 3)
-
3、处理视频:
读取或迭代视频中的帧(需要安装 pyav 后端)。
可以通过设置index参数读取单个帧:
import imageio.v3 as iio
import matplotlib.pyplot as plt
# 打开视频文件,读取单个帧(第一帧)
first_frame = iio.imread("./data/example.mp4",index=0)
# 形状
print(first_frame.shape)
# 输出:(480, 480, 3)
# 显示第一帧
plt.imshow(first_frame)
plt.axis('off')
plt.show()
也可以批量读取所有帧,需要注意的是,如果视频过大会占用大量内存:
# 批量读取所有帧
# 警告:大视频会占用大量内存(RAM)
frames = iio.imread("./data/example.mp4")
print(frames.shape)
为了避免批量读取占用大量内存,可以使用imiter()方法来迭代大视频:
# 迭代大视频
for frame in iio.imiter("./data/example.mp4"):
print(frame.shape, frame.dtype) # 输出每一帧的形状和类型
# 输出:(480, 480, 3) uint8
# (480, 480, 3) uint8
# (480, 480, 3) uint8
# ......
以下是一些处理视频的示例代码:
-
读取视频的每一帧,并将它们保存到本地:
import imageio.v3 as iio
import os
# 视频文件路径
video_path = "./data/example.mp4"
# 保存帧的文件夹路径
output_folder = "./data/frames"
# 迭代视频的每一帧
for i, frame in enumerate(iio.imiter(video_path, plugin="pyav")):
# 生成每一帧的保存文件名,例如 frame_0001.jpg
frame_filename = os.path.join(output_folder, f"frame_{i:04d}.jpg")
# 保存当前帧
iio.imwrite(frame_filename, frame)
print(f"保存帧 {i} 到 {frame_filename}")
-
将短片转换为灰度视频(需要安装 ffmpeg 后端)
import imageio.v3 as iio
import numpy as np
# 读取视频(它会加载到内存中)
# 注意:会打开两次图像。
metadata = iio.immeta("./data/example.mp4")
frames = iio.imread("./data/example.mp4", index=None)
# 手动将视频转换为灰度
gray_frames = np.dot(frames, [0.2989, 0.5870, 0.1140])
gray_frames = np.round(gray_frames).astype(np.uint8)
gray_frames_as_rgb = np.stack([gray_frames] * 3, axis=-1)
# 写入视频
iio.imwrite("./data/example_gray.mp4", gray_frames_as_rgb, fps=metadata["fps"])
-
读取本地文件夹中的所有图片,并将它们写入一个视频文件中:
# 导入 imageio 库的 v2 版本,用于读取图像和创建视频写入器
import imageio.v2 as iio
import os
# 定义图片文件夹路径
image_folder = './data/imgs'
# 获取文件夹中所有图片文件的路径
# 所有图像必须具有相同的大小
image_files = [os.path.join(image_folder, f) for f in os.listdir(image_folder)][:3]
output_video = './data/imgs/output_video.mp4'
# 使用 iio.get_writer 创建一个视频写入器对象
w = iio.get_writer(output_video,
format='FFMPEG', # 指定使用 FFMPEG 作为视频编码的后端
mode='I', # 表示只写入关键帧
fps=1, # 设置视频的帧率为 1 帧每秒,即每秒显示一张图片
codec='h264', # 指定使用 H.264 视频编码格式,这是一种广泛使用的高效编码标准
output_params=['-pix_fmt', 'yuv420p'], # 传递给 FFMPEG 的额外参数,指定像素格式为 yuv420p
pixelformat='yuv420p') # 指定视频的像素格式为 yuv420p
# 将图片写入视频
for image_file in image_files:
try:
# 使用 iio.imread 函数读取当前图片文件,将其转换为图像数据
img = iio.imread(image_file)
# 使用视频写入器的 append_data 方法将读取的图像数据添加到视频中
w.append_data(img)
except Exception as e:
print(f"处理 {image_file} 时出现错误: {e}")
# 关闭视频写入器
w.close()
print(f"视频已保存为 {output_video}")
更多内容可以前往官方文档查看:
https://imageio.readthedocs.io/en/stable/


本篇文章来源于微信公众号: 码农设计师
