简介
本教程将指导您如何使用Python编写一个脚本,该脚本能够从视频文件中提取不同的帧并保存它们。我们将使用OpenCV库来处理视频文件,并使用Pillow库来处理图像。此外,我们还将使用imagehash库来计算每帧的感知哈希值,以便识别并跳过视觉上相似的帧。
环境准备
在开始之前,请确保您的Python环境中已安装以下库:
- OpenCV (
cv2
) - Pillow (
PIL
) - imagehash
您可以使用pip安装这些库:
pip install opencv-python-headless pillow imagehash
代码解析
完整代码
import cv2
import imagehash
from PIL import Image
def extract_frames(video_file, target_dir, frame_skip=30, ext='png', quality=95):
"""
从视频中提取不同帧并保存
使用感知哈希判断两图是否相同
:param video_file: 视频文件路径
:param target_dir: 帧图的保存目录
:param frame_skip: 跳过帧
:param ext: 保存帧文件后缀,如png ,jpg
:param quality: 保存jpg图的压缩质量
:return:
"""
cap = cv2.VideoCapture(str(video_file))
# 计算视频帧总数
total_frame = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# 设置初始帧位置
frame_index = 0
# 前一帧哈希
last_hash = None
while frame_index < total_frame:
# 设置到下一个要处理的帧
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_index)
# 读取帧
ret, frame = cap.read()
if not ret:
break
# 计算帧图感知哈希
image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
frame_hash = imagehash.phash(image)
# 保存第一帧与之后不同的帧
if (last_hash is None) or (frame_hash - last_hash != 0):
# 帧图文件路径
frame_path = f'{target_dir}/{frame_hash}.{ext}'
# 保存帧
image.save(frame_path, quality=quality)
print(f'保存帧图:{frame_path}')
# 更新前一帧哈希
last_hash = frame_hash
else:
print(f'跳过相同帧:{frame_index}')
# 更新帧计数器
frame_index += frame_skip
cap.release()
以下是extract_frames
函数的详细解析,该函数是脚本的核心,用于从视频中提取帧。
导入库
import cv2
import imagehash
from PIL import Image
cv2
:OpenCV库,用于视频处理。imagehash
:用于计算图像的哈希值。PIL.Image
:Pillow库中的Image模块,用于图像处理。
定义函数
def extract_frames(video_file, target_dir, frame_skip=30, ext='png', quality=95):
video_file
:视频文件的路径。target_dir
:保存帧的目录。frame_skip
:跳过的帧数,默认为30。ext
:保存帧的文件扩展名,默认为png
。quality
:保存为jpg时的压缩质量,默认为95。
打开视频文件
cap = cv2.VideoCapture(str(video_file))
使用cv2.VideoCapture
打开视频文件。
计算视频帧总数
total_frame = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
获取视频的总帧数。
初始化变量
frame_index = 0
last_hash = None
frame_index
:当前处理的帧索引。last_hash
:上一个处理的帧的哈希值。
循环处理帧
while frame_index < total_frame:
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_index)
ret, frame = cap.read()
if not ret:
break
循环遍历每一帧,使用cap.read()
读取帧。
计算感知哈希
image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
frame_hash = imagehash.phash(image)
将BGR格式的帧转换为RGB,然后计算感知哈希值。
保存帧
if (last_hash is None) or (frame_hash - last_hash != 0):
frame_path = f'{target_dir}/{frame_hash}.{ext}'
image.save(frame_path, quality=quality)
print(f'保存帧图:{frame_path}')
last_hash = frame_hash
else:
print(f'跳过相同帧:{frame_index}')
如果当前帧的哈希值与上一个帧不同,则保存该帧。否则,跳过该帧。
更新帧计数器
frame_index += frame_skip
更新帧计数器,跳过指定的帧数。
释放资源
cap.release()
释放视频捕获对象。
使用方法
要使用此脚本,您需要指定视频文件路径和目标目录。例如:
extract_frames('path/to/your/video.mp4', 'path/to/save/frames')
这将从指定的视频文件中提取帧,并保存到指定的目录中。
结论
通过本教程,您应该能够理解如何使用Python和OpenCV从视频中提取帧,并使用感知哈希来判断帧之间的差异。这种方法特别适用于需要从视频中提取关键帧或减少存储空间的场景。