使用Python + OpenCV提取和保存视频帧

Written by

in

文章目录
  • 在计算机视觉、机器学习和图像处理应用中,从视频中处理图像帧是一个常见的任务。Python提供了一些强大的库和工具,使我们能够轻松地从视频中提取帧并对其进行处理。 百度百科: OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
  • 使用 OpenCV 库从视频中提取特定帧并保存为图像文件,首先需要确保安装了必要的库。 注意🔔:OpenCV库为 opencv-python ,导入OpenCV语法为 import cv2 pip install opencv-python numpy matplotlib
  • 注意🔔:运行代码需通过命令行的方式 import cv2 import os import argparse from datetime import timedelta from pathlib import Path def extract_frames(video_path, output_dir, frame_interval=None, time_interval=None, prefix=”frame”): “”” 从视频中提取帧并保存到指定目录 参数: video_path: 视频文件路径 output_dir: 输出目录 frame_interval: 帧间隔(每多少帧提取一帧) time_interval: 时间间隔(秒) prefix: 输出文件名前缀 “”” # 检查视频文件 if not os.path.isfile(video_path): print(f”错误: 视频文件 ‘{video_path}’ 不存在”) return # 创建输出目录 确保输出目录存在 os.makedirs(output_dir, exist_ok=True) # 打开视频文件 cap = cv2.VideoCapture(video_path) if not cap.isOpened(): print(f”错误: 无法打开视频文件 {video_path}”) return # 获取视频文件名(不含扩展名)作为默认前缀 if prefix is None: video_name = Path(video_path).stem # 例如: “input” from “input.mp4″ prefix = video_name # 获取视频属性 fps = cap.get(cv2.CAP_PROP_FPS) frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) duration = frame_count / fps print(f”视频信息:”) print(f” 视频路径: {video_path}”) print(f” 帧率: {fps:.2f} fps”) print(f” 总帧数: {frame_count}”) print(f” 分辨率: {width}x{height}”) print(f” 时长: {timedelta(seconds=duration)}”) # 确定提取间隔 if frame_interval is not None: interval = frame_interval use_frame_interval = True print(f”将每 {interval} 帧提取一帧”) elif time_interval is not None: interval = max(1, int(time_interval * fps)) # 确保至少1帧 use_frame_interval = True print(f”将每 {time_interval} 秒({interval}帧)提取一帧”) else: interval = 1 use_frame_interval = True print(“将提取所有帧”) # 开始提取帧 frame_number = 0 saved_count = 0 print(“n开始提取帧…”) while True: ret, frame = cap.read() if not ret: break # 检查是否应该保存当前帧 if use_frame_interval and frame_number % interval == 0: save_path = os.path.join(output_dir, f”{prefix}_{frame_number:06d}.jpg”) cv2.imwrite(save_path, frame) saved_count += 1 frame_number += 1 cap.release() print(f”完成提取: 共处理 {frame_number} 帧,保存 {saved_count} 张到 {output_dir}”) def main(): parser = argparse.ArgumentParser(description=’从视频中提取帧并保存’) parser.add_argument(‘–video_dir’, help=’视频所在目录(处理目录下所有视频)’) parser.add_argument(‘–video_path’, help=’单个视频文件路径(与video_dir互斥)’) parser.add_argument(‘–output_dir’, help=’输出目录’) group = parser.add_mutually_exclusive_group() group.add_argument(‘–frame_interval’, type=int, help=’帧间隔(每多少帧提取一帧)’) group.add_argument(‘–time_interval’, type=float, help=’时间间隔(秒)’) parser.add_argument(‘–prefix’, help=’输出文件名前缀(默认为视频文件名)’) parser.add_argument(‘–extensions’, default=’mp4,mkv,avi,mov’, help=’允许的视频扩展名,逗号分隔’) args = parser.parse_args() # 验证输入参数 if not args.video_dir and not args.video_path: parser.error(“请指定 –video_dir 或 –video_path”) # 获取视频文件列表 video_files = [] if args.video_dir: if not os.path.exists(args.video_dir): print(f”错误: 视频目录 {args.video_dir} 不存在”) return allowed_extensions = set(args.extensions.lower().split(‘,’)) for entry in os.scandir(args.video_dir): if entry.is_file() and entry.name.lower().split(‘.’)[-1] in allowed_extensions: video_files.append(entry.path) if not video_files: print(f”错误: 在目录 {args.video_dir} 中未找到支持的视频文件”) return else: if not os.path.exists(args.video_path): print(f”错误: 视频文件 {args.video_path} 不存在”) return video_files = [args.video_path] print(f”找到 {len(video_files)} 个视频文件需要处理”) # 处理每个视频 for video_path in video_files: video_name = Path(video_path).stem # 使用视频名作为默认前缀(除非用户指定了全局前缀) prefix = args.prefix if args.prefix else video_name extract_frames( video_path, args.output_dir, # 直接使用用户指定的输出目录,不再创建子目录 args.frame_interval, args.time_interval, prefix ) if __name__ == “__main__”: main()
  • 你可以通过以下命令行方式运行这个视频帧提取程序。 程序支持两种模式:①单视频处理和②批量处理目录中的所有视频。
  • 使用Python和OpenCV提取视频帧是一项强大而灵活的技术,适用于各种计算机视觉和多媒体处理任务。本文介绍的方法从基础到高级,覆盖了大多数实际应用场景。通过调整参数和结合其他Python库,您可以构建更复杂的视频处理流程。 到此这篇关于使用Python + OpenCV提取和保存视频帧的文章就介绍到这了,更多相关OpenCV提取和保存视频帧内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: python-opencv颜色提取分割方法 opencv 实现特定颜色线条提取与定位操作 Opencv处理图像之轮廓提取 openCV提取图像中的矩形区域 python如何使用opencv提取光流详解
  • 目录
    • 引言
    • 环境准备
    • 代码实现
    • 运行 命令行工具
      • 1 处理单个视频文件
      • 2 批量处理目录中的所有视频
      • 完整帮助信息
    • 结语

      在计算机视觉、机器学习和图像处理应用中,从视频中处理图像帧是一个常见的任务。Python提供了一些强大的库和工具,使我们能够轻松地从视频中提取帧并对其进行处理。

      百度百科: OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。

      使用 OpenCV 库从视频中提取特定帧并保存为图像文件,首先需要确保安装了必要的库。

      注意🔔:OpenCV库为 opencv-python ,导入OpenCV语法为 import cv2

      pip install opencv-python numpy matplotlib
      

      注意🔔:运行代码需通过命令行的方式

      import cv2
      import os
      import argparse
      from datetime import timedelta
      from pathlib import Path
      
      def extract_frames(video_path, output_dir, frame_interval=None, time_interval=None, prefix="frame"):
          """
          从视频中提取帧并保存到指定目录
      
          参数:
              video_path: 视频文件路径
              output_dir: 输出目录
              frame_interval: 帧间隔(每多少帧提取一帧)
              time_interval: 时间间隔(秒)
              prefix: 输出文件名前缀
          """
      
          # 检查视频文件
          if not os.path.isfile(video_path):
              print(f"错误: 视频文件 '{video_path}' 不存在")
              return
      
          # 创建输出目录 确保输出目录存在
          os.makedirs(output_dir, exist_ok=True)
      
          # 打开视频文件
          cap = cv2.VideoCapture(video_path)
          if not cap.isOpened():
              print(f"错误: 无法打开视频文件 {video_path}")
              return
      
          # 获取视频文件名(不含扩展名)作为默认前缀
          if prefix is None:
              video_name = Path(video_path).stem  # 例如: "input" from "input.mp4"
              prefix = video_name
      
          # 获取视频属性
          fps = cap.get(cv2.CAP_PROP_FPS)
          frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
          width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
          height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
          duration = frame_count / fps
      
          print(f"视频信息:")
          print(f"  视频路径: {video_path}")
          print(f"  帧率: {fps:.2f} fps")
          print(f"  总帧数: {frame_count}")
          print(f"  分辨率: {width}x{height}")
          print(f"  时长: {timedelta(seconds=duration)}")
      
          # 确定提取间隔
          if frame_interval is not None:
              interval = frame_interval
              use_frame_interval = True
              print(f"将每 {interval} 帧提取一帧")
          elif time_interval is not None:
              interval = max(1, int(time_interval * fps))  # 确保至少1帧
              use_frame_interval = True
              print(f"将每 {time_interval} 秒({interval}帧)提取一帧")
          else:
              interval = 1
              use_frame_interval = True
              print("将提取所有帧")
      
          # 开始提取帧
          frame_number = 0
          saved_count = 0
      
          print("n开始提取帧...")
      
          while True:
              ret, frame = cap.read()
              if not ret:
                  break
      
              # 检查是否应该保存当前帧
              if use_frame_interval and frame_number % interval == 0:
                  save_path = os.path.join(output_dir, f"{prefix}_{frame_number:06d}.jpg")
                  cv2.imwrite(save_path, frame)
                  saved_count += 1
      
              frame_number += 1
      
          cap.release()
          print(f"完成提取: 共处理 {frame_number} 帧,保存 {saved_count} 张到 {output_dir}")
      
      
      def main():
          parser = argparse.ArgumentParser(description='从视频中提取帧并保存')
          parser.add_argument('--video_dir', help='视频所在目录(处理目录下所有视频)')
          parser.add_argument('--video_path', help='单个视频文件路径(与video_dir互斥)')
          parser.add_argument('--output_dir', help='输出目录')
          group = parser.add_mutually_exclusive_group()
          group.add_argument('--frame_interval', type=int, help='帧间隔(每多少帧提取一帧)')
          group.add_argument('--time_interval', type=float, help='时间间隔(秒)')
          parser.add_argument('--prefix', help='输出文件名前缀(默认为视频文件名)')
          parser.add_argument('--extensions', default='mp4,mkv,avi,mov', help='允许的视频扩展名,逗号分隔')
      
          args = parser.parse_args()
      
          # 验证输入参数
          if not args.video_dir and not args.video_path:
              parser.error("请指定 --video_dir 或 --video_path")
      
          # 获取视频文件列表
          video_files = []
          if args.video_dir:
              if not os.path.exists(args.video_dir):
                  print(f"错误: 视频目录 {args.video_dir} 不存在")
                  return
      
              allowed_extensions = set(args.extensions.lower().split(','))
              for entry in os.scandir(args.video_dir):
                  if entry.is_file() and entry.name.lower().split('.')[-1] in allowed_extensions:
                      video_files.append(entry.path)
      
              if not video_files:
                  print(f"错误: 在目录 {args.video_dir} 中未找到支持的视频文件")
                  return
          else:
              if not os.path.exists(args.video_path):
                  print(f"错误: 视频文件 {args.video_path} 不存在")
                  return
              video_files = [args.video_path]
      
          print(f"找到 {len(video_files)} 个视频文件需要处理")
      
          # 处理每个视频
          for video_path in video_files:
              video_name = Path(video_path).stem
      
              # 使用视频名作为默认前缀(除非用户指定了全局前缀)
              prefix = args.prefix if args.prefix else video_name
      
              extract_frames(
                  video_path,
                  args.output_dir,  # 直接使用用户指定的输出目录,不再创建子目录
                  args.frame_interval,
                  args.time_interval,
                  prefix
              )
      
      if __name__ == "__main__":
          main()
      
      
      

      你可以通过以下命令行方式运行这个视频帧提取程序。

      程序支持两种模式:①单视频处理②批量处理目录中的所有视频

      bash 命令

      python [代码名] --video_path 视频路径 --output_dir 输出目录 [其他参数]
      

      示例:

      提取 input.mp4 的帧,每秒提取一帧,保存到 frames/ 目录:

      python frame.py --video_path input.mp4 --output_dir frames/ --time_interval 1.0
      

      bash 命令

      python frame.py --video_dir 视频目录 --output_dir 输出目录 [其他参数]
      

      示例:

      处理 videos/ 目录下的所有视频(默认支持 mp4、mkv、avi、mov 格式),每 30 帧提取一帧,保存到 frames/ 目录:

      python frame.py --video_dir videos/ --output_dir frames/ --frame_interval 30
      

      查看所有可用参数:

      python frame.py --help
      

      使用Python和OpenCV提取视频帧是一项强大而灵活的技术,适用于各种计算机视觉和多媒体处理任务。本文介绍的方法从基础到高级,覆盖了大多数实际应用场景。通过调整参数和结合其他Python库,您可以构建更复杂的视频处理流程。

      到此这篇关于使用Python + OpenCV提取和保存视频帧的文章就介绍到这了,更多相关OpenCV提取和保存视频帧内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

      您可能感兴趣的文章:

      • python-opencv颜色提取分割方法
      • opencv 实现特定颜色线条提取与定位操作
      • Opencv处理图像之轮廓提取
      • openCV提取图像中的矩形区域
      • python如何使用opencv提取光流详解

      站内搜索