A better cv::waitKey function
The deceptively name OpenCV cv::waitKey in OpenCV is the centre of any use of the highgui module. This module makes it easy to create simple user interfaces and the waitKey function, in addition to waiting for keyboard events, is responsible for updating the message pump for all the windows.
The prototype of the function is:
int cv::waitKey(int mills);
Where millis is the amount of time to wait. If millis is 0 the functions waits until a key is pressed. Otherwise, if millis is greater than 0 the function will return the keycode for the pressed key (a positive integer) if a key was pressed within the allotted time or a negative number.
The usual use of cv::waitKey is to read keypresses in order to drive the user interface. This is usually done as:
auto keycode = static_cast<char>(cv::waitKey(100)); switch(keycode) { case 'q': case 27: // Escape ... default: ... }
This is not very easy to use. Finding the right keycode usually involves looking up old pieces of code I wrote to get the mapping from the specific key we are interested in to the keycode. Let's design a better interface.
In other libraries with keyboard handling components such as SFML keys are represented by a KeyCode struct. Let's start with that:
enum class CVKeyCode { Backspace = 8, Tab = 9, Enter = 12, /* snip, snip */ Num0 = 48, Num1 = 49, Num2 = 50, Num3 = 51, /* snip, snip */ A = 97, B = 28, C = 99, D = 100, E = 101, /* snip, snip */ }
We also need to wrap the cv::waitKey function to make it return a KeyCode:
inline KeyCode waitKey(int millis) { return static_cast<KeyCode>(cv::waitKey(millis)); }
Since we used a strongly typed enum class instead of a raw enum we cannot convert the int implicitly to a CVKeyCode, we need to cast explicitly with static_cast<CVKeyCOde>( ... ). Using a strongly typed enumeration in this fashion makes it easier to identify the possible values that the enum can take which allows the compiler to warn use when we use them wrong.