使用其他按键作为opencv的waitKey()函数参数

85 投票
12 回答
353358 浏览
提问于 2025-04-17 13:29

我正在做一个程序(使用python和opencv),在这个程序里,我用空格键来切换到下一个画面,用Esc键来退出程序。这两个键是我目前能用的。为了找到更多的键,我尝试了各种代码,但都没有成功,尤其是方向键。

我发现了这个链接,里面讲了关于waitkey的内容,但我试了之后也没用。

所以我想问的是,除了esc空格键之外,怎么才能在我的python-opencv程序中捕捉到其他键,以便触发某些功能呢?

12 个回答

17

已经发布的回答表明,waitKey 返回的一些奇怪值可能是由于不同平台之间的差异。下面,我想提出的是(至少在某些平台上)waitKey 的奇怪行为是由于键盘修饰键的影响。这个帖子看起来和Tomasz的回答相似,因为我最开始是把它写成一个编辑,但被拒绝了。


waitKey 返回的键码会根据启用的修饰键而变化。NumLock、CapsLock,以及Shift、Ctrl和Alt键都会通过启用某些位来修改waitKey 返回的键码。这些标志中最小的是Shift,值为0x10000。

下面是Tomasz发布的脚本的修改版本:

#!/usr/bin/env python

import cv2
import sys

cv2.imshow(sys.argv[1], cv2.imread(sys.argv[1]))
res = cv2.waitKey(0)
print 'You pressed %d (0x%x), 2LSB: %d (%s)' % (res, res, res % 2**16,
    repr(chr(res%256)) if res%256 < 128 else '?')

这将产生以下结果:

  • 按下字母q和NumLock:

    你按下了1048689 (0x100071),2LSB: 113 ('q')

  • 按下Escape键和CapsLock,但没有NumLock:

    你按下了131099 (0x2001b),2LSB: 27 ('\x1b')

  • 按下空格键和Shift以及NumLock:

    你按下了1114144 (0x110020),2LSB: 32 (' ')

  • 按下右箭头键和Ctrl,NumLock关闭:

    你按下了327507 (0x4ff53),2LSB: 65363 ('S')

我希望这能帮助解释waitKey 的奇怪行为,以及如何获取实际按下的键,而不受NumLock和CapsLock状态的影响。从这里开始,做一些类似的事情相对简单:

ctrlPressed = 0 != res & (1 << 18)

...因为“控制键”标志是(将最低有效位算作位0)位18。Shift在位16,CapsLock的状态在位17,Alt在位19,NumLock在位20。正如Tomasz好心指出的,单独按下Shift也会返回一个值,LShift和RShift有不同的值(仍然包含刚才描述的所有这些修饰键)。我鼓励你在依赖这些值之前,先在你自己的平台上仔细检查所有这些修饰键和它们的值。:)

26

通过 waitKey 返回的按键代码似乎和平台有关。不过,看看这些按键返回的值可能会很有趣(顺便说一下,在我的平台上,Esc 并不是返回27...)

Abid的回答中列出的那些整数对普通人来说大多没什么用(除非你是个天才)。不过,如果你把它们转换成十六进制,或者看看最低有效字节,你可能会发现一些规律...

下面是我用来检查 waitKey 返回值的脚本:

#!/usr/bin/env python

import cv2
import sys

cv2.imshow(sys.argv[1], cv2.imread(sys.argv[1]))
res = cv2.waitKey(0)
print('You pressed %d (0x%x), LSB: %d (%s)' % (res, res, res % 256,
    repr(chr(res%256)) if res%256 < 128 else '?'))

你可以把它当作一个简单的命令行图片查看器。

以下是我得到的一些结果:

  • 按下字母 q:

    你按下了 1048689 (0x100071),最低有效字节: 113 ('q')

  • 按下 Esc 键(通常是 ASCII 27):

    你按下了 1048603 (0x10001b),最低有效字节: 27 ('\x1b')

  • 按下空格键:

    你按下了 1048608 (0x100020),最低有效字节: 32 (' ')

这个列表可以继续,不过你可以看到,当你得到一些“奇怪”的结果时,应该怎么处理。

顺便说一下,如果你想把它放在一个循环里,你可以直接用 waitKey(0)(一直等待),而不是忽略 -1 的返回值。

编辑:这些高位的内容比表面看起来的要复杂,具体请参考 Andrew C 的回答(提示:这和键盘的修饰键有关,比如各种“锁”,例如 NumLock)。

不过,我最近的经验显示,确实存在平台依赖性——例如在 Windows 上使用 Python 3.6 的 Anaconda 中的 OpenCV 4.1.0 并不会产生这些高位,对于某些(重要的)按键,它从 waitKey() 返回 0(比如方向键、HomeEndPageDnPageUp,甚至 DelIns)。至少 Backspace 返回 8(但是... 为什么 Del 不返回呢?)。

所以,如果你想要一个跨平台的用户界面,你可能只能使用 WASD、字母、数字、EscSpaceBackspace 这些键;)

139

你可以在Python中使用 ord() 函数来实现这个功能。

比如,如果你想模拟按下 'a' 键,可以这样做:

if cv2.waitKey(33) == ord('a'):
   print "pressed a"

这里有一个示例代码:绘制直方图

更新:

要找到任何键的值,可以用一个简单的脚本打印出这个键的值,代码如下:

import cv2
img = cv2.imread('sof.jpg') # load a dummy image
while(1):
    cv2.imshow('img',img)
    k = cv2.waitKey(33)
    if k==27:    # Esc key to stop
        break
    elif k==-1:  # normally -1 returned,so don't print it
        continue
    else:
        print k # else print its value

运行这段代码后,我得到了以下值:

Upkey : 2490368
DownKey : 2621440
LeftKey : 2424832
RightKey: 2555904
Space : 32
Delete : 3014656
...... # Continue yourself :)

撰写回答