読者です 読者をやめる 読者になる 読者になる

kivantium活動日記

プログラムを使っていろいろやります

OpenCVでRaspberry Piから画像を転送する

Raspberry Piに接続したWebカメラからOpenCVを使ってインターネット経由で画像を転送する方法を紹介します。OpenCVが動く環境であればRaspberry Pi以外でも動作します。

準備

RaspbianをインストールしたRaspberry Pi上で

sudo apt-get install libopencv-dev python-opencv

OpenCV環境が整います。C++で書こうと思ったのですが、ライブラリの構成がおかしいのかコンパイルが通らないのでPythonで書きます。Raspberry PiにはUSB接続のWebカメラがつながっています。

なお、C++版のソースコードは以前書いたOpenCVでWebカメラのストリーミングを参考にしてください。

サーバー(Raspberry Pi側)

# -*- coding:utf-8 -*-
#!/usr/bin/python

import SocketServer  
import cv2
import numpy  
import socket  
import sys  
  
class TCPHandler(SocketServer.BaseRequestHandler):  
    capture=''  
    #リクエストを受け取るたびに呼ばれる関数
    def handle(self):  
        #HELLOを受け取ったらJPEG圧縮したカメラ画像を文字列にして送信
        self.data = self.request.recv(1024).strip()
        ret, frame=capture.read()
        jpegstring=cv2.cv.EncodeImage('.jpeg',cv2.cv.fromarray(frame)).tostring()  
        self.request.send(jpegstring)  
  
  
#環境に応じて変更
HOST = '192.168.100.101'
PORT = 12345  

#カメラの設定
capture=cv2.VideoCapture(0)
capture.set(3,320)
capture.set(4,240)
if not capture:  
    print "Could not open camera"  
    sys.exit()

SocketServer.TCPServer.allow_reuse_address = True
server = SocketServer.TCPServer((HOST, PORT), TCPHandler)  
server.capture=capture  
#^Cを押したときにソケットを閉じる
try:
    server.serve_forever()  
except KeyboardInterrupt:
    pass
server.shutdown()
sys.exit()

クライアント(PC)側

# -*- coding:utf-8 -*-
#!/usr/bin/python
import socket  
import numpy  
import cv2  

  
def getimage():
    #IPアドレスとポート番号は環境に応じて変更
    HOST = "192.168.100.101"
    PORT = 12345  
    sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)  
    sock.connect((HOST,PORT))   
    sock.send('HELLO\n')  
    buf=''   
    recvlen=100  
    while recvlen>0:  
        receivedstr=sock.recv(1024*8)  
        recvlen=len(receivedstr)  
        buf +=receivedstr  
    sock.close()  
    narray=numpy.fromstring(buf,dtype='uint8')  
    return cv2.imdecode(narray,1)  
  
while True:  
    img = getimage()
    cv2.imshow('Capture',img)  
    if cv2.waitKey(100) & 0xFF == ord('q'):
        break

結果

WimaxルーターのLAN環境で実験したところ、若干の遅れはありましたが秒単位ではなかったので実用上十分な速度でした。