カメラキャプチャ画像をバイト列で送受信
前回、Socket通信でやりたいことがあった!!と記載しました。
elsammit-beginnerblg.hatenablog.com
それが、
”カメラキャプチャ画像をバイト列に変換して送信しストリーミング配信を行ってみる”
ことです。
無駄なことだと思いますが、どうしてもやってみたくて調べてみました!!
問題なく動作させることが出来たので、方法をまとめておこうと思います。
■環境
今回こちらの構成で動作させてみました!!

前回と同様、ネットワークサーバをRaspberry Pi側に構築し、クライアントをwindows PCを用いました。
今回はpythonを用いるのですが、バージョンはこちらの通りです。
・windows PC側Pythonバージョン:3.7.4
・Raspberry Pi側Pythonバージョン:3.7.3
またカメラですが、UCAM-C520FBBKを使用しました。
![]() | エレコム WEBカメラ マイク内蔵 200万画素 高精細ガラスレンズ ブラック UCAM-C520FBBK 新品価格 |
■サーバ側構築
ではまずはサーバ側の構築です。
全体のコードはこちらです。
import socketserver
import cv2
import numpy
import socket
import sys
class TCPHandler(socketserver.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
ret, frame=capture.read()
jpegstring=cv2.imencode('.jpg', frame)[1].tostring()
self.request.send(jpegstring)
#hostとportを設定
HOST = 'host名'
PORT = ポート番号
#カメラの設定
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
try:
server.serve_forever()
except KeyboardInterrupt:
pass
server.shutdown()
sys.exit()やっていることは、画像データをバイト列に変換し前回のsocket通信を実施しているのみです。
簡単には、
①データ受信により、TCPHandlerがコール
②画像データをバイト列に変換
jpegstring=cv2.imencode('.jpg', frame)[1].tostring() ③バイト列をレスポンス
self.request.send(jpegstring)
です。
■クライアント側構築
次にクライアント側の構築です。
コード全体はこちら。
import socket
import numpy
import cv2
def getimage():
#IPアドレスとポート番号は環境に応じて変更
HOST = '192.168.11.2'
PORT = 8080
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect((HOST,PORT))
sock.send(('a').encode("utf-8"))
buf=b''
recvlen=100
while recvlen>0:
receivedstr=sock.recv(1024)
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
HOST = 'ホスト名'
PORT = ポート番号
getimage()こちらもsocket通信とバイト列から画像データ変換の組み合わせです。
具体的には、
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect((HOST,PORT))
sock.send(('a').encode("utf-8")) でバイト列を要求し、
recvlen=100
while recvlen>0:
receivedstr=sock.recv(1024)
recvlen=len(receivedstr)
buf +=receivedstrにてバイト列を全て受信。
受信したバイト列を画像データに変換。
narray=numpy.fromstring(buf,dtype='uint8')
return cv2.imdecode(narray,1) 以上です。
■動作確認
こちらを動作させてみましたが、、、
う~~ん。。。
遅延が目立ちますね。。。
コードは320×240だったのですが、画像サイズを数倍拡大させると
より遅延が目立つようになりました!!
バイトサイズが大きくなるにつれて遅延が大きくなってしまうようですね!!
しかも、jpgからbmpにencodeを変換すると、
数秒の遅延が発生してしまい、ビデオとしては、、、使い物にならないですね😅
制御が単純で分わかりやすいのですが、ちょっと使うシーンは限定されてしまう気がします。
使うとしても制限を守った使い方が必要そうですね。。
