首页 > 解决方案 > 运动检测器 GUI

问题描述

我一直在尝试使用 tkinter 制作第 29 节中想到的运动检测器应用程序的 GUI,我希望它像,将有 4 个不同的按钮,4 个用于不同的框架,即 Delta 框架、灰度、彩色和阈值框架。我一直在尝试这个,但是当我这样做时。

按钮起作用,但它显示的帧始终是第一帧,它不会更新。

我的代码:

import tkinter
import cv2, time
from tkinter import *
from tkinter import ttk
 
top = tkinter.Tk()
 
first_frame=None
video=cv2.VideoCapture(0)
 
 
while True:
    check, frame = video.read()
 
    gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
    gray=cv2.GaussianBlur(gray,(21,21),0)
 
    if first_frame is None:
        first_frame=gray
        continue
 
    delta_frame=cv2.absdiff(first_frame,gray)
 
    thresh_delta=cv2.threshold(delta_frame, 30, 255, cv2.THRESH_BINARY)[1]
 
    thresh_delta=cv2.dilate(thresh_delta, None, iterations=2)
 
    (cnts,_) = cv2.findContours(thresh_delta.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
 
    for countour in cnts:
        if cv2.contourArea(countour) < 1000:
            continue
    
        (x, y, w, h) = cv2.boundingRect(countour)
        cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 3)    
 
    def Gray():
        cv2.imshow("Gray",gray)
    cv2.imshow("delta frame", delta_frame)
    cv2.imshow("Threshold Delta Frame", thresh_delta)
    cv2.imshow("Color Frame", frame)
 
    Button_Gray= tkinter.Button(top, text="Grayscale", command= Gray)
    Button_Gray.pack()
    top.mainloop()
   
    key=cv2.waitKey(1)
    print(gray)
 
    if key==ord("q"):
        break
 
 
video.realease()
cv2.destroyAllWindows

将不胜感激快速帮助!

问候 Gaurav SINGH

标签: python-3.xopencvuser-interfacetkinter

解决方案


您的代码将仅显示第一帧,因为top.mainloop()您需要找到一种方法来单独运行该 while 循环。

这可能是一个解决方案,但使用 tkinter 线程有时是一个坏主意,所以这可能不是最好的解决方案:

import tkinter
import cv2
import threading

show_gray = False
show_colored = False
show_thresh = False
show_delta = False
video=cv2.VideoCapture(0)

def Gray():
    global show_gray
    show_gray = not show_gray

def Colored():
    global show_colored
    show_colored = not show_colored
    
def Delta():
    global show_delta
    show_delta = not show_delta

def Threshold():
    global show_thresh
    show_thresh = not show_thresh

    
def stream_data():
    first_frame=None
    while True:
        check, frame = video.read()
     
        gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
        gray=cv2.GaussianBlur(gray,(21,21),0)
     
        if first_frame is None:
            first_frame=gray
            continue

        delta_frame=cv2.absdiff(first_frame,gray)
     
        thresh_delta=cv2.threshold(delta_frame, 30, 255, cv2.THRESH_BINARY)[1]
     
        thresh_delta=cv2.dilate(thresh_delta, None, iterations=2)
     
        (cnts,_) = cv2.findContours(thresh_delta.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
     
        for countour in cnts:
            if cv2.contourArea(countour) < 1000:
                continue
        
            (x, y, w, h) = cv2.boundingRect(countour)
            cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 3)    

        if show_gray:
            cv2.imshow("Grayscale frame", gray)
            
        if show_delta:
            cv2.imshow("delta frame", delta_frame)
            
        if show_thresh:
            cv2.imshow("Threshold Delta Frame", thresh_delta)
            
        if show_colored:
            cv2.imshow("Color Frame", frame)
       
        key=cv2.waitKey(1)
        # print(gray)
     
        if key==ord("q"):
            break
        
    video.release()
    cv2.destroyAllWindows()
    exit()
    
def main():
    top = tkinter.Tk()
    Button_Gray= tkinter.Button(top, text="Grayscale", command= Gray)
    Button_Gray.pack()
    colored= tkinter.Button(top, text="Colored", command= Colored)
    colored.pack()
    delta= tkinter.Button(top, text="Delta", command= Delta)
    delta.pack()
    thresh_delta = tkinter.Button(top, text="Threshold", command= Threshold)
    thresh_delta.pack()
    threading.Thread(target = stream_data, daemon = True).start()
    top.mainloop()

main()

此外,您不需要导入tkinter两次并且使用wildcard(*) 是一个坏主意。

也许这就是你需要的。

我想提一下 Christoph Rackwitz 的评论,混合 cv2 和 tkinter GUI 函数是个坏主意。


推荐阅读