FPS drop due to the WaitKey function

Hello!
In my project I need to control the movement of the drone with the WASD keys. If I press them once, everything looks fine: the command is sent to the drone and it moves correctly, the video stream goes well. But if I hold down any button on the keyboard, the drone will move correctly, but the video will stop until I release the button.
So, I tried this without the drone, just with VideoCapture and my webcam, and I had the same results, but instead of the video stream stopping completely, I had a huge FPS drop.
I then tried using another library to capture keyboard events (module “keyboard”) and got similar results.
My question is, why is this happening and what can I do to solve this problem, because sometimes I need to hold down the key?

post a minimal reproducible example please.

import cv2
from keyboard import is_pressed as key

cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()
    cv2.imshow("frame", frame)
    key = cv2.waitKey(1)    
    if key == ord('q'):
        break
    
cv2.destroyAllWindows()
cap.release()

ah yes, I can reproduce the issue on win32.

what OS/GUI toolkit do you run this on?

my best guess is that the event processing sees the keyboard event and stops there, before handling any drawing events, which may come before or after a keyboard event.

cheap workaround: run waitKey(), but repeat if there was a key code returned (stop if there wasn’t).

import cv2

cap = cv2.VideoCapture(0)
assert cap.isOpened()

while True:
    ret, frame = cap.read()
    if not ret: break
    cv2.imshow("frame", frame)

    do_stop = False
    while True:
        key = cv2.waitKey(1)
        if key == -1: # no keycode reported
            break # inner loop
        if key == ord('q'):
            do_stop = True # break outer loop
            # don't break inner loop yet, we'll do that in the next iteration when no keycode is reported

    if do_stop:
        break

cv2.destroyAllWindows()
cap.release()

it might be possible, for some GUI toolkits, to fix this inside of waitKey().

1 Like

Thank you very much!

what OS/GUI toolkit do you run this on?

This program runs on my notebook with OS Win10

good to know. I was curious to see if this happened on non-Windows as well.

I’ve investigated the code in window_w32.cpp some more. it’s possible to process non-key events first but it’s messy in some instances. Windows API knows PeekMessage and GetMessage. PeekMessage can exclude input events or it could be used to process just until a key event is found. PeekMessage is used in some situations, but GetMessage in others. GetMessage can’t exclude input events, it can only select ranges to include, which isn’t good enough. implementing a fix/improvement for the situation in there would require careful planning and documentation of the code.