【问题标题】:CV2 cap.set(1,idx); cap.read(), Does it Read Frame idx or Frame idx+1CV2 cap.set(1,idx); cap.read(),它是读取帧 idx 还是帧 idx+1
【发布时间】:2022-07-01 14:19:41
【问题描述】:

在 CV2 中,这段代码会读取给定帧号的帧还是下一帧?

desiredFrames = [3,5,7,n]
cap = cv2.VideoCapture("somefile")

for idx in desiredFrames:
    cap.set(cv2.CAP_PROP_POS_FRAMES,idx);
    cap.read() #Does it Read Frame idx or Frame idx+1

我会得到帧 [3,5,7,n] 或帧 [4,6,8,n+1]

谢谢。

【问题讨论】:

  • documentation 表示“接下来要解码/捕获的帧的基于 0 的索引”。视频文件中第一帧的索引为0。所以索引3 是第 4 帧。
  • 谢谢,但我知道它是 0 索引。我的问题是 cap.set(1,idx);转到第 i 帧,然后当我调用 cap.read() 时它读取 i+1?换句话说,如果我告诉它分页到第 5 帧然后进行读取,它是从第 5 帧开始翻页并返回第 6 帧还是 cap.read 读取然后再分页?
  • 我已经发布了一个代码示例,证明框架是[3,5,7,n]... 请在您的机器中执行代码示例(我想确保示例代码正常工作,尤其是部分与 FFmpeg 相关)。如果您使用的是 Windows,请从here 下载 FFmpeg。并将ffmpeg.exe 放在与 Python 脚本相同的文件夹中。
  • 请使用CAP_PROP_POS_FRAMES 而不是幻数1。并删除所有你所遵循的教你使用1的可怕指南的书签。
  • 好的,我修复了 cap.set(1,...) 问题。如果可能的话,您选择其中一个的理由是什么?是的,我同意有很多可怕的指南对我们这些菜鸟的​​ Python 资源中的视频管理有什么建议吗?

标签: python python-3.x opencv computer-vision


【解决方案1】:

您将获得帧[3, 5, 7, n](视频文件中第一帧的索引为0)。

我们可以通过一个简单的测试来证明它。
首先使用FFmpeg CLI 构建合成模式视频文件。
(模式的)每一帧都包含一个从零开始计数的帧计数器。

为了在python中使用FFmpeg,FFmpeg可执行文件应该在执行路径中(我们也可以使用完整路径)。

构建示例文件:

sp.run(shlex.split('ffmpeg -y -f lavfi -i testsrc=size=128x72:rate=1:duration=10 somefile.mp4'))

将 MP4 视频帧转换为 PNG 图像序列:

sp.run(shlex.split('ffmpeg -i somefile.mp4 somefile_frame%03d.png'))

这里是前5帧作为图像(我们可以看到每一帧都有一个从0开始的帧计数器):


测试desiredFrames = [3, 5, 7]

这是一个“自包含”代码示例,用于构建输入视频文件,查找第 3、5、7 帧,显示这些帧并保存为 PNG 图像:

import cv2
import subprocess as sp
import shlex

# Build sample video file for testing (suing FFmpeg CLI).
# The test pattern includes a frame counter that start from 0.
sp.run(shlex.split('ffmpeg -y -f lavfi -i testsrc=size=128x72:rate=1:duration=10 somefile.mp4'))
sp.run(shlex.split('ffmpeg -i somefile.mp4 somefile_frame%03d.png'))

desiredFrames = [3, 5, 7]

cap = cv2.VideoCapture("somefile.mp4")

for idx in desiredFrames:
    cap.set(cv2.CAP_PROP_POS_FRAMES, idx);
    _, frame = cap.read()  # Does it Read Frame idx or Frame idx+1?

    cv2.imshow('frame', frame)  # Show the frame for testing
    cv2.waitKey(1000)

    cv2.imwrite(f'frame{idx}.png', frame)  # Save the frame t PNG file for testing

cap.release()
cv2.destroyAllWindows()

输出视频帧数:

如您所见,捕获的帧为357

【讨论】:

  • 谢谢。这就是我一直在寻找的。 shlex 和 sp 的巧妙技巧。
猜你喜欢
  • 2021-05-24
  • 2022-01-23
  • 2019-08-03
  • 2015-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-18
  • 1970-01-01
相关资源
最近更新 更多