在 GTK 中线程化 OpenCV 视频并保留事件?

问题描述 投票:0回答:1

我正在尝试将相机输入 GTK 窗口, 我想保持按钮按下事件和动作通知事件事件正常工作。

我找到了如何通过刷新 Gtk.image 中的图像来获取视频, 在 GLib.idle_add 中,尝试使用 thread.Threading,尝试使用 GLib.timeout_add, 但循环仍然阻塞事件。 我还尝试在虚拟环境中使用 OpenCV-headless...

我读了它: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()

python multithreading opencv gtk3 glib
1个回答
0
投票

capture.read()
阻塞,直到有新的帧可用。这将至少限制你的事件处理循环。

您需要生成一个线程,在循环中执行

capture.read()
操作,然后将新读取的帧发送到您的 GUI。

© www.soinside.com 2019 - 2024. All rights reserved.