anv*_*ice 3 python opencv tkinter python-3.x
我正在尝试通过将 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()
Run Code Online (Sandbox Code Playgroud)
谁能建议我可能做错了什么?我确实听说 Tkinter 并不总是能很好地处理线程,但这就是我能想到的全部。为了响应建议闪烁是由标签更新引起的评论,我添加了一些代码,这些代码仍然从视频中读取并更新循环内的标签,但使用循环外部加载的图像来更新标签。然后闪烁消失,尽管(据我理解)循环的效率和标签的更新没有改变。这是更改后的videoLoop
函数(闪烁消失了): 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)
Run Code Online (Sandbox Code Playgroud)
解决方案:确保图像配置调用先于将图像存储在标签image
属性中。我已经设法解决了这个问题,但是我不完全理解它为什么起作用,因为我是 python/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 = 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()
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3829 次 |
最近记录: |