Flickering video in opencv-tkinter integration

后端 未结 2 1709
逝去的感伤
逝去的感伤 2021-01-16 08:20

I am trying to build a GUI using tkinter in python 3.6.4 64-bit on Windows 8 by integrating opencv components into the program. I can get the video to play, but there is sig

相关标签:
2条回答
  • 2021-01-16 08:54

    Solution: Make sure the image configure call precedes storing the image in the label image attribute. I've managed to solve this issue, however I don't fully understand WHY it works as I am a python/tkinter novice. I will post the solution for now and will update the answer when I manage to find a proper explanation to this behavior. My best guess is that the storing of the image in the label attribute is what actually causes it to update on the screen, while the configure method just declares that there will be an image attached, which causes the loop to have to go through another iteration before getting to the update image update statement. The below code works fine without flicker:

    from tkinter import *
    from PIL import Image, ImageTk
    import cv2
    import threading
    
    cap = cv2.VideoCapture(0)
    
    root = Tk()
    def videoLoop():
        global root
        global cap
        vidLabel = Label(root, anchor=NW)
        vidLabel.pack(expand=YES, fill=BOTH)
        while True:
            ret, frame = cap.read()
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            frame = Image.fromarray(frame)
            frame = ImageTk.PhotoImage(frame)
            vidLabel.configure(image=frame)
            vidLabel.image = frame
    
    videoThread = threading.Thread(target=videoLoop, args=())
    videoThread.start()
    root.mainloop()
    
    0 讨论(0)
  • 2021-01-16 09:12

    In tkinter in order to display images, the image needs to have a global reference reference that doesn't go out of scope and then gets garbage-collected, perhaps flickering is caused by lack of such reference. See below code that has such reference to the image, and also ditched the if/else with better structuring:

    from tkinter import *
    from PIL import Image, ImageTk
    import cv2
    import threading
    
    cap = cv2.VideoCapture(0)
    
    root = Tk()
    def videoLoop():
        global root
        global cap
        vidLabel = Label(root, anchor=NW)
        vidLabel.pack(expand=YES, fill=BOTH)
        while True:
            ret, frame = cap.read()
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            frame = Image.fromarray(frame)
            vidLabel.image = ImageTk.PhotoImage(frame)
            vidLabel.configure(image=vidLabel.image)
    
    videoThread = threading.Thread(target=videoLoop, args=())
    videoThread.start()
    root.mainloop()
    
    0 讨论(0)
提交回复
热议问题