【干货】视频文件抽帧(opencv和ffmpeg方式对比)

1 废话不多说,直接上代码

opencv方式

import time
import subprocess
import cv2, os
from math import ceildef extract_frames_opencv(video_path, output_folder, frame_rate=1):"""使用 OpenCV 从视频中抽取每秒指定帧数的帧,并保存到指定文件夹。如果视频长度不是整数秒,则会在最后一帧时补充空白图像。参数:video_path (str): 输入视频文件的路径。output_folder (str): 输出帧图像文件的文件夹路径。frame_rate (int): 每秒抽取的帧数,默认为 1。返回:None"""start_time = time.time()# 创建输出文件夹os.makedirs(output_folder, exist_ok=True)# 打开视频文件cap = cv2.VideoCapture(video_path)# 获取视频长度和帧率fps = cap.get(cv2.CAP_PROP_FPS)total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))duration = total_frames / fps# 计算需要抽取的总帧数target_frames = int(duration * frame_rate)# 逐帧抽取图像frame_idx = 0for i in range(target_frames):cap.set(cv2.CAP_PROP_POS_FRAMES, int(i * fps / frame_rate))ret, frame = cap.read()if ret:cv2.imwrite(os.path.join(output_folder, f"frame_{frame_idx:06d}.jpg"), frame)frame_idx += 1else:break# 如果最后一帧不是完整的一帧,则补充空白图像if frame_idx < target_frames:for i in range(frame_idx, target_frames):blank_image = 255 * np.ones((int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)), int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), 3), dtype=np.uint8)cv2.imwrite(os.path.join(output_folder, f"frame_{i:06d}.jpg"), blank_image)# 释放视频捕获对象cap.release()print(f"成功从视频中抽取了 {target_frames} 帧, 一共耗时{time.time() - start_time}s")

ffmpeg方式

def extract_frames_ffmpeg(video_path, output_folder, frame_rate=1):"""使用 FFmpeg 从视频中抽取每秒指定帧数的帧,并保存到指定文件夹。如果视频长度不是整数秒,则会抛出异常。参数:video_path (str): 输入视频文件的路径。output_folder (str): 输出帧图像文件的文件夹路径。frame_rate (int): 每秒抽取的帧数,默认为 1。返回:None"""start_time = time.time()# 创建输出文件夹os.makedirs(output_folder, exist_ok=True)# 获取视频长度command = ["ffprobe", "-v", "error", "-show_entries", "format=duration", "-of","default=nokey=1:noprint_wrappers=1", video_path]result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)if result.returncode != 0:raise ValueError("Failed to get video duration.")duration = float(result.stdout.decode().strip())# 四舍五入视频长度到最接近的整数秒duration = round(duration)# 构建 FFmpeg 命令command = ["ffmpeg","-i", video_path,"-vf", f"fps={frame_rate}","-frames:v", "%d" % (ceil(duration * frame_rate)),os.path.join(output_folder, "frame_%06d.jpg")]# 执行 FFmpeg 命令subprocess.run(command, check=True)print(f"成功从视频中抽取了 {ceil(duration * frame_rate)} 帧, 一共耗时{time.time() - start_time}s")

2 测试实验对比

测试一个56s的mp4文件

extract_frames_opencv(video_path, output_folder, 1)
# 成功从视频中抽取了 55 帧, 一共耗时10.131151914596558s
extract_frames_ffmpeg(video_path, output_folder, 1)
# 成功从视频中抽取了 56 帧, 一共耗时8.075150966644287s

 1帧/s时,ffmpeg稍快2s

extract_frames_opencv(video_path, output_folder1, 5)
# 成功从视频中抽取了 278 帧, 一共耗时54.822526931762695s
extract_frames_ffmpeg(video_path, output_folder2, 5)
# 成功从视频中抽取了 280 帧, 一共耗时8.546468019485474s

5帧/s时,ffmpeg方式只增加0.5s,opencv增加了5倍时长

在大文件抽帧、或者抽帧频率较高时,ffmpeg效率更高。

3 ffmpeg抽帧图片更小?

对比了下抽帧图片,分辨率一致,但是ffmpeg抽帧图片好像小很多,为什么呢?

搜了下官方解释:

FFmpeg 和 OpenCV 在抽取视频帧并保存图像时,可能会产生不同的结果,包括文件大小和图像质量等。出现这种差异的原因主要有以下几点:

  1. 编码器选择:

    • FFmpeg 默认使用 JPEG 编码器,这种编码方式通常可以生成较小的文件大小,但可能会略有些图像质量损失。
    • OpenCV 默认使用无损的 PNG 编码器,生成的文件通常会更大,但图像质量更好。
  2. 色彩空间转换:

    • FFmpeg 在抽取帧时,可能会将视频的色彩空间转换为更适合 JPEG 编码的格式,例如 YUV 420。这种转换可以进一步减小文件大小。
    • OpenCV 则可能会保留视频原有的色彩空间,如 RGB,在保存为 PNG 时不进行额外的转换。
  3. 图像缩放和重采样:

    • FFmpeg 在抽取帧时,可能会根据输出分辨率对图像进行缩放和重采样,从而进一步优化文件大小。
    • OpenCV 则可能会直接保存原始分辨率的图像,不进行任何缩放处理。

综上所述,FFmpeg 在抽取视频帧并保存为图像时,通常会采取一些优化措施,如使用 JPEG 编码、色彩空间转换和图像缩放等,从而生成相对较小的文件大小。而 OpenCV 则更倾向于保留原始的视觉质量,因此生成的图像文件会相对更大。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/23635.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux系统使用达梦数据库

在Linux系统中使用达梦数据库&#xff0c;首先需要确保已经正确安装了达梦数据库软件。以下是一个基本的使用示例&#xff0c;假设您已经安装了达梦数据库并且配置好了相关环境变量。 连接到数据库&#xff1a; 使用 dsql 命令连接到数据库 dsql -h hostname -u username -p…

宝贝,带上WebAssembly,换个姿势来优化你的前端应用

在你没崛起之前,脸是用来丢的 大家好,我是柒八九。一个专注于前端开发技术/Rust及AI应用知识分享的Coder 此篇文章所涉及到的技术有 WebAssemblyRustWeb Worker(comlink)wasm-packPhotonffmpeg.wasm脚手架生成前端项目因为,行文字数所限,有些概念可能会一带而过亦或者提供对…

BOM是什么东西

BOM&#xff08;Byte Order Mark&#xff0c;字节顺序标记&#xff09;是一个Unicode字符&#xff0c;通常出现在文本文件的开头。它的作用包括以下几个方面&#xff1a; 1. 指示文件的编码方式 BOM可以帮助软件识别文本文件使用的字符编码。不同的编码方式可能会使用不同的B…

经济与安全兼顾:茶饮店购买可燃气体报警器的价格考量

可燃气体报警器在如今的社会中扮演着至关重要的角色。它们用于检测环境中的可燃气体浓度&#xff0c;及早发现潜在的火灾隐患&#xff0c;保护人们的生命和财产安全。 在这篇文章中&#xff0c;佰德将介绍可燃气体报警器的安装、检定以及价格&#xff0c;通过实际案例和数据&a…

PCL 生成空间椭圆点云

目录 一、算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法原理 设椭圆在 X O Y XOY XOY平面上,参数方程为:

怎么保障TikTok直播网络稳定?

TikTok&#xff0c;这个近年来风靡全球的社交媒体平台&#xff0c;已成为电商引流的新方向&#xff0c;尤其是其直播功能。然而&#xff0c;对于打算进军TikTok直播领域的商家和主播而言&#xff0c;确保网络稳定无疑是首要任务。那么&#xff0c;TikTok直播专线究竟是什么呢&a…

牛啊后续:如何一行C#代码实现解析类型的Summary注释(可用于数据字典快速生成)...

前言&#xff1a;下午有小伙伴要求&#xff0c;让我继续做个解析实体类注释信息的内容。所以我也顺便加入进来。以下开始正文实战操作&#xff1a; 项目需要勾选输出api文档文件。这样就可以让所有实体类的summary信息被写入到输出目录下。如果有多个xml文件也没关系&#xff0…

小程序 UI 风格美不胜收

小程序 UI 风格美不胜收 小程序 UI 风格美不胜收

PostgreSQL的视图pg_stat_replication

PostgreSQL的视图pg_stat_replication pg_stat_replication 是 PostgreSQL 提供的一个系统视图&#xff0c;用于显示主服务器上当前正在进行的复制会话的信息。它可以帮助数据库管理员监控和管理主从复制的状态&#xff0c;确保数据的正确同步和高可靠性。 pg_stat_replicati…

MyEclipse中properties文件中文乱码(Unicode字符)解决办法

程序代码园发文地址&#xff1a;MyEclipse中properties文件中文乱码&#xff08;Unicode字符&#xff09;解决办法-程序代码园小说,Java,HTML,Java小工具,程序代码园,http://www.byqws.com/ ,MyEclipse中properties文件中文乱码&#xff08;Unicode字符&#xff09;解决办法htt…

Django学习三:views业务层中通过models对实体对象进行的增、删、改、查操作。

文章目录 前言一、Django ORM介绍二、项目快速搭建三、操作1、view.pya、增加操作b、删除操作c、修改操作d、查询操作 2、urls.py 前言 上接博文&#xff1a;Django学习二&#xff1a;配置mysql&#xff0c;创建model实例&#xff0c;自动创建数据库表&#xff0c;对mysql数据…

一周发文9篇!MIMIC-IV数据库周报(5.22~5.28)

重症医学数据库&#xff08;MIMIC&#xff09;是由计算生理学实验室开发的公开数据集&#xff0c;其中包括与数千个重症监护病房入院相关的去识别化健康数据&#xff0c;致力于推动临床信息学、流行病学和机器学习的研究。 MIMIC数据库于2003年在美国国立卫生研究院的资助下&am…

2024上海初中生古诗文大会倒计时4个半月:单选题真题示例和独家解析

现在距离2024年初中生古诗文大会还有4个半月时间&#xff0c;我们来看10道选择题真题和详细解析&#xff0c;了解古诗文大会的考察方式和知识点&#xff0c;从而更好地备考。 以下题目截取自我独家制作的在线真题集&#xff0c;都是来自于历届真题&#xff0c;去重、合并后&am…

数据仓库缓慢变化维介绍

缓慢变化维&#xff08;Slowly Changing Dimensions, SCD&#xff09;是数据仓库设计中的一个重要概念&#xff0c;用于处理维度表中随时间缓慢变化的属性。维度表中的数据通常描述业务实体&#xff08;如客户、产品、员工等&#xff09;&#xff0c;而这些实体的某些属性&…

面试成功的不二法门:详解Vue3答题章法

前言 面试题在网络上有如海洋之深&#xff0c;对于同一知识点&#xff0c;每个人的理解也各有千秋。我们在面试中常常会遇到一个瞬息间脑海里一片空白的情况&#xff0c;其实这并不是因为我们不懂&#xff0c;而是因为我们在回答的时候缺乏一个清晰的思路。那么问题来了&#x…

《魔法与科技的融合:SpringBoot运维的现代传说》

揭开了SpringBoot应用部署的神秘面纱。从云平台的选型到Docker的容器化魔法&#xff0c;再到Kubernetes的集群力量&#xff0c;每一步都充满了奇幻色彩。文章以轻松幽默的笔触&#xff0c;带领读者穿梭于现代应用部署的各个角落&#xff0c;探索自动化部署的奥秘&#xff0c;学…

关于图像过曝问题的排查思路

1、问题背景 读者提问&#xff0c;图像在室外遇到过曝的问题&#xff0c;有什么排查思路和改善方法。 2、问题分析 1&#xff09;先检查一下sensor驱动&#xff0c;对照 sensor datasheet 确认下最小曝光行设置的是否正确&#xff0c; 因为室外高亮场景一般曝光行走的都比较…

【深度学习】PuLID: Pure and Lightning ID Customization via Contrastive Alignment

论文&#xff1a;https://arxiv.org/abs/2404.16022 代码&#xff1a;https://github.com/ToTheBeginning/PuLID 文章目录 AbstractIntroductionRelated WorkMethods Abstract 我们提出了一种新颖的、无需调整的文本生成图像ID定制方法——Pure and Lightning ID customizatio…

微信好友朋友圈的三天、半年可见怎么破?方法拿走不谢

『Code掘金』问大家&#xff0c;有没有这种经历&#xff0c;当你想去翻某人的朋友圈时&#xff0c;对方设置成了3天可见&#xff0c;之前的内容没法看到了。 不过没关系&#xff01;今天『Code掘金』给大家分享一款导出朋友圈的工具&#xff0c;让大家留住痕迹。 WechatMomen…

PostgreSQL中有没有类似Oracle的dba_objects系统视图

PostgreSQL中有没有类似Oracle的dba_objects系统视图 在PostgreSQL中&#xff0c;没有一个完全集成了所有对象信息的视图&#xff08;类似于Oracle中的DBA_OBJECTS&#xff09;。但是&#xff0c;PostgreSQL提供了一些系统目录表和视图&#xff0c;可以用来获取数据库对象的信…