Sourav
Sourav

Reputation: 866

Play One Frame Per Second with Opencv Python

There is a 30fps video with 2 hour playback time. I just need one frame per second to be played. I can do the following by -

cap = cv2.VideoCapture('vid.avi')
count = 0
while(True):
    ret, frame = cap.read()

    if count%30==0:
        cv2.imshow('frame',frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
    count = count+1
cv2.destroyAllWindows()

But the mentioned method is very slow and not feasible. I am trying to do something that will make a list of frame number to show (each 30th frame = 30,90,120,150,.....) then only access those frame and play. I have written the following codes -

import cv2

# read the video and extract info about it
cap = cv2.VideoCapture('vid.avi')


# get total number of frames and generate a list with each 30 th frame 
totalFrames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
x = [i for i in range (1, totalFrames) if divmod(i, int(30))[1]==0]


for myFrameNumber in x:
    cap.set(cv2.CAP_PROP_POS_FRAMES,myFrameNumber)
    while True:
        ret, frame = cap.read()
        cv2.imshow("video", frame)

        # something wrong in the following three line
        ch = 0xFF & cv2.waitKey(1)
        if ch == 27:
            break
cv2.destroyAllWindows()

The code only plays the 30th frame while the "esc" button pressed otherwise it plays at a normal speed. Can anyone please figure out the issue?

Upvotes: 1

Views: 2209

Answers (1)

J.D.
J.D.

Reputation: 4561

You are locked in the while True: loop until you press escape. The while has the code to display video normally, continually reading and displaying frames. But when you press escape the code exists to the for myFrameNumber in x: block which set the next frame in the array with frame numbers.

You should remove the While loop, so only the frames you set are read and displayed. To achieve a second delay, you can increase the wait time in waitKey (in milliseconds)

    for myFrameNumber in x:
            #set which frame to read
            cap.set(cv2.CAP_PROP_POS_FRAMES,myFrameNumber)
            # read frame
            ret, frame = cap.read()
            # display frame
            cv2.imshow("video", frame)

            # wait one second, exit loop if escape is pressed
            ch = 0xFF & cv2.waitKey(1000)
            if ch == 27:
            break

Upvotes: 1

Related Questions