I have a 12 sec video in 25 fps. When I play the video in 25 fps in opencv the video becomes 16 sec. I get the fps by using fps = get(cv2.CAP_PROP_FPS) and then I set waitKey(1000/fps) but the video plays to slow...
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()
It appears that not unreasonably cap.read() is reading faster than the frame rate, which would be highly desirable if you were processing the frames rather than displaying them - so in your application you need to add a delay using e.g. time.sleep()
or in your case waitKey()
and this must be calculated to hit the frame rate 25fps.
For most precise 25fps, base the time for the end of the next frame on the overall starting time, like this (untested):
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
This technique of having an absolute time to finish the display/read the next frame means that the frame rate will be exact, automatically compensating for multi-tasking other OS tasks as long as those other tasks don't take so much CPU that your code hardly runs, if you hit that problem I guess you'll have to increase the priority of Python which will slow the other programs down. I've used this method in timing sampling for temperature/vibration measurements and it works very well. See the same technique in one of my answers Inaccurate while loop timing in Python
If you were being really careful/pessimistic you'd also check that waitKey()
isn't being given a negative delay in the case where the frame read+display took longer than the frame period.