Unityのカメラから他プロセスへ映像を転送する方法として、以下のような一般的なプロセス間通信が考えられる。
- MMAP
- ソケット通信
- RTSP
この記事ではこれらの方法を解説する。ただしRTSPはGStreamerのインストール方法ができなかったのでやっていない。
MMAP
MMAPはメモリ上にファイル等をマッピングし、表面上はファイルのやり取りではあるが、実際にはメモリ上でやり取りを行うプロセス間通信である。例えば書き込み側がIMGというファイルに画像を書き込み、読み込み側がIMGというファイルを読み込むことで、画像を読み込むことができる。これをMMAPを使用するとメモリ上でやり取りができ、高速な通信が可能となる。
送信側
コードは以下の通り。mmfというMemoryMappedFileにPNGエンコードした画像を書き込んでいる。MemoryMappedFileを作成する際のtag名は後ほど使う。
accessor = mmf.CreateViewAccessor(); RenderTexture.active = cam.targetTexture; tex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0); tex.Apply(); byte[] bytes = tex.EncodeToPNG(); accessor.WriteArray<byte>(0, bytes, 0, bytes.Length); accessor.Dispose();
スクリプト全文は以下。実際に使用する際は、そのままスクリプトを使用すればOK。
Linon_SDK/camera_mmap.cs at main · wooolwooolwoool/Linon_SDK · GitHub
受信側
受信側のPythonコードは以下の通り。tagnameは送信側と合わせる。
class MMAPCamera(): def __init__(self, tagname): self.mm = mmap.mmap(-1, 1024 * 1024 * 50, tagname) def read(self): self.mm.seek(0) mode = self.mm.read() ByteToImg = Image.open(io.BytesIO(mode)) return ByteToImg
コード全文は以下。
Linon_SDK/camera.py at main · wooolwooolwoool/Linon_SDK · GitHub
ソケット通信
ソケット通信ではデータをUDPやTCPで送信する。MMAPと違いネットワークを使用するため低速にはなってしまうものの、対向がネットワーク上にあればよいので別PC間での通信も可能となる。
送信側
送信側は以下の通り。先ほどデータを書き込んでいたのを、UDPで送信しているという違いだけである。あとソケット通信は低速なので、JPGエンコードにしてQualityを調整できるようにしてある。
byte[] bytes = tex.EncodeToJPG(quality);
udpClientSend.Send(bytes, bytes.Length);
スクリプト全体は以下の通り。
Linon_SDK/camere_udp.cs at main · wooolwooolwoool/Linon_SDK · GitHub
受信側
受信側のC++コードは以下の通り。受信データをOpenCVでデコードすればOK。
udp0.udp_recv(data, buf_size); std::vector<uchar> buf(data, data+buf_size); im = cv::imdecode(cv::Mat(buf), -1);
コード全体は以下の通り。ORB SLAM3に適当に組み込んだもの。
Linon_SDK/mono_inertial_euroc.cc at main · wooolwooolwoool/Linon_SDK · GitHub