opencv-tkinter集成中的视频闪烁 [英] Flickering video in opencv-tkinter integration

查看:389
本文介绍了opencv-tkinter集成中的视频闪烁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 significant flicker going on. Namely, a screen the same color as the native tkinter background shows up briefly several times a second. I've tested several cameras with similar results, and double-checked that the cameras work properly via native video playback software. Here is my code:

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)

Could anyone suggest what I might be doing wrong? I did hear that tkinter doesn't always play well with threads, but that's about all I can think of. In response to a comment suggesting the flicker is caused by label updating, I added some code that still reads from video and updates the label within the loop, but uses an image loaded outside of the loop to update the label. The flicker then goes away, although (to my understanding) the efficiency of the loop and updating of the label hasn't changed. Here is the changed videoLoop function (with flicker gone): def videoLoop(): global root vidLabel = None 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方法只是声明将附加一个图像,这导致循环不得不进行另一次迭代在进入更新映像更新语句之前.下面的代码可以正常工作而不会闪烁:

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

这篇关于opencv-tkinter集成中的视频闪烁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆