OpenCV Python: How to detect if a window is closed?

Question:

I have the following code:

total_frames = 50
cv2.cv.NamedWindow("Dragonfly Simulation")
cv2.cv.StartWindowThread()
for i in range(total_frames):
    # do stuff
    img_name = # something
    img = cv2.cv.LoadImage(img_name)
    cv2.cv.ShowImage("Dragonfly Simulation", img)
    cv2.cv.WaitKey(2)
cv2.cv.DestroyWindow("Dragonfly Simulation")
cv2.cv.WaitKey(1)
# rest of code

So what does it do:

  1. Opens a window
  2. In a loop, shows an image on the window
  3. Once finished, closes the window
  4. Runs the rest of the code

However in this case I have the total_frame given before. I don’t want that.

Instead, I want a code that does the following:

  1. Opens a window
  2. In a loop, shows an image on the window
  3. Waits for the user to close that window
  4. When the user closes that window, exit loop, goes on with the rest of the code.

However, I cannot find a function in OpenCV that can detect when user closes a window. Can anyone suggest a workaround please?

Asked By: dessskris

||

Answers:

import cv2
import numpy as np

# total_frames = 50
cv2.namedWindow("Dragonfly Simulation")
cv2.startWindowThread()
# for i in range(total_frames):
while True:
    # do stuff
    img = np.random.randint(0,255,(200,300)).astype(np.uint8)
    cv2.imshow("Dragonfly Simulation", img)
    key = cv2.waitKey(200)
    print key
    if key in [ord('a'), 1048673]:
        print 'a pressed!'
    elif key in [27, 1048603]: # ESC key to abort, close window
        cv2.destroyAllWindows()
        break

# do the rest of processing after break 
print 'results:'

Sure, you can check user inputs using waitKey and here is a small example based on your code. I changed old cv interface to cv2. I think cv is obsolete.

(Edit) I moved cv2.destroyAllWindows() to inside the while loop to make it clear that the window closes when the user pressed ESC key (which you can assign a key of your choice). I do not think opencv has a proper event handler to catch the window close event like in other GUI toolkit (wxPython etc). So you will need to define how your users should close the window and watch out for that.

Answered By: otterb

I was just looking for a way to detect when the window has been closed using the X button of the window in addition to waiting for a key press, but I couldn’t find an answer anywhere (IsWindowVisible and cvGetWindowHandle are not available in the Python cv2 module).

So I played around and this is how it works:

while cv2.getWindowProperty('window-name', 0) >= 0:
    keyCode = cv2.waitKey(50)
    # ...

cv2.getWindowProperty() returns -1 as soon as the window is closed.


For explanation, see the documentation for the enumeration of cv::WindowPropertyFlags: getting the flag with index 0 is the fullscreen property, but actually it doesn’t matter which flag to use, they all become -1 as soon as the window is closed.


Note: This might only work for certain GUI backends. Notably, it will not work with the GTK backend used in Debian/Ubuntu packages. To use the Qt backend instead, you have to install opencv-python via pip.

Answered By: Simon Hänisch

As of version 2.2 there is a simple solution (this is modified from the loop in hist.py):

    cv2.imshow('image',im)
    while True:
        k = cv2.waitKey(100) # change the value from the original 0 (wait forever) to something appropriate
...
        elif k == 27:
            print('ESC')
            cv2.destroyAllWindows()
            break        
        if cv2.getWindowProperty('image',cv2.WND_PROP_VISIBLE) < 1:        
            break        
    cv2.destroyAllWindows()
Answered By: David Kohen
        if cv2.getWindowProperty('windowname',1) == -1 :
            break
        cv2.imshow('windowname', image)
Answered By: stephen george

I tested on C++ using the getWindowProperty(‘image’, WND_PROP_VISIBLE), but it does not work. So I used the WND_PROP_AUTOSIZE and it works.

I did like this:

cv::namedWindow("myTitle", WINDOW_AUTOSIZE);

while(1)
{
    cv::imshow("myTitle", myImage);


    if (cv::getWindowProperty("myTitle", WND_PROP_AUTOSIZE) == -1)
        break;
}
Answered By: Derzu

I used the following code t check if a key is pressed or the window is closed at the same time.

    while cv2.getWindowProperty(camera.get_name(), cv2.WND_PROP_VISIBLE) > 0:
        if cv2.waitKey(100) > 0:
            break

    cv2.destroyAllWindows()
Answered By: Jop Knoppers

I made a simple function based on this post. It works in opencv 4.5.2

def wait_with_check_closing(win_name):
    """ 
        https://stackoverflow.com/questions/35003476/"
        "opencv-python-how-to-detect-if-a-window-is-closed/37881722
    """
    while True:
        keyCode = cv2.waitKey(50)
        if keyCode != -1:
            break
        win_prop = cv2.getWindowProperty(win_name, cv2.WND_PROP_VISIBLE)
        if win_prop <= 0:
            break


It can be used instead of cv2.waitKey(0) like following example.

# Usage
cv2.imshow(title, img_resized)
# cv2.waitKey(0)
wait_with_check_closing(title)
cv2.destroyAllWindows()
Answered By: Jaeyoon Jeong

https://www.programcreek.com/python/example/110676/cv2.WND_PROP_VISIBLE

For my scenario, it had to be the following. I had to call k = cv2.waitKey(1) & 0xFF before checking status of the window for it to work

def show_webcam(mirror=False):
    cam = cv2.VideoCapture(0)
    # cv2.startWindowThread()
    window_name="A_star webcam"
    while True:
        ret_val, img = cam.read()
        if mirror: 
            img = cv2.flip(img, 1)
        cv2.imshow(window_name, img)
        k = cv2.waitKey(1) & 0xFF 
        if not (cv2.getWindowProperty(window_name,cv2.WND_PROP_VISIBLE)):
            break
        
        if cv2.waitKey(1) == 27: 
            break  # esc to quit
     
    cv2.destroyAllWindows()

The libraries installed are

autopep8==1.6.0
numpy==1.22.1
opencv-python==4.5.5.62
pycodestyle==2.8.0
toml==0.10.2
Answered By: Ebrahim Karam

@David Kohen’s answer is working great for me. But if you have many images to show its better to convert it to a function

 def waitUntilX(window):
    while True:
        k = cv2.waitKey(100) # change the value from the original 0 (wait forever) to something appropriate
        if k == 27:
            print('ESC')
            cv2.destroyAllWindows()
            break        
        if cv2.getWindowProperty(window,cv2.WND_PROP_VISIBLE) < 1:        
            break        
    cv2.destroyAllWindows()

Usage

invertedmask = cv2.bitwise_not(mask)
cv2.imshow('inverted mask', invertedmask)
waitUntilX('inverted mask')
Answered By: mustafa candan
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.