2016-04-22 53 views
1

我想結合一個活的攝像頭飼料作爲窗口背景,同時控制相機的pan_tilt方向與鼠標指針懸停在圖像上。
我有兩個獨立工作的程序,第一個是pan_tilt控件,它使用一個叫做servo_control.py的pololu maestro8伺服控制器。第二個是webcam窗口和名爲test_servo_webcam3.py的pan_tilt的XY事件控件。蟒蛇伺服平移傾斜攝像頭圖像作爲背景

servo_control.py

#!/usr/bin/env python 

import serial 
import time 


class Servo: 

    def __init__(self): 
     self.ser = serial.Serial('/dev/ttyACM0') 
     self.ser.baudrate = 115200 
     self.ser.write(chr(0xAA)) 
     self.ser.flush() 
     self.centre_servo() 

    def centre_servo(self): 
     # tvalue is for every 1/4 us so 4000=1000us 
     # centre servos 
     self.ser.write(chr(0x84) + chr(0x00) + chr(0x70) + chr(0x2E)) 
     # 0x2E70 = 0b010.1110.111.0000 = 6000 -> 1500us = zero power 
     self.ser.flush() 
     self.ser.write(chr(0x84) + chr(0x01) + chr(0x70) + chr(0x2E)) 
     # 0x2E70 = 0b010.1110.111.0000 = 6000 -> 1500us = zero power 
     self.ser.flush() 

    def servo_track_XY(self, channel, XYvalue): 
     Xvalue = (XYvalue * 2) + 1000 
     if Xvalue < 1000: 
      Xvalue = 1000 
     if Xvalue > 2000: 
      Xvalue = 2000 
     #print "X, Y", Xvalue, Yvalue 
     Xvalue = round((Xvalue * 4), -1) 

     MSB = int(Xvalue/128) 
     LSB = int(Xvalue - (MSB * 128)) 
     xchannel = int(channel) 

     self.ser.flush() 
     self.ser.write(chr(0x84) + chr(xchannel) + chr(LSB) + chr(MSB)) 
     self.ser.flush() 

if __name__ == "__main__": 
    prog = Servo() 
    time.sleep(1) 
    for num in range(0, 500): 
     prog.servo_track_XY(0, num) 
     prog.servo_track_XY(1, num) 
     print num 
     time.sleep(0.02) 
    time.sleep(1) 
    prog.centre_servo() 

test_servo_webcam3.py

#!/usr/bin/python 

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

class Application(): 
    def __init__(self): 
     #...setup_window 
     window = gtk.Window(gtk.WINDOW_TOPLEVEL) 
     window.set_title("Webcam-Viewer") 
     window.set_default_size(500, 500) 
     window.connect("destroy", gtk.main_quit, "WM destroy") 
     vbox = gtk.VBox() 
     window.add(vbox) 
     self.movie_window = gtk.DrawingArea() 
     self.movie_window.connect("motion_notify_event", self.motion_notify_event) 
     self.movie_window.set_events(gtk.gdk.EXPOSURE_MASK 
          | gtk.gdk.LEAVE_NOTIFY_MASK 
          | gtk.gdk.BUTTON_PRESS_MASK 
          | gtk.gdk.POINTER_MOTION_MASK 
          | gtk.gdk.POINTER_MOTION_HINT_MASK) 
     vbox.add(self.movie_window) 
     hbox = gtk.HBox() 
     vbox.pack_start(hbox, False) 
     #hbox.set_border_width(10) 
     hbox.pack_start(gtk.Label()) 
     hbox.add(gtk.Label()) 
    #...button - centre 
     self.button1 = gtk.Button("Centre") 
     vbox.pack_start(self.button1, False) 
    #...button - start 
     self.button2 = gtk.Button("Start") 
     vbox.pack_start(self.button2, False) 
    #...button - quit 
     self.button3 = gtk.Button("Quit") 
     vbox.pack_start(self.button3, False) 
    #...connect_signals 
     self.movie_window.connect("motion_notify_event", self.motion_notify_event) 
     self.button1.connect("clicked", self.centre_servo) 
     self.button2.connect("clicked", self.start_stop) 
     self.button3.connect("clicked", self.exit) 

     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) 
     #...initialise 
     self.pan_tilt = servo_control.Servo() 
     gtk.gdk.threads_init() 
     gtk.main() 

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

    def exit(self, widget, data=None): 
     self.player.set_state(gst.STATE_NULL) 
     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.button2.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.button2.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) 

    def motion_notify_event(self, widget, event): 
     self.pan_tilt.servo_track_XY(0, event.x) 
     self.pan_tilt.servo_track_XY(1, event.y) 
     #print event.x, event.y 

    def centre_servo(self, widget, data=None): 
     self.pan_tilt.centre_servo() 

if __name__ == "__main__": 
    Application() 

test_servo_webcam3.py作爲被寫入將通過鼠標移動導入servo_control.py和控制攝像機的搖攝和傾斜在窗口。按start應顯示網絡攝像頭圖像,但網絡攝像頭圖像不顯示。

爲攝像頭圖像出現伺服控制必須像這樣註釋掉。

#self.pan_tilt = servo_control.Servo() 

我不明白爲什麼通過訪問servo_control文件沒有出現網絡攝像頭圖像。

+0

你應該嘗試這種減少到[MCVE。 – SiHa

回答

0

不確定這是您問題的原因,但是您的gtk.threads_init()gtk.main()語句錯誤。他們應該是你的Application()實例的兩側,而不是在類的定義:

if __name__ == "__main__": 
    gtk.gdk.threads_init() # Here, or immediately after the imports 
    Application() 
    gtk.main() 

這也許是因爲你這樣做:self.pan_tilt = servo_control.Servo() GTK之前,已初始化允許線程,它變得地方卡住了。

這就是說在Servo()裏似乎沒有什麼'thready',但是我從痛苦的經歷中知道,GTK可以是非常對線程的挑剔。

0

已解決。經過大量的搜索,我找到了答案。 'gst.parse_launch'需要一個Source來傳入一個傳遞給Sink的Filter。 'Source - > Filter - > Sink'。在我的程序中,過濾器丟失了。一旦添加了代碼功能。

所以更改此行

self.player = gst.parse_launch ("v4l2src ! autovideosink") 

這個

self.player = gst.parse_launch ("v4l2src ! video/x-raw-yuv,width=640,height=480,framerate=30/1 ! autovideosink") 

的SiHa,謝謝你們的意見