【问题标题】:OpenCV VideoCapture returns strange frame offset for different versionsOpenCV VideoCapture 为不同版本返回奇怪的帧偏移
【发布时间】:2021-11-29 17:53:16
【问题描述】:

我正在使用opencv-python,当我执行以下代码时:

index = 0
cap = cv2.VideoCapture(video_path)
while True:
    offset = cap.get(cv2.CAP_PROP_POS_MSEC)
    print(cv2.__version__, index, offset)

    ok, frame = cap.read()
    if not ok:
        break
    index += 1

我得到以下输出:

3.4.7 0 0.0
3.4.7 1 33.36666666666667
3.4.7 2 66.73333333333333
3.4.7 3 100.10000000000001
3.4.7 4 133.46666666666667

如果我在版本 3.4.8.29 上执行此代码,我会得到以下输出:

3.4.8 0 0.0
3.4.8 1 0.0
3.4.8 2 33.36666666666667
3.4.8 3 66.73333333333333
3.4.8 4 100.10000000000001

如果我在版本 4.5.2.52 上执行它,我会得到:

4.5.2 0 0.0
4.5.2 1 0.0
4.5.2 2 0.0
4.5.2 3 0.0
4.5.2 4 0.0

问题首先是,哪一个是正确的?看起来 3.4.7 是正确的,但它似乎也在版本之间随机变化。

以及如何修改其他版本以获得正确的结果,与3.4.7相同

【问题讨论】:

  • 您可以使用 FFprobe(命令行工具)来提取 PTS 时间戳,如 here 所述。 ffprobe -i vid.mp4 -show_frames -show_entries frame=pkt_pts_time -of csv=p=0 > frames.txt
  • 你能测试一下新版本是否读取了一些空帧吗?那么所有版本对于可读的非空帧可能都是正确的。
  • @Rotem 这是您建议的结果:0.000000 0.033367 0.066733 0.100100
  • @micka “空框架”是什么意思?
  • 图片大小为0宽高。

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


【解决方案1】:

我阅读了 OpenCV 文档,他们说:“读/写属性涉及很多层。沿着这个链可能会发生一些意想不到的结果。有效的行为取决于设备硬件、驱动程序和 API 后端。” (来源:https://docs.opencv.org/3.4.15/d4/d15/group__videoio__flags__base.html#gaeb8dd9c89c10a5c63c139bf7c4f5704d

所以换句话说,OpenCV 不保证这个函数的一致和可靠的行为。

我还安装了 openCV 4.5.2.52 并将您的脚本应用到我的一个“.mp4”视频中。然后我得到了与 openCV 版本 3.4.8.29 相同的结果。所以我认为你遇到的行为不是“错误”,而是这个函数的不可靠行为。

作为解决方法,您可以通过将帧数除以 FPS 计数来计算“偏移量”(参见下面的代码)。这样您就可以更好地控制行为,甚至可能获得更一致的结果。

index = 0
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
while True:
    offset = cap.get(cv2.CAP_PROP_POS_MSEC)

    ok, frame = cap.read()
    if not ok:
        break
    
    # CAP_PROP_POS_MSEC
    print("CAP_PROP_POS_MSEC: ", index, offset)
    
    # Devide fps by frame number
    offset = cap.get(cv2.CAP_PROP_POS_FRAMES) / fps * 1000
    print("cv2.CAP_PROP_POS_FRAMES", index, offset)
     
    index += 1

【讨论】:

  • 请更改您的代码以提及偏移量应为offset = cap.get(cv2.CAP_PROP_POS_FRAMES) / fps * 1000。除非有更好的答案来解释这个问题,否则我会在接下来的几天内将其标记为正确。
  • tnx 的反馈!我更改了示例代码:)
  • @user972014 这是否满足您的回答?或者还有什么需要的吗?
  • 谨慎使用帧数和 fps 速率来计算帧时间,因为很少有视频文件具有可变帧速率(fps 不稳定或恒定的视频)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-20
  • 1970-01-01
  • 1970-01-01
  • 2017-11-13
  • 1970-01-01
  • 1970-01-01
  • 2016-06-08
相关资源
最近更新 更多