DestroyWindow does not close window on Mac using Python and OpenCV

Solution 1:

There are a few peculiarities with the GUI in OpenCV. The destroyImage call fails to close a window (atleast under Linux, where the default backend was Gtk+ until 2.1.0) unless waitKey was called to pump the events. Adding a waitKey(1) call right after destroyWindow may work.

Even so, closing is not guaranteed; the the waitKey function is only intercepted if a window has focus, and so if the window didn't have focus at the time you invoked destroyWindow, chances are it'll stay visible till the next destroyWindow call.

I'm assuming this is a behaviour that stems from Gtk+; the function didn't give me any trouble when I used it under Windows.

Solution 2:

You need to run cv.startWindowThread() after opening the window. I had the same issue and now this works for me.

Hope this helps for future readers. And there is also a cv2 binding (I advise to use that instead of cv).

This code works for me:

import cv2 as cv
import time

WINDOW_NAME = "win"

image = cv.imread("ela.jpg", cv.CV_LOAD_IMAGE_COLOR)
cv.namedWindow(WINDOW_NAME, cv.CV_WINDOW_AUTOSIZE)
initialtime = time.time()

cv.startWindowThread()

while (time.time() - initialtime < 5):
  print "in first while"
cv.imshow(WINDOW_NAME, image)
cv.waitKey(1000)

cv.waitKey(1)
cv.destroyAllWindows()
cv.waitKey(1)

initialtime = time.time()
while (time.time() - initialtime < 6):
    print "in second while"

The same issue happens with the C++ version, on Linux: Trying to close OpenCV window has no effect

Solution 3:

Sayem2603

I tried your solution and it worked for me - thanks! I did some trial and error and discovered that looping 4 times did the trick for me... or posting the same code 4 times just the same..

Further, I drilled down to:

cv2.destroyAllWindows()
cv2.waitKey(1)
cv2.waitKey(1)
cv2.waitKey(1)
cv2.waitKey(1)

or simply calling DestroyAllWindows and then looping the waitKey() code 4 times:

cv2.destroyAllWindows()
for i in range (1,5):
    cv2.waitKey(1)

Worked as well. I am not savvy enough to know why this works exactly, though I assume it has something to do with the interruption and delay created by looping that code(?)

Matthäus Brandl said, above, that the third waitKey() worked for him, so perhaps it is slightly different on each system? (I am running Linux Mint with 3.16.1 kernel and python 2.7)

The delay, alone, doesn't explain it, as simply increasing the delay time on the waitKey() does not do the trick. (Also looped print("Hello") 1000 times instead of using wiatKey() just to see if the delay that created helped any - it did not.) Must have something more to do with how waitKey() interacts with window events.

OpenCV Docs say: "This function is the only method in HighGUI that can fetch and handle events, so it needs to be called periodically for normal event processing unless HighGUI is used within an environment that takes care of event processing."

Perhaps it creates an interrupt of sorts in the GUI display that allows the destroyAllWindows() action to process?

J