news 2026/4/20 5:08:07

视频提取图片帧,图片合成视频

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
视频提取图片帧,图片合成视频

写了两个脚本。一个用于将视频按帧率一次转为图片,另一个将图片合成的为视频的脚本。

一、环境配置:安装opencv2

用到了os库、cv2、glob

pip install opencv-contrib-python

二、代码

1.首先是第一个视频转为图片的代码:

可以按需修改最后几行的代码。输入视频路径和输出图片的路径一定要改;输出照片的格式默认是jpg,按需改成png啥的都可以;保存帧数默认是0,就是将所有的帧数都提取出来,但是这样就会有很多相似的照片,反正按需求来吧,设置30帧提取一帧都可以。

video_path='D:\\data\\1080p.mp4', #输入转换的视频
output_dir='D:\\data\\1080p', #输出图片的文件夹
frame_format='png', #输出照片的格式
skip_frames=9 # 0=保存所有帧,1=每2帧保存1帧,依此类推

import cv2 import os def video_to_frames(video_path, output_dir, frame_format='jpg', skip_frames=0): """ 将视频逐帧提取为图片 参数: video_path: 输入视频的路径(如 "test.mp4") output_dir: 输出图片的文件夹路径 frame_format: 保存图片的格式,可选 'jpg' 或 'png' skip_frames: 跳帧间隔(0表示不跳帧,1表示每2帧取1帧,以此类推) """ # 创建输出文件夹(如果不存在) if not os.path.exists(output_dir): os.makedirs(output_dir) # 打开视频文件 cap = cv2.VideoCapture(video_path) if not cap.isOpened(): raise ValueError(f"无法打开视频文件: {video_path}") frame_count = 0 # 总帧数计数器 saved_count = 0 # 保存的帧数计数器 # 逐帧读取视频 while True: # 读取一帧 ret, frame = cap.read() # ret 为 False 表示读取完毕(到视频末尾) if not ret: break # 跳帧处理(按需保存) if frame_count % (skip_frames + 1) == 0: # 定义图片文件名(格式:frame_0001.jpg) frame_filename = f"frame_{saved_count:04d}.{frame_format}" frame_path = os.path.join(output_dir, frame_filename) # 保存帧为图片 cv2.imwrite(frame_path, frame) saved_count += 1 frame_count += 1 # 释放视频资源 cap.release() print(f"视频帧提取完成!") print(f"总帧数: {frame_count}, 保存的帧数: {saved_count}") print(f"图片保存路径: {os.path.abspath(output_dir)}") # ------------------- 示例调用 ------------------- if __name__ == "__main__": # 替换为你的视频路径和输出文件夹路径 video_to_frames( video_path='D:\\data\\1080p.mp4', #输入转换的视频 output_dir='D:\\data\\1080p', #输出图片的文件夹 frame_format='jpg', #输出照片的格式 skip_frames=0 # 0=保存所有帧,1=每2帧保存1帧,依此类推 )

2.图片依次转换为视频的代码

逻辑基本上差不多,调整的参数:

frames_dir=FRAMES_DIR #替换为你的图片文件夹路径
output_video_path=OUTPUT_VIDEO, #替换为你预计保存视频的路径
fps=25, # 帧率,根据原视频调整(比如原视频是25FPS就设为25)
frame_format='jpg' # 图片格式,和之前保存的一致

import cv2 import os import glob def frames_to_video(frames_dir, output_video_path, fps=30, frame_format='jpg'): """ 将按顺序命名的图片帧合并为视频 参数: frames_dir: 存放图片帧的文件夹路径 output_video_path: 输出视频的路径(如 "output_video.mp4") fps: 输出视频的帧率(默认30帧/秒,可根据原视频调整) frame_format: 图片帧的格式(如 'jpg'、'png') """ # 检查输入文件夹是否存在 if not os.path.exists(frames_dir): raise ValueError(f"图片文件夹不存在: {frames_dir}") # 获取所有图片帧的路径,并按文件名排序(保证帧顺序) frame_paths = glob.glob(os.path.join(frames_dir, f"*.{frame_format}")) if not frame_paths: raise ValueError(f"在 {frames_dir} 中未找到 {frame_format} 格式的图片") # 按文件名排序(关键!确保帧顺序正确) frame_paths.sort(key=lambda x: int(os.path.splitext(os.path.basename(x))[0].split('_')[1])) # 读取第一张图片,获取视频分辨率 first_frame = cv2.imread(frame_paths[0]) if first_frame is None: raise ValueError(f"无法读取第一张图片: {frame_paths[0]}") height, width = first_frame.shape[:2] # 设置视频编码格式和写入对象 # MP4格式推荐使用 'mp4v' 编码,兼容性更好 fourcc = cv2.VideoWriter_fourcc(*'mp4v') video_writer = cv2.VideoWriter( output_video_path, fourcc, fps, (width, height) # 视频分辨率(宽, 高) ) if not video_writer.isOpened(): raise ValueError(f"无法创建视频写入对象,请检查输出路径和编码格式") # 逐帧写入视频 total_frames = len(frame_paths) for i, frame_path in enumerate(frame_paths): # 读取图片帧 frame = cv2.imread(frame_path) if frame is None: print(f"警告:跳过损坏的图片 {frame_path}") continue # 确保图片尺寸和视频分辨率一致(防止尺寸不匹配报错) if frame.shape[:2] != (height, width): frame = cv2.resize(frame, (width, height)) # 写入视频 video_writer.write(frame) # 打印进度(可选) if (i + 1) % 100 == 0 or (i + 1) == total_frames: print(f"已处理 {i + 1}/{total_frames} 帧") # 释放资源 video_writer.release() print(f"\n视频生成完成!") print(f"输出视频路径: {os.path.abspath(output_video_path)}") print(f"视频参数:分辨率 {width}x{height},帧率 {fps} FPS") if __name__ == "__main__": # 替换为你的图片文件夹路径和输出视频路径 FRAMES_DIR = "D:/data/img" # 存放图片帧的文件夹(和之前转帧的输出路径一致) OUTPUT_VIDEO = "D:/data/img.mp4" # 输出视频文件名 # 调用函数(帧率建议和原视频一致,通常为24/30 FPS) frames_to_video( frames_dir=FRAMES_DIR, output_video_path=OUTPUT_VIDEO, fps=25, # 帧率,根据原视频调整(比如原视频是25FPS就设为25) frame_format='jpg' # 图片格式,和之前保存的一致 )
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/20 5:05:27

企业云盘怎么选?10 个主流工具优劣分析

很多企业在选企业网盘时,表面上看的是容量和价格,真正落地时卡住的往往是另外几件事:大文件传输稳不稳,权限能不能细到部门和角色,外部协作是否可控,版本记录能不能追溯,系统能不能接进现有的项…

作者头像 李华
网站建设 2026/4/20 5:00:23

5G网络‘双卡双待’:手把手拆解Option 3X/4双连接配置与故障排查指南

5G双连接实战:Option 3X与Option 4架构深度解析与排障手册 当运营商开始部署5G网络时,如何实现4G/5G协同组网成为关键挑战。双连接技术允许终端同时接入4G和5G网络,大幅提升用户体验和网络效率。但在实际部署中,不同架构选择带来的…

作者头像 李华
网站建设 2026/4/20 4:57:48

codex app每次打开重连5次Reconnecting问题解决

原因: 默认是使用websocket协议,在websocket重连等待五次(并且每次的超时时间足足有20s)之后才会切换到可以正常通信的HTTP协议,至于websocket协议为什么不通,可能是代理不支持websocket协议. 方案1: 在.c…

作者头像 李华
网站建设 2026/4/20 4:57:15

Phi-3-mini-128k-instruct实战教程:基于vLLM API封装REST接口供Web端调用

Phi-3-mini-128k-instruct实战教程:基于vLLM API封装REST接口供Web端调用 1. 模型简介 Phi-3-Mini-128K-Instruct是一个38亿参数的轻量级开放模型,属于Phi-3系列的最新成员。这个模型经过精心训练,特别擅长理解和执行各种指令任务。 模型的…

作者头像 李华
网站建设 2026/4/20 4:52:40

UnSHc深度解析:Shell脚本安全审计与逆向工程的技术实现

UnSHc深度解析:Shell脚本安全审计与逆向工程的技术实现 【免费下载链接】UnSHc UnSHc - How to decrypt SHc *.sh.x encrypted file ? 项目地址: https://gitcode.com/gh_mirrors/un/UnSHc 在Shell脚本安全领域,SHc加密工具因其强大的保护能力而…

作者头像 李华
网站建设 2026/4/20 4:49:14

2026美国EB - 1A杰出人才移民行业盘点,真实口碑参考

在2026年,美国EB - 1A杰出人才移民受到众多精英人士的关注。然而,这个行业存在不少痛点,像模板化操作泛滥、过度包装与虚假宣传、前期评估不严谨、服务流程不透明以及团队配置不完整等问题,让申请人在选择移民机构时十分困惑。接下…

作者头像 李华