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
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()
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With