ITの隊長のブログ

ITの隊長のブログです。Rubyを使って仕事しています。最近も色々やっているお(^ω^ = ^ω^)

Pythonでsocket通信UDPでnumpyのデータを送受信するためにやったこと

スポンサードリンク

雑メモ

  1. 送信するときに大きい画像とだとエラーになる場合がある。その場合はデータを分割して送りましょう
  2. 分割して送った場合、1つのデータがどこからどこまでなのか、受信側は判断する必要がある。今回のコードは任意の文字列で判断していますが、よく考えたら、プロトコルってbytes数とかで判断しているの多いからbytes数とかがいいと思った
import socket
import numpy as np
import cv2

udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
to_send_addr = ('127.0.0.1', 9999)

img = np.zeros([500, 500], np.uint)  # テスト画像作成
with closing(udp):
    jpg_str = cv2.imencode('.jpeg', img)

    # 画像を分割する
    for i in np.array_split(jpg_str[1], 10):
        # 画像の送信
        udp.sendto(i.tostring(), to_send_addr)

    # 1つのデータが終了したよを伝えるために判断できる文字列を送信する
    # -> チェックするなら送信する画像のbytes数のほうがいいと思った
    udp.sendto(b'__end__', to_send_addr)
    udp.close()

受信側

import socket
import numpy as np
import cv2


def recive(udp):
    buff = 1024 * 64
    while True:
        recive_data = bytes()
        while True:
            # 送られてくるデータが大きいので一度に受け取るデータ量を大きく設定
            jpg_str, addr = udp.recvfrom(buff)
            is_len = len(jpg_str) == 7
            is_end = jpg_str == b'__end__'
            if is_len and is_end: break
            recive_data += jpg_str

        if len(recive_data) == 0: continue

        # string型からnumpyを用いuint8に戻す
        narray = np.fromstring(recive_data, dtype='uint8')

        # uint8のデータを画像データに戻す
        img = cv2.imdecode(narray, 1)
        yield img


udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp.bind(('127.0.0.1', 9999))

# 画像を取り続ける
for img in recive(udp):
    # 送信された画像の処理を行う
    # ...

encode, decodeをOpenCVではなくて、pillowでできないか模索中