视频文件在进行关键内容提取的时候,人工观看,会比较费时,即使快进播放视频,一小时的视频,也需要十几分钟,或者更长时间;通常情况下,一秒钟的视频包含24帧图像,如果能够把视频中的关键帧“捕获”下来,尤其是在相似镜头拍摄时间比较久的场景,对图片去重,将有助于过滤掉绝大多数的“噪点”帧,最大程度上提取视频的核心内容。
同步推进更优的三种关键帧提取方案,效果和性能更佳:
视频提取关键帧工具类KeyFramesExtractUtils.py,动态支持三种取帧方式,关键参数可配置,代码经过优化处理,效果和性能更好。_君临天下tjm的博客-CSDN博客项目中可以直接导入该工具类KeyFramesExtractUtils.py,三种取帧方式通过参数选择,method可以取"use_top_order"、"use_thresh"、"use_local_maxima"中的任何一种,第三种方式效果最佳,默认也是"use_local_maxima"。视频帧的提取率约为1.66‰,21m15s的视频,耗时约330s(即5分30秒)。...https://blog.csdn.net/shanxiderenheni/article/details/125891527
同步另外三种视频提取关键帧的方法:
视频提取关键帧的三种方式【已调通】https://blog.csdn.net/shanxiderenheni/article/details/124499862
pip install -i https://pypi.douban.com/simple/ av
pip install -i https://pypi.douban.com/simple/ pillow
# -*- coding: utf-8 -*-
"""
@author: tjm
@software: PyCharm
@file: pyav_test.py
@time: 2021/11/1 11:10
"""
# 虚拟环境:py36_pyav_env
# 视频提取关键帧
import av
import os
import shutil
# 存原始视频的目录
dir_video_src = os.path.join(os.getcwd(), '.\\videos')
# 存处理后提取到关键帧图片数据的目录
dir_video_des = os.path.join(os.getcwd(), '.\\images')
# 扫描视频文件,检查/videos下是否有视频文件
print(dir_video_src + '\r\n')
list_video = []
for item_filename in os.listdir(dir_video_src):
list_video.append(item_filename)
print(item_filename)
if len(list_video) == 0:
print(".\\videos\\:视频文件不存在")
# 定义提取视频关键帧的函数
def extract_video(filename):
container = av.open(filename)
# Signal that we only want to look at keyframes.
stream = container.streams.video[0]
stream.codec_context.skip_frame = 'NONKEY'
for frame in container.decode(stream):
frame.to_image().save(
'frame.{:04d}.png'.format(frame.pts),
quality=80,
)
# 提取关键帧并保存
def do_video2image():
for filename in list_video:
file_dir_desc = os.path.join(dir_video_des, filename)
if not os.path.exists(file_dir_desc):
os.makedirs(file_dir_desc)
print("已自动创建:", file_dir_desc)
else:
print("合并后的目录已存在")
# 提取关键帧
extract_video(os.path.join(dir_video_src, filename))
# 把关键帧图片放到data/processed下
for filename_png in os.listdir(os.getcwd()):
if ".png" in filename_png:
# shutil.move(filename_png, file_dir_desc)
shutil.copy2(filename_png, file_dir_desc)
os.remove(filename_png)
print(filename_png)
if __name__ == '__main__':
do_video2image()
案例中一个48秒的视频,最后提取出5张关键帧,极大的提高了视频观看效率,也支持批量视频操作。
请注意:关键帧的数目与视频的拍摄质量和延时有关,如果镜头转移的很慢,拍摄清晰度很高,那么关键帧提取的效果越好。
# -*- coding: utf-8 -*-
"""
@author: tjm
@software: PyCharm
@file: PyAvUtils.py
@time: 2022/4/15 14:09
"""
import av
import os
import shutil
# 视频提取关键帧工具类(支持批量视频)
class PyAvUtils:
def __init__(self, video_dir, keyframe_dir):
self.video_dir = video_dir
self.keyframe_dir = keyframe_dir
# 提取关键帧并保存
def do_video2image(self):
for video_name in os.listdir(self.video_dir):
print(video_name)
video_keyframe_dir = os.path.join(self.keyframe_dir, video_name)
if not os.path.exists(video_keyframe_dir):
os.makedirs(video_keyframe_dir)
print("已自动创建:", video_keyframe_dir)
else:
print("目录已存在")
# 提取关键帧
self.extract_video(video_name)
# 定义提取视频关键帧的函数
def extract_video(self, filename):
cur_video_path = os.path.join(self.video_dir, filename)
cur_video_keyframe_dir = os.path.join(self.keyframe_dir, filename)
container = av.open(cur_video_path)
# Signal that we only want to look at keyframes.
stream = container.streams.video[0]
stream.codec_context.skip_frame = 'NONKEY'
for frame in container.decode(stream):
frame.to_image().save(cur_video_keyframe_dir + '/' + 'frame.{:04d}.jpg'.format(frame.pts),
quality=90)
if __name__ == '__main__':
pa = PyAvUtils('.\\videos', '.\\images')
pa.do_video2image()