opencv-tkinter集成中的视频闪烁


问题内容

我正在尝试通过将opencv组件集成到程序中,在Windows 8上的python 3.6.4
64位中使用tkinter来构建GUI。我可以播放视频,但闪烁现象仍然很严重。即,与本机tkinter背景颜色相同的屏幕每秒会短暂显示几次。我已经测试了几台具有相似结果的摄像机,并再次检查了这些摄像机是否可以通过本机视频播放软件正常工作。这是我的代码:

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 = None
    while True:
        ret, frame = cap.read()
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        frame = Image.fromarray(frame)
        frame = ImageTk.PhotoImage(frame)
        if vidLabel: vidLabel.configure(image=frame)
        else:
            vidLabel = Label(root, image=frame, anchor=NW)
            vidLabel.pack(expand=YES, fill=BOTH)

videoThread = threading.Thread(target=videoLoop, args=())
videoThread.start()
root.mainloop()

有人可以建议我可能做错了吗?我确实听说过tkinter并不总是能很好地与线程配合使用,但这就是我能想到的全部。为了回应暗示闪烁是由标签更新引起的评论,我添加了一些仍从视频读取并在循环内更新标签的代码,但使用了循环外加载的图像来更新标签。然后闪烁消失了,尽管(据我所知)循环的效率和标签的更新没有改变。这是更改后的videoLoop函数(闪烁消失了):def
videoLoop():全局根vidLabel =无cap = cv2.VideoCapture(0)

    ret, frame = cap.read()
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    frame = Image.fromarray(frame)
    frame = ImageTk.PhotoImage(frame)

    while True:
        ret, lame = cap.read()
        lame = cv2.cvtColor(lame, cv2.COLOR_BGR2RGB)
        lame = Image.fromarray(lame)
        lame = ImageTk.PhotoImage(lame)

        if vidLabel:
            vidLabel.configure(image=None)
            vidLabel.configure(image=frame)
        else:
            vidLabel = Label(root, image=frame, anchor=NW)
            vidLabel.pack(expand=YES, fill=BOTH)

问题答案:

解决方案:确保图像配置调用先于将图像存储在标签image属性中。我已经设法解决了这个问题,但是由于我是python /
tkinter新手,所以我不完全理解为什么它能工作。我现在将发布解决方案,并在设法找到对此行为的适当解释时更新答案。我最好的猜测是,将图像存储在label属性中实际上是导致其在屏幕上更新的原因,而configure方法只是声明将附加一个图像,这导致循环必须进行另一次迭代在进入更新映像更新语句之前。下面的代码可以正常工作而不会闪烁:

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