当前位置: 首页 > news >正文

python实现提取视频帧的图片

文章目录

  • 1、需求痛点
  • 2、完整代码⭐
  • 3、代码分析
    • 3.1、需要改动的地方
    • 3.2、OpenCV库的使用
    • 3.3、多线程技术
  • 4、执行效率
  • 5、效果展示⭐
  • 6、注意事项🔺
  • 7、总结

🍃作者介绍:双非本科大三网络工程专业在读,阿里云专家博主,专注于Java领域学习,擅长web应用开发、数据结构和算法,初步涉猎人工智能和前端开发。
🦅个人主页:@逐梦苍穹
📕所属专栏:项目
🌻您的一键三连,是我创作的最大动力🌹

1、需求痛点

有时候看见一个视频,想要截图里面的素材来自己用,但是此时又记不得自己需要的内容大概在视频的哪个地方,那么就得从头看视频不断暂停播放视频循环往复 ,以寻找需要的内容进行截图。
那么,本文就带你用 python 实现一个提取视频帧的程序把视频帧提取成图片
然后你只需要在键盘上利用 “->” 键,就可以轻松快速的找到想要的素材内容。
那么话不多说,进入正题!

2、完整代码⭐

# -*- coding: utf-8 -*-
# @Author:︶ㄣ释然
# @Time: 2024/7/31 1:19import cv2  # 导入OpenCV库,用于视频处理
import os  # 导入os库,用于文件和目录操作
import concurrent.futures  # 导入并发库,用于多线程处理
import time  # 导入时间库,用于计算时间# 定义保存帧的函数
def save_frame(frame, frame_filename):cv2.imwrite(frame_filename, frame)  # 使用OpenCV保存帧到文件# 定义提取视频帧的函数
def extract_frames(video_path, output_folder, frame_interval, max_threads):cap = cv2.VideoCapture(video_path)  # 打开视频文件frame_count = 0  # 初始化帧计数器futures = []  # 初始化futures列表,用于存储线程任务start_time = time.time()  # 记录开始时间# 使用ThreadPoolExecutor创建一个线程池,最大线程数为max_threadswith concurrent.futures.ThreadPoolExecutor(max_workers=max_threads) as executor:while cap.isOpened():  # 当视频文件打开时ret, frame = cap.read()  # 读取一帧if not ret:  # 如果读取失败,跳出循环breakif frame_count % frame_interval == 0:  # 每隔frame_interval帧处理一次seconds = frame_count // frame_interval  # 计算当前帧对应的秒数frame_filename = os.path.join(output_folder, f'frame_{seconds:04d}.jpg')  # 构建帧文件名futures.append(executor.submit(save_frame, frame, frame_filename))  # 提交保存帧的任务到线程池frame_count += 1  # 增加帧计数器cap.release()  # 释放视频文件for future in concurrent.futures.as_completed(futures):  # 等待所有线程完成future.result()  # 获取线程结果end_time = time.time()  # 记录结束时间elapsed_time = end_time - start_time  # 计算执行时间print(f'提取完成,共提取了 {frame_count // frame_interval} 帧')  # 输出提取的帧数print(f'程序执行时间: {elapsed_time:.2f} 秒')  # 输出程序执行时间# 创建文件夹保存帧
output_folder = 'video_frames'
os.makedirs(output_folder, exist_ok=True)  # 如果文件夹不存在,则创建# 打开视频文件
video_path = '1.mp4'# 获取视频帧率
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)  # 获取视频的帧率
cap.release()  # 释放视频文件
frame_interval = int(1 * fps)  # 每秒提取一帧# 用户指定的线程数
max_threads = 8# 提取视频帧
extract_frames(video_path, output_folder, frame_interval, max_threads)  # 调用提取帧的函数

3、代码分析

3.1、需要改动的地方

首先,保存图片的文件夹名称,你可以修改:
在这里插入图片描述

然后,你需要把视频下载下来,填写视频路径:
在这里插入图片描述

接着,本程序是多线程的,你需要指定你所需要的线程数量:
在这里插入图片描述

最后,该程序默认是一秒提取一帧图片,你可以修改这个数字:
在这里插入图片描述

1 * fps"即每秒提取一帧图片,同理,如果想要十秒提取一张,则是"10 * fps”。

3.2、OpenCV库的使用

OpenCV是一个强大的计算机视觉库,支持视频和图像处理。
在本程序中,OpenCV被用来读取视频文件和保存帧图像。
cv2.VideoCapture用于打开视频文件,cv2.imwrite用于将帧图像保存到文件。

3.3、多线程技术

为了提高帧提取和保存的效率,程序使用了Python的concurrent.futures库中的ThreadPoolExecutor进行多线程处理。
ThreadPoolExecutor允许我们轻松地管理和调度多个线程,特别适合I/O密集型任务。
该程序实现了从视频中每秒提取一帧并多线程保存到文件夹的功能,极大地提升了处理效率。
多线程的使用有效地利用了计算资源,减少了帧提取和保存过程中的等待时间。

4、执行效率

我的CPU型号:11th Gen Intel® Core™ i5-1135G7 @ 2.40GHz (8 CPUs), ~2.4GHz

经过我的测试:提取13分钟的视频,每秒一帧共提取出800张图,8线程,用时是 2分钟
在这里插入图片描述

5、效果展示⭐

运行程序之后,会生成一个文件夹,里面是保存的图片,效果如下图:
在这里插入图片描述

清晰度都不错,放几张给大家看一下:
在这里插入图片描述
在这里插入图片描述

此时你想要哪个素材,就不用一直在视频里面不断重复暂停、播放的过程了。

6、注意事项🔺

用了别人的素材,如果需要发成文章,比如像我这样发一篇博客的话,最好艾特原作者或者附上引用素材的链接。
我这里用到的演示视频,用于提取素材图片,来源于:
https://www.bilibili.com/video/BV1fY411H7g8?t=245.4

7、总结

通过对该代码的分析,我们可以看到利用Python的多线程技术可以显著提高视频处理任务的效率。
OpenCV库提供了强大的视频处理功能,而concurrent.futures库则简化了多线程的实现。
对于需要处理大量视频数据的应用场景,这种方法无疑是高效且实用的。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • vue3 主页面 跳转到子页面后 ,再次切换到主页面后 主页面及其它的所有页面 竟然不显示了的解决。
  • 企业做数据治理的意义是什么
  • 计算机网络必会面经
  • springboot业务层service开发全过程(以mybatis-plus为例)
  • EF访问PostgreSql,如何判断jsonb类型的数组是否包含某个数值
  • k8s学习--k8s集群部署kubesphere的详细过程
  • 2024.8.1(前端服务器的配置以及tomcat环境的配置)
  • 对象转化成base64-再转回对象
  • 人数管控系统助力图书馆实现精准客流统计分析
  • uniapp微信小程序按钮分享定制动态传参
  • git回退未commit、回退已commit、回退已push、合并某一次commit到另一个分支
  • 下载安装docker并解决拉去镜像的connect:connection refused问题(2024.7.31亲测有效)
  • 【Linux】文件描述符 fd
  • uniapp手写滚动选择器
  • 开机WiFi没了只能宽带,连声音都有问题,服务里系统还原等一堆错误无法调试!——DHCP服务器常见的故障影响这么大?
  • [LeetCode] Wiggle Sort
  • [译] React v16.8: 含有Hooks的版本
  • js写一个简单的选项卡
  • Kibana配置logstash,报表一体化
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • Next.js之基础概念(二)
  • Object.assign方法不能实现深复制
  • Protobuf3语言指南
  • 码农张的Bug人生 - 见面之礼
  • 全栈开发——Linux
  • 如何优雅地使用 Sublime Text
  • 使用common-codec进行md5加密
  • 使用docker-compose进行多节点部署
  • 由插件封装引出的一丢丢思考
  • zabbix3.2监控linux磁盘IO
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • ​渐进式Web应用PWA的未来
  • # 数仓建模:如何构建主题宽表模型?
  • $GOPATH/go.mod exists but should not goland
  • (1/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)
  • (1综述)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (floyd+补集) poj 3275
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (二)hibernate配置管理
  • (学习日记)2024.04.10:UCOSIII第三十八节:事件实验
  • (一)kafka实战——kafka源码编译启动
  • (转)linux下的时间函数使用
  • .NET 8.0 发布到 IIS
  • .net core 连接数据库,通过数据库生成Modell
  • .Net CoreRabbitMQ消息存储可靠机制
  • .NET Standard 的管理策略
  • .Net 知识杂记
  • .Net--CLS,CTS,CLI,BCL,FCL
  • .NET设计模式(8):适配器模式(Adapter Pattern)
  • @data注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • [.net]官方水晶报表的使用以演示下载
  • [24年新算法]NRBO-XGBoost回归+交叉验证基于牛顿拉夫逊优化算法-XGBoost多变量回归预测
  • [Angular] 笔记 9:list/detail 页面以及@Output
  • [BUG] Hadoop-3.3.4集群yarn管理页面子队列不显示任务