代码之家  ›  专栏  ›  技术社区  ›  Mauro Bianchi

Python GStreamer网络摄像头查看器

  •  5
  • Mauro Bianchi  · 技术社区  · 16 年前

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

    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的经验,非常感谢您的帮助

    谢谢

    2 回复  |  直到 16 年前
        1
  •  4
  •   Mauro Bianchi    16 年前

    多亏了OpenCV,我用wxPython重写了所有的东西(我比pyGTK更了解wxPython)。下面是一个完整的工作示例(带快照!),如果有人感兴趣。 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()
    
        2
  •  2
  •   Linus Unnebäck    15 年前

    我很肯定你能做到:

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

    从网络摄像头获取最后一帧的图像。500和400是窗户的宽度和高度。