【问题标题】:How to change frame per second (FPS) while using `cv2` when converting video to frames?将视频转换为帧时如何在使用`cv2`时更改每秒帧数(FPS)?
【发布时间】:2021-09-27 15:33:34
【问题描述】:

目前我使用2017_08_31_0121.mp4 作为我的视频,这是一个 21 秒长的视频,一旦我将它分成帧,我会得到 504 帧。这意味着每秒帧数设置为24。我想更改帧数但我不知道下面代码的哪一部分负责设置每秒帧数。

问题:

  1. 我一直以为默认FPS是25,现在我是24,请问可以告诉我默认FPS是在哪里设置的吗?

  2. 如果我想使用自定义 FPS 比如说 10,我该如何修改以下代码来做到这一点?

import cv2
vidcap = cv2.VideoCapture('/content/2017_08_31_0121.mp4')
success, image = vidcap.read()
count = 0
while success:
  if count<10:
    id = f'00{count}'
  elif count < 100:
    id = f'0{count}'
  else:
    id = count
  cv2.imwrite(f"./new_frames/frame{id}.jpg", image)    # save frame as JPEG file      
  success, image = vidcap.read()
  count += 1

【问题讨论】:

  • 无意义的要求。 OpenCV 将尽快读取视频。您将获得文件中的那些帧。你想完成什么?
  • 顺便说一句,您可以使用f"./new_frames/frame{id:03d}.jpg"更简单地实现零填充
  • @Christoph Rackwitz:“OpenCV 将尽快阅读视频”。谢谢你。我没有意识到这一点。哪个读它cv2.VideoCapturevidcap.read()。我问这个是因为我不想完全阅读它,我想从原始文件的每一秒中提取(3 或 5)帧。这是我的最终目标。
  • @Christoph Rackwitz:具体来说,我想在不读取所有帧的情况下每秒提取 3 或 5 帧。
  • 从每秒帧数退后一步,跳来跳去片刻,试着简单地说出你想要做什么,这样我们就能更好地帮助你。您是否出于某种原因试图缩短视频?还是加快速度?什么?为什么?谢谢。

标签: python opencv


【解决方案1】:

您需要了解“视频”的工作原理。

视频由关键帧和 P/B 帧组成。关键帧本身就是完整的图像。要解码 P/B 帧,需要先解码前面的帧。某些视频文件仅包含关键帧(“帧内”)。一些视频文件每 0.1-10 秒包含一个关键帧,中间只有 P/B 帧。

您可以在视频中跳来跳去,但只能直接跳到关键帧。如果你想跳到一个非关键帧,你必须先跳到前一个关键帧,然后解码后面的每一帧,直到你到达目的地。

我建议您不要遵循以下想法:

  • ffmpeg -i INPUT -r 3 OUTPUT 将读取整个视频,并根据需要复制/丢弃帧以达到每秒 3 帧,同时保持您在视频中看到的“速度”。它必须重新编码结果。如果您需要以该帧速率重复阅读同一视频,这只是一个明智的选择。

  • 在 ffmpeg 中涉及 GNU Parallel 将毫无意义,因为 ffmpeg 本身使用所有可用的 CPU 并行运行其解码和编码(对于大多数编解码器)。

这是您可以执行的操作:

使用 VideoCapture 的 grabretrieve 方法。反复拨打grab。这完成了解码帧和在视频中前进的最少工作。致电retrieve 获取您真正想要的框架。这完成了剩下的工作,它会将那个框架作为一个数组提供给你。

您必须使用vidcap.get(cv.CAP_PROP_FPS) 检查视频的fps 值,然后数数并决定是只需要抓取,还是同时抓取和取回。

import numpy as np
import cv2 as cv

vidcap = cv2.VideoCapture('/content/2017_08_31_0121.mp4')
assert vidcap.isOpened()

fps_in = vidcap.get(cv.CAP_PROP_FPS)
fps_out = 3

index_in = -1
index_out = -1

while True:
    success = vidcap.grab()
    if not success: break
    index_in += 1

    out_due = int(index_in / fps_in * fps_out)
    if out_due > index_out:
        success, frame = vidcap.retrieve()
        if not success: break
        index_out += 1

        # do something with `frame`

【讨论】:

  • 你是对的 - 我正在删除我的建议。
  • 对于“默认” fps,它不存在。视频有各种帧速率。欧洲喜欢25 fps。美国喜欢 23.976 fps。存在分数和倍数。有些视频甚至没有固定的帧速率,这意味着帧之间的时间可能会有所不同。
  • @Christoph Rackwitz:非常感谢您的启发性回答。由于我对视频不熟悉,您能告诉我什么是 P/B 帧吗? P/B 代表什么?另外,能否请您告诉我如何提取给定视频的关键帧?
  • opencv 无法判断帧是什么类型,也无法判断关键帧在哪里。它是用于计算机视觉的库,而不是用于处理视频文件的库。改为查看“PyAV”(也是ffmpeg)。 -- 框架、它们的名称和含义:en.wikipedia.org/wiki/Video_compression_picture_types
猜你喜欢
  • 2020-12-01
  • 2020-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-07
  • 2020-01-05
  • 2018-08-12
相关资源
最近更新 更多