我正试图将我的摄像头馈送到GTK窗口中,并且我想保持按钮按下事件和运动通知事件的工作。
我已经找到了如何通过刷新Gtk中的图像来获取视频。图像,在GLib中。idle_add,尝试使用线程。线程,尝试使用GLib.timeout_add,但循环仍然阻止事件。我还尝试在虚拟环境中使用OpenCV无头。
标签:https://pygobject.readthedocs.io/en/latest/guide/threading.html
我不明白什么?有办法解决吗?
下面是我的(简化)代码:
import cv2
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gtk, GdkPixbuf
#import threading
vdo_url="http://my_cam/vdo.mjpg" # simplified, without security
class Cam_GTK(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Cam GTK")
self.capture = cv2.VideoCapture(vdo_url)
self.video = Gtk.Image.new()
self.video.connect("button-press-event", self.on_video_clicked )
self.video.connect("motion-notify-event", self.on_video_hover )
# Also tried with event=Gtk.EventBox.new(), event.add(self.video), then "connect"...
page_box = Gtk.Box( orientation=Gtk.Orientation.VERTICAL, spacing=1 )
page_box.pack_start( self.video, True, True, 0 )
self.add(page_box)
GLib.idle_add(self.show_frame)
#GLib.timeout_add(100, self.show_frame)
#tried to Thread(target=self.show_frame) w/out loop
self.connect("destroy", Gtk.main_quit)
self.show_all()
def on_video_hover( self, event, result ):
print("video hover")
def on_video_clicked( self, event, button ):
print("video clicked")
def show_frame(self):
ret, frame = self.capture.read()
#tried with a while
if ret:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
pb = GdkPixbuf.Pixbuf.new_from_data(frame.tobytes(),
GdkPixbuf.Colorspace.RGB,
False,
8,
frame.shape[1],
frame.shape[0],
frame.shape[2]*frame.shape[1])
self.video.set_from_pixbuf( pb.copy() )
return True #tried changed to False to stop loop
cam = Cam_GTK()
Gtk.main()
2条答案
按热度按时间jyztefdp1#
我回答自己:我找到了一个工作解决方案,耦合多个用途:
1.线程化非阻塞GLib.idle_add
1.使用Gtk.EventBox分隔事件调用
下面是工作代码(我认为它可能对有同样麻烦的人有用):
zfycwa2u2#
capture.read()
会阻塞直到有新的帧可用。这至少会将你的事件处理循环限制到视频源可以提供的任何帧速率。你不希望这样。您可能希望生成一个线程,该线程在循环中执行
capture.read()
,然后将新读取的帧发送到GUI,这将GUI事件处理与阅读视频完全分离。您还必须使用一些 * 消息传递 * 的风格。任何GUI函数的直接调用都可能会阻塞,因为它们可能会隐式地发布一些事件并等待它被处理.如果您当前执行的函数是由同一个事件循环执行的,那么就不会发生这种情况,该事件循环仍然在忙碌该函数,所以它不能做其他事情,但是你的API调用需要它来完成.所以这就是为什么它会阻塞。这对Qt(信号和插槽)是正确的,对GTK也是如此。
随机搜索结果,看起来很有希望:Signals and slots in GTK