Python GStreamer 网络摄像头查看器

发布于 2024-09-08 00:07:08 字数 2704 浏览 2 评论 0原文

我正在研究这个很好的示例,它使用 python 和 GStreamer 显示 GTK 小部件中的网络摄像头输出:

http://pygstdocs.berlios.de/pygst-tutorial/webcam-viewer.html 这是代码:

#!/usr/bin/env python

import sys, os
import pygtk, gtk, gobject
import pygst
pygst.require("0.10")
import gst

class GTK_Main:

def __init__(self):
    window = gtk.Window(gtk.WINDOW_TOPLEVEL)
    window.set_title("Webcam-Viewer")
    window.set_default_size(500, 400)
    window.connect("destroy", gtk.main_quit, "WM destroy")
    vbox = gtk.VBox()
    window.add(vbox)
    self.movie_window = gtk.DrawingArea()
    vbox.add(self.movie_window)
    hbox = gtk.HBox()
    vbox.pack_start(hbox, False)
    hbox.set_border_width(10)
    hbox.pack_start(gtk.Label())
    self.button = gtk.Button("Start")
    self.button.connect("clicked", self.start_stop)
    hbox.pack_start(self.button, False)
    self.button2 = gtk.Button("Quit")
    self.button2.connect("clicked", self.exit)
    hbox.pack_start(self.button2, False)
    hbox.add(gtk.Label())
    window.show_all()

    # Set up the gstreamer pipeline
    self.player = gst.parse_launch ("v4l2src ! autovideosink")

    bus = self.player.get_bus()
    bus.add_signal_watch()
    bus.enable_sync_message_emission()
    bus.connect("message", self.on_message)
    bus.connect("sync-message::element", self.on_sync_message)

def start_stop(self, w):
    if self.button.get_label() == "Start":
        self.button.set_label("Stop")
        self.player.set_state(gst.STATE_PLAYING)
    else:
        self.player.set_state(gst.STATE_NULL)
        self.button.set_label("Start")

def exit(self, widget, data=None):
    gtk.main_quit()

def on_message(self, bus, message):
    t = message.type
    if t == gst.MESSAGE_EOS:
        self.player.set_state(gst.STATE_NULL)
        self.button.set_label("Start")
    elif t == gst.MESSAGE_ERROR:
        err, debug = message.parse_error()
        print "Error: %s" % err, debug
        self.player.set_state(gst.STATE_NULL)
        self.button.set_label("Start")

def on_sync_message(self, bus, message):
    if message.structure is None:
        return
    message_name = message.structure.get_name()
    if message_name == "prepare-xwindow-id":
        # Assign the viewport
        imagesink = message.src
        imagesink.set_property("force-aspect-ratio", True)
        imagesink.set_xwindow_id(self.movie_window.window.xid)

GTK_Main()
gtk.gdk.threads_init()
gtk.main()

我想做的是有一种方法来拍摄当前帧的快照并将其保存到磁盘。 我认为有两种方法可以做到这一点: - 一些 gstreamer 方法(但我认为我至少应该修改管道) - 以某种方式用 GTK 本身抓取图片

对此有任何提示吗? 我没有使用 gstreamer 或 gtk 的经验,非常感谢任何帮助,

非常感谢 毛罗

I'working on this nice example that shows a webcam output in a GTK widget with python and GStreamer:

http://pygstdocs.berlios.de/pygst-tutorial/webcam-viewer.html
here is the code:

#!/usr/bin/env python

import sys, os
import pygtk, gtk, gobject
import pygst
pygst.require("0.10")
import gst

class GTK_Main:

def __init__(self):
    window = gtk.Window(gtk.WINDOW_TOPLEVEL)
    window.set_title("Webcam-Viewer")
    window.set_default_size(500, 400)
    window.connect("destroy", gtk.main_quit, "WM destroy")
    vbox = gtk.VBox()
    window.add(vbox)
    self.movie_window = gtk.DrawingArea()
    vbox.add(self.movie_window)
    hbox = gtk.HBox()
    vbox.pack_start(hbox, False)
    hbox.set_border_width(10)
    hbox.pack_start(gtk.Label())
    self.button = gtk.Button("Start")
    self.button.connect("clicked", self.start_stop)
    hbox.pack_start(self.button, False)
    self.button2 = gtk.Button("Quit")
    self.button2.connect("clicked", self.exit)
    hbox.pack_start(self.button2, False)
    hbox.add(gtk.Label())
    window.show_all()

    # Set up the gstreamer pipeline
    self.player = gst.parse_launch ("v4l2src ! autovideosink")

    bus = self.player.get_bus()
    bus.add_signal_watch()
    bus.enable_sync_message_emission()
    bus.connect("message", self.on_message)
    bus.connect("sync-message::element", self.on_sync_message)

def start_stop(self, w):
    if self.button.get_label() == "Start":
        self.button.set_label("Stop")
        self.player.set_state(gst.STATE_PLAYING)
    else:
        self.player.set_state(gst.STATE_NULL)
        self.button.set_label("Start")

def exit(self, widget, data=None):
    gtk.main_quit()

def on_message(self, bus, message):
    t = message.type
    if t == gst.MESSAGE_EOS:
        self.player.set_state(gst.STATE_NULL)
        self.button.set_label("Start")
    elif t == gst.MESSAGE_ERROR:
        err, debug = message.parse_error()
        print "Error: %s" % err, debug
        self.player.set_state(gst.STATE_NULL)
        self.button.set_label("Start")

def on_sync_message(self, bus, message):
    if message.structure is None:
        return
    message_name = message.structure.get_name()
    if message_name == "prepare-xwindow-id":
        # Assign the viewport
        imagesink = message.src
        imagesink.set_property("force-aspect-ratio", True)
        imagesink.set_xwindow_id(self.movie_window.window.xid)

GTK_Main()
gtk.gdk.threads_init()
gtk.main()

What I'd like to do is have a method to take a snapshot of the current frame and save to disk.
I think there are 2 ways to do it:
- some gstreamer method (but i think I should at least modify the pipeline)
- grab the picture somehow with GTK itself

Any hint on this?
I have no experience with gstreamer or gtk, any help is really appreciated

Thanks a lot
Mauro

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

汐鸠 2024-09-15 00:07:08

感谢 OpenCV,我成功地用 wxPython 重写了所有内容(我比 pyGTK 更了解它)。如果有人感兴趣的话,这是一个完整的工作示例(带有快照!)。
另请在此处查看 OpenCV wiki:http://opencv.willowgarage.com/wiki/wxpython

import wx
import opencv.cv as cv
import opencv.highgui as gui


class CvMovieFrame(wx.Frame):
    TIMER_PLAY_ID = 101
    def __init__(self, parent):        

        wx.Frame.__init__(self, parent, -1,)        

        sizer = wx.BoxSizer(wx.VERTICAL)         

        self.capture = gui.cvCreateCameraCapture(0)
        frame = gui.cvQueryFrame(self.capture)
        cv.cvCvtColor(frame, frame, cv.CV_BGR2RGB)

        self.SetSize((frame.width + 300, frame.height + 100))

        self.bmp = wx.BitmapFromBuffer(frame.width, frame.height, frame.imageData)
        self.displayPanel= wx.StaticBitmap(self, -1, bitmap=self.bmp)
        sizer.Add(self.displayPanel, 0, wx.ALL, 10)

        self.shotbutton = wx.Button(self,-1, "Shot")
        sizer.Add(self.shotbutton,-1, wx.GROW)

        self.retrybutton = wx.Button(self,-1, "Retry")
        sizer.Add(self.retrybutton,-1, wx.GROW)     
        self.retrybutton.Hide()   

        #events
        self.Bind(wx.EVT_BUTTON, self.onShot, self.shotbutton)
        self.Bind(wx.EVT_BUTTON, self.onRetry, self.retrybutton)
        self.Bind(wx.EVT_PAINT, self.onPaint)
        self.Bind(wx.EVT_CLOSE, self.onClose)

        self.playTimer = wx.Timer(self, self.TIMER_PLAY_ID)
        wx.EVT_TIMER(self, self.TIMER_PLAY_ID, self.onNextFrame)

        self.fps = 8;
        self.SetSizer(sizer)
        sizer.Layout()
        self.startTimer()        

    def startTimer(self):
        if self.fps!=0: self.playTimer.Start(1000/self.fps)#every X ms
        else: self.playTimer.Start(1000/15)#assuming 15 fps        

    def onRetry(self, event):
        frame = gui.cvQueryFrame(self.capture)
        cv.cvCvtColor(frame, frame, cv.CV_BGR2RGB)
        self.bmp = wx.BitmapFromBuffer(frame.width, frame.height, frame.imageData)
        self.startTimer()
        self.shotbutton.Show()
        self.retrybutton.Hide()
        self.hasPicture = False
        self.Layout()
        event.Skip()    

    def onShot(self, event):
        frame = gui.cvQueryFrame(self.capture)
        self.playTimer.Stop()
        gui.cvSaveImage("foo.png", frame)        

        self.hasPicture = True
        self.shotbutton.Hide()
        self.retrybutton.Show()
        self.Layout()
        event.Skip()

    def onClose(self, event):
        try:
            self.playTimer.Stop()
        except:
            pass

        self.Show(False)
        self.Destroy()      

    def onPaint(self, evt):
        if self.bmp:
            self.displayPanel.SetBitmap(self.bmp)
        evt.Skip()

    def onNextFrame(self, evt):

        frame = gui.cvQueryFrame(self.capture)
        if frame:
            cv.cvCvtColor(frame, frame, cv.CV_BGR2RGB)
            self.bmp = wx.BitmapFromBuffer(frame.width, frame.height, frame.imageData)
            self.Refresh()        
        evt.Skip()

if __name__=="__main__":
    app = wx.App()
    f = CvMovieFrame(None)
    f.Centre()
    f.Show(True)
    app.MainLoop()

Thanks to OpenCV I managed to rewrite everything with wxPython (which i know better than pyGTK). Here is a full working example (whith snapshot!), if anyone interested.
Also checkout the OpenCV wiki here: http://opencv.willowgarage.com/wiki/wxpython

import wx
import opencv.cv as cv
import opencv.highgui as gui


class CvMovieFrame(wx.Frame):
    TIMER_PLAY_ID = 101
    def __init__(self, parent):        

        wx.Frame.__init__(self, parent, -1,)        

        sizer = wx.BoxSizer(wx.VERTICAL)         

        self.capture = gui.cvCreateCameraCapture(0)
        frame = gui.cvQueryFrame(self.capture)
        cv.cvCvtColor(frame, frame, cv.CV_BGR2RGB)

        self.SetSize((frame.width + 300, frame.height + 100))

        self.bmp = wx.BitmapFromBuffer(frame.width, frame.height, frame.imageData)
        self.displayPanel= wx.StaticBitmap(self, -1, bitmap=self.bmp)
        sizer.Add(self.displayPanel, 0, wx.ALL, 10)

        self.shotbutton = wx.Button(self,-1, "Shot")
        sizer.Add(self.shotbutton,-1, wx.GROW)

        self.retrybutton = wx.Button(self,-1, "Retry")
        sizer.Add(self.retrybutton,-1, wx.GROW)     
        self.retrybutton.Hide()   

        #events
        self.Bind(wx.EVT_BUTTON, self.onShot, self.shotbutton)
        self.Bind(wx.EVT_BUTTON, self.onRetry, self.retrybutton)
        self.Bind(wx.EVT_PAINT, self.onPaint)
        self.Bind(wx.EVT_CLOSE, self.onClose)

        self.playTimer = wx.Timer(self, self.TIMER_PLAY_ID)
        wx.EVT_TIMER(self, self.TIMER_PLAY_ID, self.onNextFrame)

        self.fps = 8;
        self.SetSizer(sizer)
        sizer.Layout()
        self.startTimer()        

    def startTimer(self):
        if self.fps!=0: self.playTimer.Start(1000/self.fps)#every X ms
        else: self.playTimer.Start(1000/15)#assuming 15 fps        

    def onRetry(self, event):
        frame = gui.cvQueryFrame(self.capture)
        cv.cvCvtColor(frame, frame, cv.CV_BGR2RGB)
        self.bmp = wx.BitmapFromBuffer(frame.width, frame.height, frame.imageData)
        self.startTimer()
        self.shotbutton.Show()
        self.retrybutton.Hide()
        self.hasPicture = False
        self.Layout()
        event.Skip()    

    def onShot(self, event):
        frame = gui.cvQueryFrame(self.capture)
        self.playTimer.Stop()
        gui.cvSaveImage("foo.png", frame)        

        self.hasPicture = True
        self.shotbutton.Hide()
        self.retrybutton.Show()
        self.Layout()
        event.Skip()

    def onClose(self, event):
        try:
            self.playTimer.Stop()
        except:
            pass

        self.Show(False)
        self.Destroy()      

    def onPaint(self, evt):
        if self.bmp:
            self.displayPanel.SetBitmap(self.bmp)
        evt.Skip()

    def onNextFrame(self, evt):

        frame = gui.cvQueryFrame(self.capture)
        if frame:
            cv.cvCvtColor(frame, frame, cv.CV_BGR2RGB)
            self.bmp = wx.BitmapFromBuffer(frame.width, frame.height, frame.imageData)
            self.Refresh()        
        evt.Skip()

if __name__=="__main__":
    app = wx.App()
    f = CvMovieFrame(None)
    f.Centre()
    f.Show(True)
    app.MainLoop()
夜雨飘雪 2024-09-15 00:07:08

我很确定你可以这样做:

self.movie_window.window.get_image(0, 0, 500, 400)

从网络摄像头获取带有最后一帧的 GtkImage 。 500和400是窗口的宽度和高度。

I'm pretty sure that you could do:

self.movie_window.window.get_image(0, 0, 500, 400)

To get a GtkImage with the last frame from the webcam. The 500 and 400 is the width and the height of the window.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文