2010-06-29 33 views
5

I'working en este buen ejemplo que muestra una salida de cámara web en un widget GTK con el pitón y GStreamer:Python GStreamer cámara web espectador

http://pygstdocs.berlios.de/pygst-tutorial/webcam-viewer.html aquí está el código:

#!/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() 

lo que había Me gustaría tener un método para tomar una instantánea del fotograma actual y guardarlo en el disco. Creo que hay 2 maneras de hacerlo: - algún método gstreamer (pero yo creo que debería al menos modificar la tubería) - agarrar la imagen de alguna manera con GTK sí

Cualquier sugerencia al respecto? no tengo experiencia con gstreamer o GTK, cualquier ayuda es muy apreciada

Muchas gracias Mauro

Respuesta

5

Gracias a OpenCV he conseguido volver a escribir todo con wxPython (que sé mejor que pyGTK). Aquí hay un ejemplo completo de trabajo (¡con una instantánea!), Si alguien está interesado. también comprobación del OpenCV wiki aquí: 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() 
+6

usted no está respondiendo su propia pregunta .. – elmarco

2

Estoy bastante seguro de que usted podría hacer:

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

Para obtener una GtkImage con el último fotograma de la cámara web. El 500 y 400 es el ancho y el alto de la ventana.