DestroyWindow does not close window on Mac using Python and OpenCV

PythonUser InterfaceOpencv

Python Problem Overview


My program generates a series of windows using the following code:

def display(img, name, fun):
    global clicked
    
    cv.NamedWindow(name, 1)
    cv.ShowImage(name, img)
    cv.SetMouseCallback(name, fun, img)

    while cv.WaitKey(33) == -1:
        if clicked == 1:
            clicked = 0
            cv.ShowImage(name, img)
        
    cv.DestroyWindow(name)

I press "q" within the gui window to close it. However, the code continues to the next call of the display function and displays a second gui window while not closing the first. I'm using a Mac with OpenCV 2.1, running the program in Terminal. How can I close the gui windows? Thanks.

Python Solutions


Solution 1 - Python

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 - Python

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: https://stackoverflow.com/questions/7139968/trying-to-close-opencv-window-has-no-effect

Solution 3 - Python

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

Solution 4 - Python

Here is what worked for me:

cv2.namedWindow("image")
cv2.imshow('image', img)
cv2.waitKey(0) # close window when a key press is detected
cv2.destroyWindow('image')
cv2.waitKey(1)

Solution 5 - Python

This solution works for me (under Ubuntu 12.04 with python open in the shell):

Re-invoke cv.ShowImage after the window is 'destroyed'.

Solution 6 - Python

I solved the problem by calling cv2.waitKey(1) in a for loop, I don't know why it worked but gets my job done, so I didn't bother myself further.

for i in range(1,10):
    cv2.destroyAllWindows()
    cv2.waitkey(1)

you are welcome to explain.

Solution 7 - Python

If you are using Spyder ( Anaconda Package ) there is the problem.

None of the solutions worked for me. I discovered that the problem wasn't the functions, but a problem on Spyder really. Try to use a texteditor plus running on terminal and you be fine using simply:

WINDOW_NAME = "win"
image = cv.imread("foto.jpg", 0)
cv.namedWindow(WINDOW_NAME, cv.CV_WINDOW_AUTOSIZE)

cv.startWindowThread()

cv.imshow(WINDOW_NAME, image)
cv.waitKey()
cv.destroyAllWindows()

Solution 8 - Python

It seems that none of the above solutions worked for me if I run it on Jupyter Notebook (the window hangs when closing and you need to force quit Python to close the window).

I am on macOS High Sierra 10.13.4, Python 3.6.5, OpenCV 3.4.1.

The below code works if you run it as a .py file (source: https://www.learnopencv.com/read-write-and-display-a-video-using-opencv-cpp-python/). It opens the camera, records the video, closes the window successfully upon pressing 'q', and saves the video in .avi format.

import cv2
import numpy as np
 
# Create a VideoCapture object
cap = cv2.VideoCapture(0)
 
# Check if camera opened successfully
if (cap.isOpened() == False): 
  print("Unable to read camera feed")
 
# Default resolutions of the frame are obtained.The default resolutions are system dependent.
# We convert the resolutions from float to integer.
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
 
# Define the codec and create VideoWriter object.The output is stored in 'outpy.avi' file.
out = cv2.VideoWriter('outpy.avi',cv2.VideoWriter_fourcc('M','J','P','G'), 10, (frame_width,frame_height))
 
while(True):
  ret, frame = cap.read()
 
  if ret == True: 
     
    # Write the frame into the file 'output.avi'
    out.write(frame)
 
    # Display the resulting frame    
    cv2.imshow('frame',frame)
 
    # Press Q on keyboard to stop recording
    if cv2.waitKey(1) & 0xFF == ord('q'):
      break
 
  # Break the loop
  else:
    break 
 
# When everything done, release the video capture and video write objects
cap.release()
out.release()
 
# Closes all the frames
cv2.destroyAllWindows() 

Solution 9 - Python

Fiddling around with this issue in the python console I observed the following behavior:

  • issuing a cv2.imshow after cv2.destroyWindow sometimes closes the window. Albeit the old window pops up again with the next highgui call, e.g., cv2.namedWindow
  • the third call of cv2.waitKey after cv2.destroyWindow closed the window every time I tried. Additionally the closed window remained closed, even when using cv2.namedWindow afterwards

Hope this helps somebody.

(I used Ubuntu 12.10 with python 2.7.3 but OpenCV 2.4.2 from the 13.04 repos)

Solution 10 - Python

After searching aroung for some time, none of the solutions provided worked for me so since there's a bug in this function and I did not have time to fix it, I did not have to use the cv2 window to show the frames. Once a few frames have been saved, you can open the file in a different viewer, like VLC or MoviePlayer ( for linux ).

Here's how i did mine.

 import cv2

 threadDie = True # change this to false elsewhere to stop getting the video
 def getVideo(Message):
          print Message
          print "Opening url"
          video = cv2.VideoCapture("rtsp://username:passwordp@IpAddress:554/axis-media/media.amp")
  
          print "Opened url"
          fourcc = cv2.cv.CV_FOURCC('X','V','I','D')
          fps = 25.0 # or 30.0 for a better quality stream
          writer = cv2.VideoWriter('out.avi', fourcc,fps, (640,480),1)
          i = 0
  
          print "Reading frames "
          while threadDie:
                  ret, img = video.read()
                  print "frame number: ",i
                  i=i+1
                  writer.write(img)
          del(video)
    
  
          print "Finished capturing video"

Then open the file with a different viewer, prabably in a nother function, like if you like vlc, you can start it and pass the saved file as a parameter. On the terminal, i would do this

vlc out.avi #out.avi is my video file being saved by the function above.

This worked for me on arch linux.

Solution 11 - Python

I had the same issue. The problem is that while(cap.isOpened()): loop does not finish so that I added below structure. When video has no frame in the following part, it returns ret values as False. Normally, I put destroyAllWindows command out of loop but I moved it into the loop. It works in my code properly.

while(cap.isOpened()):
 ret, frame = cap.read()  
 if ret == False:
        cap.release()
        cv2.waitKey(1)
        cv2.destroyAllWindows()
        cv2.waitKey(1)

Solution 12 - Python

This worked for me in spyder :

import cv2 as cv
cv.namedWindow("image")
img = cv.imread("image_name.jpg")
cv.imshow("image",img)

cv.waitKey(5000) # 5 sec delay before image window closes
cv.destroyWindow("image")

Remember use only cv.waitKey(positive Integer) for this to work

Solution 13 - Python

cv2.imshow("the image I want to show ",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.waitKey(1)  # to close the window.

The above code worked well for me. I'm using Mac and python 3.7 .

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionArthurView Question on Stackoverflow
Solution 1 - PythonsusmitsView Answer on Stackoverflow
Solution 2 - PythonelaRoscaView Answer on Stackoverflow
Solution 3 - PythonJayView Answer on Stackoverflow
Solution 4 - PythonHassan AlshehriView Answer on Stackoverflow
Solution 5 - PythonMarco CentinView Answer on Stackoverflow
Solution 6 - Pythonsayem2603View Answer on Stackoverflow
Solution 7 - PythonMichelcycView Answer on Stackoverflow
Solution 8 - Pythonyl_lowView Answer on Stackoverflow
Solution 9 - PythonBrandlingoView Answer on Stackoverflow
Solution 10 - PythonTelewaView Answer on Stackoverflow
Solution 11 - PythonMehmet KazançView Answer on Stackoverflow
Solution 12 - PythonDinesh jainView Answer on Stackoverflow
Solution 13 - PythonBian View Answer on Stackoverflow