CV01-OpenCV窗口手动关闭后堵塞程序运行的问题

·

0 min read

jameslei.com

OpenCV窗口手动关闭后堵塞程序运行的问题

问题描述

系统环境:Ubuntu 18.04

OpenCV版本:4.1.0

Python版本:3.7.3

当我们通过OpenCV的imshow()方法显示图像后,我们会使用waitKey()方法保持窗口存在来展示图像。

此时我们能够获取用户的按键来关闭窗口,该方法的实现为:

import cv2 as cv

img = cv.imread(img_dir)

cv.imshow('img',img)
if cv.waitKey(0) == 27: # wait for ESC
    cv.destroyWindow('img')

此时程序会堵塞并且一直等待用户在图片窗口按下ESC键。

而当我们通过图像窗口的关闭按钮关闭图像后,程序依然被堵塞,而此时我们所期望的是程序能够继续运行下去,因此我们需要检测图像窗口是否被关闭。

解决方法

我们不再使用waitKey(0)来显示图像,转而通过循环来保持图像的展示,同时检测:

  1. 用户是否按下指定按键
  2. 窗口是否被关闭

我们通过获取窗口的WND_PROP_VISIBLE属性来判断窗口是否存在,使用到的方法为:cv.getWindowProperty(win_name,prop_id),该方法能够获取到的窗口属性都有:

//! Flags for cv::setWindowProperty cv::getWindowProperty
enum WindowPropertyFlags {
       WND_PROP_FULLSCREEN   = 0, //!< 全屏(can be WINDOW_NORMAL or WINDOW_FULLSCREEN).
       WND_PROP_AUTOSIZE     = 1, //!<自动大小(can be WINDOW_NORMAL or WINDOW_AUTOSIZE).
       WND_PROP_ASPECT_RATIO = 2, //!< 保持纵横比(can be set to WINDOW_FREERATIO or WINDOW_KEEPRATIO).
       WND_PROP_OPENGL       = 3, //!< opengl窗口.
       WND_PROP_VISIBLE      = 4  //!< 检测窗口是否存在并且是否可见
     };

综合起来的实现为:

import cv2 as cv

img = cv.imread(img_dir)
cv.imshow('img',img)
while cv.waitKey(100) != 27:# loop if not get ESC
    if cv.getWindowProperty('img',cv.WND_PROP_VISIBLE) <= 0:
        break
cv.destroyWindow('img')

此举能够在手动关闭窗口后保持程序的正常运行不堵塞。

封装

我将该功能封装成为了一个方法showImage(),代码如下:

def showImage(img, title='image', t=1000, esc=False):
    cv.imshow(title, img)
    if esc:
        while cv.waitKey(100) != 27:
            if cv.getWindowProperty(title,cv.WND_PROP_VISIBLE)<=0:
                break
    else:
        cv.waitKey(t)
    cv.destroyWindow(title)

该方法实现的功能为,当esc属性为False的时候,窗口显示tms自动关闭;而当escTrue的时候,我们会检测窗口是否存在和是否按下ESC键,若手动关闭了窗口或按下ESC键关闭窗口,程序将继续运行。

参考