首页 > 解决方案 > 在两个不同的 Windows tkinter python 上显示摄像机

问题描述

我有一个包含两个不同功能窗口的 GUI python 应用程序,我试图在 tkinter 应用程序的第二个窗口中显示摄像机。但是,视频帧总是显示在第一个窗口上!!不知道是线程问题还是相机库的问题。我的代码有什么问题吗?提前致谢。

# add the necessairy librairy
    import tkinter as tk
    import threading
    import time
    import subprocess
    from imutils.video import VideoStream
    import time
    import imutils
    import cv2
    import argparse
    from PIL import Image
    from PIL import ImageTk
    
    class PhotoBoothApp:
        def __init__(self,vs):
            # store the video stream object and output path, then initialize
            # the most recently read frame, thread for reading frames, and
            # the thread stop event
    
            self.vs = vs
            self.frame = None
            self.thread = None
            self.stopEvent_2 = None
    
            # initialize the root window and image panel
            self.root = tk.Tk()
            self.panel = None
            self.user_input = tk.StringVar(self.root)
            self.but_frame = tk.Frame(self.root)
            w = 800 # width for the Tk root
            h = 500 # height for the Tk root
            # get screen width and height
            ws = self.root.winfo_screenwidth() # width of the screen
            hs = self.root.winfo_screenheight() # height of the screen
            # calculate x and y coordinates for the Tk master window
            x = (ws/3) - (w/3)
            y = (hs/3) - (h/3)
            # set the dimensions of the screen 
            # and where it is placed
            self.root.geometry('%dx%d+%d+%d' % (w, h, x, y))
            # when open the second window i want it to be on toplevel; it means when i click outside the frame it won't get hide
            self.root.title("Test thread")
    
            # create a button, that when pressed, will take the current
            # frame and save it to file
            btn = tk.Button(self.but_frame, bd = '5',text=" photo ")
            
            self.but_frame.pack(side="left")
                    
            # start a thread that constantly pools the video sensor for
            # the most recently read frame
            self.stopEvent_2 = threading.Event()
            self.thread = threading.Thread(target=self.videoLoop, args=())
            self.thread.start()
    
            # set a callback to handle when the window is closed
            self.root.wm_protocol("WM_DELETE_WINDOW", self.onClose)

        def videoLoop(self):
            # DISCLAIMER:
            # I'm not a GUI developer, nor do I even pretend to be. This
            # try/except statement is a pretty ugly hack to get around
            # a RunTime error that Tkinter throws due to threading
    
            try:
                # keep looping over frames until we are instructed to stop
                while not self.stopEvent_2.is_set():
                    # grab the frame from the video stream and resize it to
                    # have a maximum width of 300 pixels
                    self.frame = self.vs.read()
                    self.frame = imutils.resize(self.frame, width=300)
    
                    #cv2.imshow('video player', self.frame) 
            
                    # OpenCV represents images in BGR order; however PIL
                    # represents images in RGB order, so we need to swap
                    # the channels, then convert to PIL and ImageTk format
                    image = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
                    image = Image.fromarray(image)
                    image = ImageTk.PhotoImage(image)
            
                    # if the panel is not None, we need to initialize it
                    if self.panel is None:
                        self.panel = tk.Label(image=image)
                        self.panel.image = image
                        self.panel.pack(side="left", padx=10, pady=10)
            
                    # otherwise, simply update the panel
                    else:
                        self.panel.configure(image=image)
                        self.panel.image = image
    
            except RuntimeError :
                print("[INFO] caught a RuntimeError_________________________________________")
    
        def onClose(self):
            # set the stop event, cleanup the camera, and allow the rest of
            # the quit process to continue
            print("[INFO] closing...")
            self.stopEvent_2.set()
            self.vs.stop()
            self.root.quit()
    
       
    # here's the main window
    Mafenetre = tk.Tk()
    #set main window title
    Mafenetre.title("GUI")
    Mafenetre['bg']='white' # couleur de fond
    # get screen width and height
    wf1= Mafenetre.winfo_screenwidth()
    hf1= Mafenetre.winfo_screenheight()
    A = str(wf1)
    B = str(hf1)
    # set the dimensions of the screen 
    # and where it is placed
    
    w = 500 # width for the Tk root
    h = 500 # height for the Tk root
    # get screen width and height
    ws = Mafenetre.winfo_screenwidth() # width of the screen
    hs = Mafenetre.winfo_screenheight() # height of the screen
    # calculate x and y coordinates for the Tk master window
    x = (ws/2) - (w/2)
    y = (hs/2) - (h/2)
    # set the dimensions of the screen 
    # and where it is placed
    Mafenetre.geometry('%dx%d+%d+%d' % (w, h, x, y))
    # add test button to the main window
    reglage = tk.Button(Mafenetre, bd = '5',text="  PARAM  ", bg='#c42034', fg='white',font= "Helvetica", 12))
    reglage.pack(side=tk.TOP, padx=6,pady=35)
    camera = VideoStream(0).start()
    pba = PhotoBoothApp(camera)
    Mafenetre.mainloop()

标签: python-3.xtkinter

解决方案


推荐阅读