[python][转载]tkinter opencv显示视频一闪一闪解决方法

Posted FL1623863129

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[python][转载]tkinter opencv显示视频一闪一闪解决方法相关的知识,希望对你有一定的参考价值。

我试图通过将opencv组件集成到程序中,在windows8上使用python3.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)

解决方案:确保在将图像存储在labelimage属性之前调用image configure。 我已经成功地解决了这个问题,但是我不完全理解它的工作原理,因为我是一个python/tkinter新手。我现在将发布解决方案,并在我设法找到对这种行为的适当解释时更新答案。我的最佳猜测是,将图像存储在label属性中实际上是导致它在屏幕上更新的原因,而configure方法只是声明将附加一个图像,这导致循环在到达update image update语句之前必须经历另一次迭代。以下代码工作正常,无闪烁:

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

在tkinter中,为了显示图像,图像需要有一个全局引用reference that doesn't go out of scope and then gets garbage-collected,可能是由于缺少这样的引用而引起的。请参见下面的代码,该代码具有对图像的此类引用,并且还放弃了具有更好结构的if/else

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

 

以上是关于[python][转载]tkinter opencv显示视频一闪一闪解决方法的主要内容,如果未能解决你的问题,请参考以下文章

python中,用tkinter模块写贪吃蛇

Python 内置界面开发框架 Tkinter入门篇 丙

PyQt图形程序设计 - 冒泡排序 - Python多线程

Python中的tkinter库简单案例详解

python tkinter与ttk

python [Python:Tkinter桌面开发] #python #tkinter #tk #desktop