2015-09-02 298 views
3

我在寫一個需要在Tkinter窗口中顯示視頻流的程序。由於還會有按鈕來執行各種功能,因此我正在使用網格來組織所有事情。與Tkinter一起使用OpenCV

下面的代碼,從Show webcam sequence TkInter修飾,做工精細我的樹莓派:

import Tkinter as tk 
import cv2 
from PIL import Image, ImageTk 

width, height = 800, 600 
cap = cv2.VideoCapture(0) 

root = tk.Tk() 
lmain = tk.Label(root) 
lmain.pack() 

def show_frame(): 
    _, frame = cap.read() 
    frame = cv2.flip(frame, 1) 
    cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA) 
    img = Image.fromarray(cv2image) 
    imgtk = ImageTk.PhotoImage(image=img) 
    lmain.imgtk = imgtk 
    lmain.configure(image=imgtk) 
    lmain.after(10, show_frame) 

show_frame() 
root.mainloop() 

然而,與Tkinter的結合不起作用。 (在下文中,我試着註釋掉顯示1,顯示2,既不。)

import numpy as np 
import cv2 
import Tkinter as tk 
import Image, ImageTk 

#Set up GUI 
window = tk.Tk() #Makes main window 
window.wm_title("Digital Microscope") 
window.config(background="#FFFFFF") 

#Graphics window 
imageFrame = tk.Frame(window, width=600, height=500) 
imageFrame.grid(row=0, column=0, padx=10, pady=2) 

#Capture video frames 
lmain = tk.Label(imageFrame) 
cap = cv2.VideoCapture(0) 
def show_frame(): 
    _, frame = cap.read() 
    frame = cv2.flip(frame, 1) 
    cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA) 
    img = Image.fromarray(cv2image) 
    imgtk = ImageTk.PhotoImage(image=img) 
    lmain.imgtk = imgtk 
    lmain.configure(image=imgtk) 
    lmain.after(10, show_frame) 

tk.Label(imageFrame, image=show_frame()).grid(row=0, column=0, padx=10, pady=2) #Display 1 


#Slider window (slider controls stage position) 
sliderFrame = tk.Frame(window, width=600, height=100) 
sliderFrame.grid(row = 600, column=0, padx=10, pady=2) 


show_frame() #Display 2 
window.mainloop() #Starts GUI 

我怎樣才能獲得視頻在imageFrame顯示?

回答

11

這應該工作:

所有的
import numpy as np 
import cv2 
import Tkinter as tk 
import Image, ImageTk 

#Set up GUI 
window = tk.Tk() #Makes main window 
window.wm_title("Digital Microscope") 
window.config(background="#FFFFFF") 

#Graphics window 
imageFrame = tk.Frame(window, width=600, height=500) 
imageFrame.grid(row=0, column=0, padx=10, pady=2) 

#Capture video frames 
lmain = tk.Label(imageFrame) 
lmain.grid(row=0, column=0) 
cap = cv2.VideoCapture(0) 
def show_frame(): 
    _, frame = cap.read() 
    frame = cv2.flip(frame, 1) 
    cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA) 
    img = Image.fromarray(cv2image) 
    imgtk = ImageTk.PhotoImage(image=img) 
    lmain.imgtk = imgtk 
    lmain.configure(image=imgtk) 
    lmain.after(10, show_frame) 



#Slider window (slider controls stage position) 
sliderFrame = tk.Frame(window, width=600, height=100) 
sliderFrame.grid(row = 600, column=0, padx=10, pady=2) 


show_frame() #Display 2 
window.mainloop() #Starts GUI 

首先,你必須行tk.Label(imageFrame, image=show_frame()).grid(row=0, column=0, padx=10, pady=2),由於show_frame()不返回任何東西,你已經設置imageNone。其次,你需要確保你lmain.grid(),否則lmain不會顯示。

如果你想有兩個顯示器一個在另一個之上,你可以做這樣的事情:

import numpy as np 
import cv2 
import Tkinter as tk 
import Image, ImageTk 

#Set up GUI 
window = tk.Tk() #Makes main window 
window.wm_title("Digital Microscope") 
window.config(background="#FFFFFF") 

#Graphics window 
imageFrame = tk.Frame(window, width=600, height=500) 
imageFrame.grid(row=0, column=0, padx=10, pady=2) 

#Capture video frames 

cap = cv2.VideoCapture(0) 

def show_frame(): 
    _, frame = cap.read() 
    frame = cv2.flip(frame, 1) 
    cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA) 
    img = Image.fromarray(cv2image) 
    imgtk = ImageTk.PhotoImage(image=img) 
    display1.imgtk = imgtk #Shows frame for display 1 
    display1.configure(image=imgtk) 
    display2.imgtk = imgtk #Shows frame for display 2 
    display2.configure(image=imgtk) 
    window.after(10, show_frame) 

display1 = tk.Label(imageFrame) 
display1.grid(row=1, column=0, padx=10, pady=2) #Display 1 
display2 = tk.Label(imageFrame) 
display2.grid(row=0, column=0) #Display 2 

#Slider window (slider controls stage position) 
sliderFrame = tk.Frame(window, width=600, height=100) 
sliderFrame.grid(row = 600, column=0, padx=10, pady=2) 

show_frame() #Display 
window.mainloop() #Starts GUI 
+0

謝謝you.You是GENUIS! – Maham

0

試試這個代碼:

from PIL import Image, ImageTk 
import Tkinter as tk 
import argparse 
import datetime 
import cv2 
import os 

class Application: 
    def __init__(self, output_path = "./"): 
     """ Initialize application which uses OpenCV + Tkinter. It displays 
      a video stream in a Tkinter window and stores current snapshot on disk """ 
     self.vs = cv2.VideoCapture(0) # capture video frames, 0 is your default video camera 
     self.output_path = output_path # store output path 
     self.current_image = None # current image from the camera 

     self.root = tk.Tk() # initialize root window 
     self.root.title("PyImageSearch PhotoBooth") # set window title 
     # self.destructor function gets fired when the window is closed 
     self.root.protocol('WM_DELETE_WINDOW', self.destructor) 

     self.panel = tk.Label(self.root) # initialize image panel 
     self.panel.pack(padx=10, pady=10) 

     # create a button, that when pressed, will take the current frame and save it to file 
     btn = tk.Button(self.root, text="Snapshot!", command=self.take_snapshot) 
     btn.pack(fill="both", expand=True, padx=10, pady=10) 

     # start a self.video_loop that constantly pools the video sensor 
     # for the most recently read frame 
     self.video_loop() 

    def video_loop(self): 
     """ Get frame from the video stream and show it in Tkinter """ 
     ok, frame = self.vs.read() # read frame from video stream 
     if ok: # frame captured without any errors 
      cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA) # convert colors from BGR to RGBA 
      self.current_image = Image.fromarray(cv2image) # convert image for PIL 
      imgtk = ImageTk.PhotoImage(image=self.current_image) # convert image for tkinter 
      self.panel.imgtk = imgtk # anchor imgtk so it does not be deleted by garbage-collector 
      self.panel.config(image=imgtk) # show the image 
     self.root.after(30, self.video_loop) # call the same function after 30 milliseconds 

    def take_snapshot(self): 
     """ Take snapshot and save it to the file """ 
     ts = datetime.datetime.now() # grab the current timestamp 
     filename = "{}.jpg".format(ts.strftime("%Y-%m-%d_%H-%M-%S")) # construct filename 
     p = os.path.join(self.output_path, filename) # construct output path 
     self.current_image.save(p, "JPEG") # save image as jpeg file 
     print("[INFO] saved {}".format(filename)) 

    def destructor(self): 
     """ Destroy the root object and release all resources """ 
     print("[INFO] closing...") 
     self.root.destroy() 
     self.vs.release() # release web camera 
     cv2.destroyAllWindows() # it is not mandatory in this application 

# construct the argument parse and parse the arguments 
ap = argparse.ArgumentParser() 
ap.add_argument("-o", "--output", default="./", 
    help="path to output directory to store snapshots (default: current folder") 
args = vars(ap.parse_args()) 

# start the app 
print("[INFO] starting...") 
pba = Application(args["output"]) 
pba.root.mainloop() 
相關問題