タンクとコマンドセンター間は無線LANで繋ぐので、ソケットを使って画像を転送する必要があります。Cでソケットプログラムを書くのは面倒ですが、pythonにはラッパークラスがあって比較的簡単にソケットプログラミングができます。
Webカメラで取得した画像の送信フローは以下のとおりです。
タンクはコマンドセンターから画像要求が来た場合に、Webカメラで取得した画像をJPEGに圧縮して送り返します。コマンドセンターでは受信した画像をデコードし、画面に表示します。受信しているデータはJPEGなので、そのままJPEGファイルとしてディスクに書き込むことも可能です。
SocketServerモジュールのサンプルコードを元に、BeagleBoneタンクで画像を取得し、コマンドセンターに転送するプログラムを作りました。例外処理等はしてませんが、一応動いています。タンク側はCtrl+cの強制終了でしか終わらないので行儀良いプログラムではありません。そのうち改良しようと思います。
はじめはOpenCV2.4から実装されているcv2.imencodeとcv2.imdecodeを使っていたのですが、BeagleBone側はOpenCV2.3だという事に気づき、エンコードにcv2.cv.EncodeImageを使用しています。OpenCV2.3のcv2.imencodeはSegmentation faultが出たので使うのをやめました。
まだ有線LANでしか実験していませんが、QVGAサイズの画像を1秒間に5枚程度は送受信できています。無線に変えても2〜3枚は送受信できるかな・・・?
BeagleBoneタンク側:
""" webcamera server for opencv 2.3 """ import SocketServer import cv2.cv as cv import numpy import socket import sys #for OpenCV2.3 python interface class TCPHandler(SocketServer.BaseRequestHandler): capture='' def handle(self): # self.request is the TCP socket connected to the client self.data = self.request.recv(1024).strip() print "%s connected:" % self.client_address[0] frame=cv.QueryFrame(capture) jpegstring=cv.EncodeImage('.jpeg',frame).tostring() print len(jpegstring) self.request.send(jpegstring) if __name__ == "__main__": HOST, PORT = '192.168.111.40', 12345 #init camera cameraid=0 capture=cv.CreateCameraCapture(0) cv.SetCaptureProperty(capture,cv.CV_CAP_PROP_FRAME_WIDTH,320) cv.SetCaptureProperty(capture,cv.CV_CAP_PROP_FRAME_HEIGHT,240) if not capture: print "Could not open camera" exit() server = SocketServer.TCPServer((HOST, PORT), TCPHandler) # Activate the server; this will keep running until you # interrupt the program with Ctrl-C server.capture=capture server.serve_forever()
コマンドセンター側
''' Image receiver for OpenCV 2.4 python interface ''' import socket import sys import numpy import cv2 # for opencv 2.4.2 HOST, PORT = "192.168.111.40", 12345 # Receive data from the server and shut down quitflag=False recvlen=1 def getImageFromServer(): sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) sock.connect((HOST,PORT)) sock.send('HELLO\n') recvlen=100 buffer='' while recvlen>0: receivedstr=sock.recv(1024*8) recvlen=len(receivedstr) buffer +=receivedstr print '%d bytes received' %len(buffer) narray=numpy.fromstring(buffer,dtype='uint8') decimg=cv2.imdecode(narray,1) sock.close() return decimg while 1: img=getImageFromServer() cv2.imshow('Capture',img) key=cv2.waitKey(100) if(int(key)>27): break img=''
※IPアドレスとポートは適当に読み替えてください。
次はソケットで操縦コマンドを送受信してGPIOを制御する部分を作ろうと思います。
ではまた。
0 件のコメント:
コメントを投稿