视频中的帧速率不正确

frame rate not correct in videos

我有一个 25 fps 的 12 秒视频。当我在 opencv 中以 25 fps 播放视频时,视频变为 16 秒。我通过使用获得 fps fps = get(cv2.CAP_PROP_FPS) 然后我设置了 waitKey(1000/fps) 但视频播放速度变慢了...

import numpy as np
import cv2
import time
start = time.time()

cap = cv2.VideoCapture("hackerman.mp4")
fps = cap.get(cv2.CAP_PROP_FPS)
print(fps)
while True:
    # Capture frame-by-frame
    ret, frame = cap.read()
    if ret == True:
        frame_new = frame
    else:
        end = time.time()
    # frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # turn video gray

    # Display the resulting frame
    cv2.namedWindow('frame', cv2.WINDOW_NORMAL)
    cv2.imshow('frame', frame_new)

    k = cv2.waitKey(int(round(1000/fps))) & 0xFF
    if k == 27:         # wait for ESC key to exit
        break
    elif cv2.getWindowProperty("frame", 0) == -1:
        break


print(end-start)
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

看来 cap.read() 的读取速度比帧速率更快,这在处理帧而不是显示帧时非常可取 - 因此在您的应用程序中您需要添加一个延迟使用例如time.sleep() 或在您的情况下 waitKey() 并且必须计算此值以达到 25fps 的帧速率。

对于最精确的 25fps,将下一帧的结束时间基于整体开始时间,如下所示(未测试):

frameref_ms = int(time.time()*1000)
frametime_ms = int(1000/fps)

while True:
    # update frameref to end frame period from now (regardless of how long reading and displaying the frame takes)
    frameref_ms += frametime_ms
    # Capture frame-by-frame
    ret, frame = cap.read()
    if ret == True:
        frame_new = frame
    else:
        end = time.time()
    # frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # turn video gray

    # Display the resulting frame
    cv2.namedWindow('frame', cv2.WINDOW_NORMAL)
    cv2.imshow('frame', frame_new)
    # wait for a keypress or the time needed to finish the frame duration
    k = cv2.waitKey(frameref_ms-int(time.time()*1000)) & 0xFF
    if k == 27:         # wait for ESC key to exit
        break
    elif cv2.getWindowProperty("frame", 0) == -1:
        break

这种有绝对时间完成 display/read 下一帧的技术意味着帧速率将是准确的,自动补偿其他 OS 任务的多任务任务不会占用太多 CPU 以致于您的代码几乎无法运行,如果您遇到该问题,我想您将不得不提高 Python 的优先级,这会减慢其他程序的速度。我已经在 temperature/vibration 测量的定时采样中使用了这种方法,并且效果很好。在我的一个答案中看到相同的技术

如果你真的 careful/pessimistic 你也会检查 waitKey() 在帧读取+显示花费的时间长于帧周期的情况下没有被给予负延迟。