调用destroyAllWindows()函数后opencv窗口没有关闭

时间:2016-11-27 11:43:21

标签: python opencv tkinter

我正在使用opencv在python中实现camshift算法,并使用它给出的位置来移动我的鼠标并在kolour应用程序上绘制。 当我按下tkinter ui上的按钮时,框架会启动然后再启动 按下“q”键后,“框架”不会关闭,框架会冻结,强制退出的选项会出现。我正在使用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()

3 个答案:

答案 0 :(得分:2)

这个问题有点陈旧但值得回答,因为它出现在搜索中。我遇到了同样的问题,最终找到了一个有效的答案。看起来很糟糕,但是允许opencv通过它的进程关闭窗口。 Opencv在waitKey()期间执行其处理,因此在destroyallwindows()函数之前和之后添加一些这样的技巧。

在您的代码中,

cv2.destroyAllWindows()

...试试这个。它对我有用。

# 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

答案 1 :(得分:1)

我不确定,cv可能会使用tkinter来显示窗口,因此root.mainloop()可能会保持窗口打开。您可以尝试结束root.mainloop()以关闭程序和所有窗口。

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()

答案 2 :(得分:1)

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