简体   繁体   中英

opencv window not closing after calling destroyAllWindows() function

I am implementing camshift algorithm in python using opencv and using the position given by it to move my mouse and draw on the kolour application. When i press the button on in tkinter ui a frame launches and then Upon pressing the key 'q' the 'frame' does not close, The frame just freezes and the option to force quit comes. I am using tkinter for UI.

global paint_open
paint_open = 0

def func():

    global frame, roiPts, inputMode ,token

    camera = cv2.VideoCapture(0)

    cv2.namedWindow("frame")
    cv2.setMouseCallback("frame", selectROI)

    termination = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)
    roiBox = None
    li=[]

    while True:

        (grabbed, frame) = camera.read()

        if roiBox is not None:

            hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
            backProj = cv2.calcBackProject([hsv], [0], roiHist, [0, 180], 1) 

            (r, roiBox) = cv2.CamShift(backProj, roiBox, termination)
            pts = np.int0(cv2.cv.BoxPoints(r))
            li.append(pts)

            #coordinates contain the coordinates of the tracked object
            coordinates = r[0]
            # x, y contains the coordinates
            x = int(coordinates[0])
            y = int(coordinates[1])
            drawing(x,y)     

        #draws a circle around the center from x,y
        cv2.circle(frame, (int(x), int(y)), 4, (0, 0, 255), 2)


        #draws a colored frame around the object
        cv2.polylines(frame, [pts], True, (255, 0, 0), 2)

        #here imshow function start
        cv2.imshow("frame", frame)
        key = cv2.waitKey(1) & 0xFF


        # handle if the 'i' key is pressed, then go into ROI
        if key == ord("i") and len(roiPts) < 4:

            inputMode = True
            orig = frame.copy()

            while len(roiPts) < 4:
                cv2.imshow("frame", frame)
                cv2.waitKey(0)
                roiPts = np.array(roiPts)
                s = roiPts.sum(axis = 1)
                tl = roiPts[np.argmin(s)]
                br = roiPts[np.argmax(s)]


            roi = orig[tl[1]:br[1], tl[0]:br[0]]
            roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)



            roiHist = cv2.calcHist([roi], [0], None, [16], [0, 180])
            roiHist = cv2.normalize(roiHist, roiHist, 0, 255, cv2.NORM_MINMAX)
            roiBox = (tl[0], tl[1], br[0], br[1])

        # if the 'q' key is pressed, stop the loop
        elif key == ord("q"):
            break


    camera.release()
    cv2.destroyAllWindows()

def drawing(x,y):
    global paint_open
    if paint_open == 0:
        launchapp('kolourpaint')
        paint_open = 1
    py.dragTo(x,y)

def main():
    root=tk.Tk()
    bkgcolor='#D84315'
    root.configure(background=bkgcolor)

    label=tk.Label(root,text="Gesture Recognition Project",font=('arial black',12),fg="white",width=90,height=3,bg="purple")
    label.pack()

    frame1 = tk.Frame(root,bg=bkgcolor)
    frame1.pack(padx=205,pady=25)

    bframe1 = tk.Frame(root,bg=bkgcolor)
    bframe1.pack(side=tk.BOTTOM,padx=205)


    photo3 = tk.PhotoImage(file="3.png")



    button2 = tk.Button(frame1, width=255, height=255, image=photo3,text="Slide Presenter",fg="purple",bg="white",command=func)
    button2.pack(side=tk.LEFT,padx=25)
    button2.image = photo1





# start the event loop
root.mainloop()

This question is a bit old but worth answering, since it comes up in searches. I experienced the same problem and eventually found an answer that worked. It seems hack-ish, but allows opencv to go through its processes to close a window. Opencv performs its processing during the waitKey(), so adding a few of those before and after the destroyallwindows() function did the trick.

In your code, where it says

cv2.destroyAllWindows()

... try this instead. It worked for me.

# All these waitkeys are a hack to get the OpenCV window to close
cv2.waitKey(1)
cv2.destroyAllWindows()
for i in range (1,5):
    cv2.waitKey(1)
return

I'm not sure but cv may use tkinter to display windows so root.mainloop() may keep windows open. You can try to end root.mainloop() to close program and all windows.

import Tkinter as tk
import cv2

# create global value (with some value)
root = None

def func():
    # inform function to use global variable instead of local one
    global root

    # ...

    cv2.destroyAllWindows()
    camera.release()
    # close root window and leave mainloop()
    root.destroy()

def main():
    # inform function to use global variable instead of local one
    global root

    root = tk.Tk()

    # ...

    root.mainloop()

main()

由于调用destroyAllWindows()函数时会打开一个新窗口,因此您需要按空格键来关闭命令的执行。

This work for me

while True: 
    _, frame = cap.read()

    cv2.imshow(windowName, frame)
    keyCode = cv2.waitKey(1)

    if cv2.getWindowProperty(windowName, cv2.WND_PROP_VISIBLE) <1:
        break
cv2.destroyAllWindows()

from https://newbedev.com/closing-video-window-using-close-x-button-in-opencv-python

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM