How to show videos frame by frame (with key presses) with python and OpenCV

Question:

I am trying to open a video file and play it frame by frame using key presses. So it would open and show a single frame indefinitely until a particular key is pressed and then it would switch to the next frame.

I’m using Python 3 and OpenCV. This is the first time I am using OpenCV so any corrections/recommendations are welcome.

The code below works in the sense that it shows the video one frame at a time but not only when I press k but with any key press and it ignores the q to exit.

import cv2
import os


def play_video(folder):
    # load video capture from file
    video = cv2.VideoCapture(os.path.join(folder, "Field.mp4"))
    # window name and size
    cv2.namedWindow("video", cv2.WINDOW_AUTOSIZE)
    while video.isOpened():
        # Read video capture
        ret, frame = video.read()
        # Display each frame
        cv2.imshow("video", frame)
        # show one frame at a time
        cv2.waitKey(00) == ord('k')
        # Quit when 'q' is pressed
        if cv2.waitKey(1) == ord('q'):
            break
    # Release capture object
    video.release()
    # Exit and distroy all windows
    cv2.destroyAllWindows()


play_video("bb-eye-s001")

I would like to press a specific key to move forward (one to move back too, but that might be for another question) and be able to press q to quit.

Any suggestions? Thank you in advance!

Asked By: Bioso

||

Answers:

The cv2.waitKey(00) == ord('k') condition you have is never tested. Effectively, that line computes True or False, then throws it away.
What you want it to stop until the user presses either 'q' or 'k':

while video.isOpened():
    # Read video capture
    ret, frame = video.read()
    # Display each frame
    cv2.imshow("video", frame)
    # show one frame at a time
    key = cv2.waitKey(0)
    while key not in [ord('q'), ord('k')]:
        key = cv2.waitKey(0)
    # Quit when 'q' is pressed
    if key == ord('q'):
        break
Answered By: GPhilo

An alternate solution that has better control flow, a single call to waitKey, "event handler" code blocks, proper error checking on the VideoCapture object.

...
assert video.isOpened()

cv.namedWindow("video", cv.WINDOW_NORMAL)

while True:
    key = cv.waitKeyEx(0) # waitKeyEx also reads arrow keys

    if key == ord('k'):
        (ret, frame) = video.read()
        if not ret: break
        cv.imshow("video", frame)
    
    elif key == ord('q'):
        break

    else:
        print(f"unknown key code 0x{key:02x}")

cv.destroyWindow("video")
...
Answered By: Christoph Rackwitz