【问题标题】:OpenCV closing a window with a mouse click on a Raspberry PiOpenCV 在 Raspberry Pi 上单击鼠标关闭窗口
【发布时间】:2015-06-15 10:47:44
【问题描述】:

我想要做的是,我想让用户单击 OpenCV 窗口中的关闭“X”按钮并让程序识别它,然后关闭该窗口。

这似乎并不容易,经过四天的兜兜转转并找出如何在 Windows 机器上完成它,我并没有更接近于找出如何在 Raspberry Pi 上使用 Python 完成它。

我想我需要获取 OpenCV 窗口的句柄(如何?),然后使用它来查看窗口是否仍然可见(什么调用?),如果不是,则停止程序(我可以做那一点)。

我已经尝试过 cvGetWindowHandle("window_name") 但我已经下载了源代码并且 GetWindowHandle 似乎无法从 python 获得。

【问题讨论】:

  • OpenCV 在 Raspbian 上使用什么窗口后端? Qt?
  • 不知道,怎么发现?
  • 我不确定如何在运行时执行此操作,如果您自己构建它,那么我猜 gtk 是 Linux 的默认设置,如果您设置了一些特定的标志,则为其他设置。但无论如何,这无济于事,因为您必须通过后端 api 访问窗口并接收我猜您不想做的事件。我会尝试考虑是否有更简单的方法。

标签: python opencv raspberry-pi


【解决方案1】:

捕获鼠标左键单击事件并关闭窗口的代码相当简单:

if event == cv2.EVENT_LBUTTONDOWN:
    cv2.destroyWindow("window_name")

有一个关于如何使用按钮单击事件here 的教程,这是我获取该代码的地方,它提供了一个完整的python 工作示例。

但是,您可能在 Rpi 上运行基于 unix 的系统,因此需要读取 This answer,因为您需要 waitKey(1) 的组合才能使其工作。

【讨论】:

  • 抱歉,这行不通。如果鼠标点击在关闭按钮所在的窗口栏,则不会返回任何事件。
【解决方案2】:

我可能有一个解决方案,但我不能 100% 确定,所以你必须自己检查一下:) 我假设 OpenCV 在下面使用 X11(如果没有这些都没有意义)。使用 X11,您可以:

1) 为您的 OpenCV 窗口查找 X11 窗口句柄,如 here 所述

2) 使用XSelectInput 钩入它的事件循环,有点类似于here 所做的事情。我假设您应该使用StructureNotifyMask 作为掩码来获取XDestroyWindowEvent 事件。运行X11事件循环,一旦得到对应的事件就可以调用OpenCV的destroyWindow函数。

这个建议是基于假设的,我不能保证它会起作用,但据我所知,如果 OpenCV 不是用其他特定的窗口管理器构建的,这应该可以工作。据我了解,Raspbian 在某种程度上是随 X11 一起提供的,然后它切换到了 Wayland。如果你有 Wayland 的图像,那么这可能不起作用(很抱歉,我的 Linux 技能不包含如何确定使用哪一个的秘诀:D)。

更新

实际上,经过更多阅读后,我似乎觉得 gtks 应该能够处理下面使用的任何内容(X11/Wayland)。因此,如果您安装 gtk 开发库,您还应该能够连接到 Windows 删除信号,如here 所述。那么唯一的问题就是如何获取窗口句柄了。

我的个人建议 - 使用 Qt 或其他一些 GUI 友好的框架来渲染 OpenCV 图像,而不是直接使用 OpenCV。 OpenCV 是一个成像框架,但恕我直言 highgui 对于任何严重的事情都无法使用。

【讨论】:

  • 谢谢,但就迷宫般的 Linux 而言,所有这些链接都超出了我的想象。更新链接都是关于 C 的,我正在使用 Python。
  • @Grumpy-Mike 你能详细说明你想用 OpenCV 做什么吗?也许我可以建议一种更简单的方法来做同样的事情并完全控制窗口。
  • 我正在用摄像机做一系列事情。第一个是视频音序器,其中板上的彩色钉确定播放的音符。但是,当您按下关闭十字时,用户会期望窗口关闭,而是关闭并在随机位置弹出。我不敢相信任何人会期望窗口中的任何其他行为,但实际上使这种简单的行为起作用似乎很难。
  • @Grumpy-Mike 我知道这对于 Qt 经验很少的人来说可能看起来很难,但这个问题 (stackoverflow.com/questions/21246766/…) 使用 OpenCV 在 QT 小部件上显示帧。您可以尝试调整它,以便拥有 OpenCV 并完全控制窗口。
  • 谢谢,但该页面是用 C 语言编写的,我正在用 Python 编写,我认为学习一个新主题 (QT Widget) 并在两者之间进行翻译的工作量太大而无法关闭通过单击关闭框打开一个窗口。此外,它看起来也像旧版本的 openCV,因此也需要转换。我还担心这会减慢速度,并且应用程序需要尽可能快的处理时间。无论如何感谢您的关注,看来这个问题没有合理的解决方案。
【解决方案3】:

我要做的就是让用户单击 openCV 中的关闭 X 窗口

这就是我在捕获循环中的做法(RPi 拉伸,opencv 4.0):

while True: 
    # do your video capture
    # ... 
    cv.imshow("video frame",frame)
    if cv.getWindowProperty('video frame', 1) < 0:
        break

getWindowProperty 没有太多文档记录,但顾名思义,它的作用是返回给定窗口的属性。其中两个感兴趣的标志是WND_PROP_FULLSCREEN(或0)和WND_PROP_AUTOSIZE(或1)。当窗口关闭时,函数返回-1。使用它来立即中断您的循环(如果不在循环中,则关闭您的窗口)。

参考资料:

【讨论】:

    【解决方案4】:

    投票cv2.getWindowImageRect(windowName)。当用户单击窗口关闭按钮时,它将返回 (-1, -1, -1, -1)。

    # check if window was closed or image was resized
    
    xPos, yPos, width, height = cv2.getWindowImageRect(windowName)
    
    if xPos == -1: # if user closed window
        pass # do whatever you want here if the user clicked CLOSE
    

    我还没有在任何地方找到这个文档;在处理窗口大小调整时偶然发现了它。 (使用 OpenCV 4.1.0 测试。)

    【讨论】:

      猜你喜欢
      • 2021-05-31
      • 1970-01-01
      • 1970-01-01
      • 2011-11-17
      • 2012-04-10
      • 2012-04-30
      • 1970-01-01
      • 2019-05-08
      • 1970-01-01
      相关资源
      最近更新 更多