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

我正在编写一个程序(python,opencv) ,其中我使用 spacebar进入下一帧,使用 Esc退出程序。这是我唯一能用的两把钥匙。我试图找到更多的钥匙,试图为他们的各种代码,但没有工作。特别是箭头键。

我找到了 < a href = “ http://pklaus.github.com/HHG-Analysis-Python/helpers.html # module-keycode”> this 关于 waitkey的内容,但是它不起作用。

因此,我的问题是,除了 escspacebar之外,如何捕获其他键来触发 python-opencv 程序中的某些函数?

313362 次浏览

您可以在 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 :)

waitKey返回的密码似乎与平台有关。 然而,这可能是非常有教育意义的,看看钥匙还有什么用 (顺便说一句,在我的平台上,埃斯克不会返回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 '?'))

您可以将其用作最小的命令行图像查看器。

我得到了一些结果:

  • 问:

    您按了1048689(0x100071) ,LSB: 113(‘ q’)

  • 转义键(传统上,ASCII 27) :

    您按下了1048603(0x10001b) ,LSB: 27(’x1b’)

  • 空间:

    您按了1048608(0x100020) ,LSB: 32(’)

当你得到“奇怪”的结果时,这个列表可以继续下去,不管你看到的是怎样的道路。

顺便说一句,如果你想把它放在一个循环中,你可以只 waitKey(0)(永远等待) ,而不是忽略 -1返回值。

编辑 : 这些高比特比我们看到的要多得多——请看 Andrew C 的回答(提示: 它与键盘修饰符有关,比如所有的“ Lock”,如 NumLock)。

然而,我最近的经验表明,存在一种平台依赖性——例如,阿纳康达的 Opencv4.1.0在 Python 3.6在 Windows 上不产生这些比特,对于一些(重要的)键,返回 waitKey()0(箭头、 HomeEndPageDnPageUp,甚至是 DelIns)。至少 Backspace返回 8(但是... 为什么不返回 Del?).

因此,对于跨平台用户界面,你可能只能使用 WASD、字母、数字、 EscSpaceBackspace;)

对于 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;
}

已经公布的答案表明,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 的退出键:

    您按下了131099(0x2001b)、2LSB: 27(‘ x1b’)

  • Shift 和 NumLock 空间:

    您按了1114144(0x110020) ,2LSB: 32(’)

  • 右箭头键控制,锁定:

    您按下了327507(0x4ff53) ,2LSB: 65363(‘ S’)

我希望这有助于解释 waitKey的异常行为,以及如何让实际的键按下,而不管 NumLock 和 CapLock 的状态如何。从这里开始,做这样的事情相对简单:

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

因为“控制键”的标志是第19位。Shift 在位17,CapsLock 的状态在位18,Alt 在位20,NumLock 在位21。

使用 Ubuntu 和 C + + 时,我在字符/整型转换方面遇到了问题。我需要使用 cv::waitKey()%256来获得正确的 ASCII 值。

如果您想暂停程序以截取进度的屏幕截图

(在 let’s say cv2.imshow 中显示)

按下“ Scr”按钮(或其组合)后,cv2.waitKey(0)将继续运行,但您可以尝试这样做

cv2.waitKey(0)
input('')

Waitkey (0)为程序提供足够的时间来处理您想要在 imshow 和 input (”)中看到的所有内容

让它等待您在控制台窗口中按 Enter

这个在 python 3上可以工作

至于我,下面的代码 不起作用,当它运行时,图像将步骤到下一个没有您的新闻:

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)

产出如下:

enter image description here

我也觉得很困惑。 我正在运行 Ubuntu 18,发现了以下内容: 如果 cv.imshow 窗口具有焦点,那么您将在终端中获得一组值,类似于上面讨论的 ASCII 值。

如果终端有焦点,您将看到不同的值。IE-当你按下 a 键(而不是 ASCII 值97)时,你会看到“ a”,当你按下 Escape 键时,你会看到“ ^ ]”而不是“27”。

我没有看到上面提到的6位数字在任何情况下,我使用类似的代码。似乎 waitKey 的值是 mS 中的投票周期,点说明了这一点。

当焦点在测试图像上时,运行此代码片段并按下键,然后单击终端窗口并按下相同的键。

    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

这会直接将密钥组合打印到图像上:

z pressed an ctrl + z pressed

第一个窗口显示按下 'z',第二个窗口显示按下 'ctrl' + 'z'。使用组合键时,会出现问号。

不要搞错问号代码,它是 63

import numpy as np
import cv2


im = np.zeros((100, 300), np.uint8)
cv2.imshow('Keypressed', im)
while True:
key = cv2.waitKey(0)
im_c = im.copy()
cv2.putText(
im_c,
f'{chr(key)} -> {key}',
(10, 60),
cv2.FONT_HERSHEY_SIMPLEX,
1,
(255,255,255),
2)
cv2.imshow('Keypressed', im_c)
if key == 27: break # 'ESC'

在 Ubuntu18、 python3、 opencv3.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.waitKeyEx()。OpenCV 在 cv2.waitKeyEx()上的 文件内容如下:

类似于 waitKey,但返回完整的键代码。

注意

关键代码是实现特定的,取决于使用的后端: QT/GTK/Win32/etc

因此,跨平台实现可能需要一些注意力。然而,对我来说,这是迄今为止最简单和最直接的解决方案,以获得箭头键等工作在 Windows 上。