我正在处理一个程序(使用python和opencv),我使用空格键
进入下一帧,使用Esc键
退出程序。这是我能够工作的唯二按键。我试图找到其他按键的相关信息,尝试了各种代码,但没有成功,特别是方向键。
我在这里找到了与waitkey
有关的信息,但是它并不起作用。
我的问题是,如何捕捉除esc
和spacebar
以外的其他按键,以触发我的Python-opencv程序中的特定函数?
ord()
函数来实现这一点。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 :)
waitKey
返回的键码似乎与平台有关。然而,查看键返回什么可能非常有教育意义(顺便说一下,在我的平台上,Esc不返回27...)。
阿比德的答案列出的整数对于人类大脑来说大多无用(除非你是神童……)。但是,如果您以十六进制形式检查它们,或者看一下最低有效字节,您可能会注意到模式……
我用于检查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),LSB:113('q')
Esc 键(传统上,ASCII 27):
你按下了 1048603(0x10001b),LSB:27('\x1b')
空格:
你按下了 1048608(0x100020),LSB:32(' ')
这个列表可能还可以继续,但是当你获得“奇怪”的结果时,你可以看到前进的方式。
顺便说一句,如果你想把它放在一个循环中,你可以只使用 waitKey(0)
(永远等待),而不是忽略 -1
的返回值。
编辑:这些高位有更多的含义 - 请参见 Andrew C 的答案(提示:它与键盘修饰键有关,例如所有的“锁定”键,如 NumLock)。
然而,我的最近的经验表明,存在平台依赖性 - 例如,来自 Anaconda 的 Python 3.6 上的 OpenCV 4.1.0 在 Windows 上不会产生这些位,并且对于一些(重要的)键,它从 waitKey()
返回 0
(箭头,Home,End,PageDn,PageUp,甚至是 Del 和 Ins)。至少 Backspace 返回 8
(但...为什么不是 Del?)。
因此,对于跨平台的 UI,你可能只能使用 W、A、S、D、字母、数字、Esc、Space 和 Backspace ;)
res = cv2.waitkey() & 0xEFFFFF
。 - billyjmc0x8
而不是0x1
。这些位是键盘修饰符的标志。清除符号位将是& 0x7fff...。 - Tomasz Gandor已经发布的答案表明,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 '?')
以下是相应的结果:
使用NumLock键的q字母:
您按下了1048689(0x100071),2LSB:113('q')
CapsLock但未使用NumLock的Escape键:
您按下了131099(0x2001b),2LSB:27('\ x1b')
使用Shift和NumLock的空格键:
您按下了1114144(0x110020),2LSB:32(' ')
使用Control,NumLock关闭的右箭头键:
您按下了327507(0x4ff53),2LSB:65363('S')
我希望这有助于解释waitKey
的不寻常行为以及如何获取实际按下的键,而不考虑NumLock和CapLock的状态。从这里开始,做一些类似以下的事情相对简单:
ctrlPressed = 0 != res & (1 << 18)
...作为“控制键”标志的是(将最低有效位视为位0)第18位。Shift在第16位,CapsLock的状态在第17位,Alt在第19位,NumLock在第20位。正如Tomasz所指出的那样,仅按下Shift键也会返回一个值,对于LShift和RShift分别有不同的值(仍然带有所有这些修饰符)。在依赖它们之前,请务必在自己的平台上双重检查所有这些修饰符和值。 :)
(1<<16)
)。此外,只需按下Shift也会返回一个值——LShift为0xffe1
,RShift为0xffe2
。修饰符也适用于这里。 - Tomasz Gandor对于我来说,下面的代码无法正常工作,当它运行时,图片会在没有你按下按钮的情况下迅速跳转到下一张:
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
def test_wait_key():
lst_img_path = [
'/home/xy/yy_face_head/face_det_test/111.png',
'/home/xy/yy_face_head/face_det_test/222.png'
#.....more path ...
]
for f_path in lst_img_path:
img = cv2.imread(f_path)
cv2.imshow('tmp', img)
c = cv2.waitKey(0) % 256
if c == ord('a'):
print "pressed a"
else:
print 'you press %s' % chr(c)
因此,在跨平台实现上可能需要一些关注。然而,对我来说,这是迄今为止在Windows上获取箭头键等工作最简单直接的解决方案。类似于waitKey,但返回完整的键代码。
注意
键代码是实现特定的,取决于使用的后端:QT/GTK/Win32等
waitKeyEx()
在此提交中于2016年被引入,这是在我留下初始评论之后。有趣的是,同一提交修补了原始的waitKey()
函数,使其始终被掩码为code&0xff
,这与我的答案中的res%2 ** 16
具有相同的效果。并不令人惊讶,但非常有帮助的是,完整的按键代码取决于后端,这指向我们去获取更多信息的方向! - Andrew C.waitKeyEx()
是在2016年的这个提交中引入的,而这是在我留下初始评论之后。有趣的是,同一个提交还修补了原始的waitKey()
函数,使其始终被掩码为code & 0xff
,这与我自己的答案中的res % 2**16
具有相同的效果。并不奇怪,但将完整的按键码取决于后端明确说明了,这对于指引我们去寻找更多信息非常有帮助! - undefined对于C++:
如果使用键盘字符/数字,更简单的解决方案是:
int key = cvWaitKey();
switch(key)
{
case ((int)('a')):
// do something if button 'a' is pressed
break;
case ((int)('h')):
// do something if button 'h' is pressed
break;
}
int
,只需使用 case 'a':
即可。 - eezstreet在使用Ubuntu和C++时,我遇到了字符/整数转换的问题。我需要使用cv::waitKey()%256
来获取正确的ASCII值。
在Ubuntu18、python3和OpenCV 3.2.0上有效的答案与上面的答案类似。但是需要更改cv2.waitKey(0)
这一行。这意味着程序将等待直到按下一个按钮。
使用此代码,我找到了箭头按钮的键值:向上箭头(82)、向下箭头(84)、向左箭头(81)和回车键(10)等。
import cv2
img = cv2.imread('sof.jpg') # load a dummy image
while(1):
cv2.imshow('img',img)
k = cv2.waitKey(0)
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
(在cv2.imshow中显示)
cv2.waitKey(0)
会在按下“Scr”按钮(或其组合键)后继续,但您可以尝试这个方法
cv2.waitKey(0)
input('')
使用cv2.waitkey(0)可以给程序足够的时间来处理你想在imshow中看到的一切,而input('')则会让程序等待你在控制台窗口按下Enter键。
这适用于Python 3。
我也觉得这很令人困惑。 我正在运行Ubuntu 18,发现以下内容: 如果cv.imshow窗口具有焦点,则在终端中会得到一组值-如上面讨论的ASCII值。
如果终端具有焦点,则会看到不同的值。即,按a键时将看到“a”(而不是ASCII值97),按Escape键时将看到“^]”而不是“27”。
我在任何情况下都没有看到上述6位数字,并且我使用了类似的代码。 看来waitKey的值是以毫秒为单位的轮询周期。 这些点说明了这一点。
运行此片段并在测试图像上具有焦点时按键,然后单击终端窗口并按相同的键。
import cv2
img = cv2.imread('test.jpg')
cv2.imshow('Your test image', img)
while(1):
k = cv2.waitKey(300)
if k == 27:
break
elif k==-1:
print "."
continue
else:
print k