Unity で撮影したスクリーンショットを連続で Node-RED に送って画像表示するメモ

Unity で撮影したスクリーンショットを連続で Node-RED に送って画像表示するメモです。

画像を送る仕組みは以前のものを使う

Unity で撮影したスクリーンショットを Node-RED で受け取って画像保存するメモ

シンプルに 1 度だけ画像を Node-RED に送る仕組みはこちらでした。

こちらを連続して送って画像表示します。

Unity に Cube を準備

image

Unity に Cube を準備します。

Cube に CubeEvent.cs を割り当て

Cube に CubeEvent.cs を割り当てます。

Unity で CaptureScreenshotAsTexture を使って後加工しやすいスクリーンショットをするメモ

スクリーンショットのコード DoScreenShot を InvokeRepeating に渡せるように StartCoroutine(DoScreenShot()); を囲った処理 DoScreenShotCore を作っています。

コードは以下の通りです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class CubeEvent : MonoBehaviour
{
    // キャプチャされた画像データ
    byte[] dataImage;

    void Start()
    {
        // 連続実行にする
        InvokeRepeating("DoScreenShotCore", 1.0f, 1.0f);
    }

    // InvokeRepeating に渡せるように StartCoroutine(DoScreenShot()); を囲った処理 
    void DoScreenShotCore()
    {
        StartCoroutine(DoScreenShot());
    }

    IEnumerator DoScreenShot()
    {
        Debug.Log($"DoScreenShot");

        // レンダリング後に処理を開始
        yield return new WaitForEndOfFrame();

        // Texture2D でスクリーンショットを取得
        Texture2D textureScreenCapture = ScreenCapture.CaptureScreenshotAsTexture();

        // EncodeToJPG で JPEG に変換する。EncodeToPNG なら PNG に変換できる
        dataImage = textureScreenCapture.EncodeToJPG();

        Debug.Log($"撮影完了");
        Debug.Log($"{dataImage}");

        // textureScreenCapture を削除
        Destroy(textureScreenCapture);

        // 画像送信
        StartCoroutine(PostData());
    }

    IEnumerator PostData()
    {
        // IMultipartFormSection で multipart/form-data のデータとして送れます
        // https://docs.unity3d.com/ja/2018.4/Manual/UnityWebRequest-SendingForm.html
        // https://docs.unity3d.com/ja/2019.4/ScriptReference/Networking.IMultipartFormSection.html
        // https://docs.unity3d.com/ja/2020.3/ScriptReference/Networking.MultipartFormDataSection.html
        List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
        // 画像フォームで用意
        formData.Add(new MultipartFormFileSection("imageFile", dataImage, "01.jpg", "multipart/form-data"));

        // HTTP リクエストする(POST メソッド) UnityWebRequest を呼び出し
        // 第 2 引数で上記のフォームデータを割り当てて multipart/form-data のデータとして送ります
        UnityWebRequest request = UnityWebRequest.Post("http://localhost:1880/api/post/image", formData);

        // ダウンロード(サーバ→Unity)のハンドラを作成
        request.downloadHandler = new DownloadHandlerBuffer();

        // リクエスト開始
        yield return request.SendWebRequest();

        // 結果によって分岐
        switch (request.result)
        {
            case UnityWebRequest.Result.InProgress:
                Debug.Log("リクエスト中");
                break;

            case UnityWebRequest.Result.ProtocolError:
                Debug.Log("ProtocolError");
                Debug.Log(request.responseCode);
                Debug.Log(request.error);
                break;

            case UnityWebRequest.Result.ConnectionError:
                Debug.Log("ConnectionError");
                break;

            case UnityWebRequest.Result.Success:
                Debug.Log("リクエスト成功");

                // コンソールに表示
                Debug.Log($"responseData: {request.downloadHandler.text}");

                break;
        }


    }
}

node-red-contrib-image-output ノードインストール

image

画像を表示するために node-red-contrib-image-output (node) – Node-RED のノードをインストールします。

Node-RED のフローの作成

このデータを受け取る Node-RED の仕組みです。

image

このようなフローをつくります。 http in ノードから http response ノードにつながり、http in ノードから change ノード・node-red-contrib-image-output ノードでつないで受け取った画像を表示しています。

image

http in ノードのプロパティです。

image

http in ノードは multipart/form-data で画像を受け取るために「ファイルのアップロード」をチェックしておきます。 URL は /api/post/image にします。

image

http in ノードに change ノードをつなぎます。

image

change ノードのプロパティです。change ノードでは http in ノードで multipart/form-data で付与された画像データを受け取っています。

このように msg.req.files[0].buffer で送られてきた 1 つめの画像を取得しています。

image

change ノードに node-red-contrib-image-output ノードをつなぎます。

image

node-red-contrib-image-output ノードのプロパティは、そのままで OK です。

フロー JSON は以下の通りです。

[
    {
        "id": "f8aae4e3ce6f56d5",
        "type": "http in",
        "z": "2af3578e1e4de10b",
        "name": "",
        "url": "/api/post/image",
        "method": "post",
        "upload": true,
        "swaggerDoc": "",
        "x": 320,
        "y": 540,
        "wires": [
            [
                "d353b7ae8301b8d7",
                "feca9055b60c7e47"
            ]
        ]
    },
    {
        "id": "d353b7ae8301b8d7",
        "type": "change",
        "z": "2af3578e1e4de10b",
        "name": "buffer 取得",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "req.files[0].buffer",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 550,
        "y": 600,
        "wires": [
            [
                "8dd4c32aaebfd0e6"
            ]
        ]
    },
    {
        "id": "feca9055b60c7e47",
        "type": "http response",
        "z": "2af3578e1e4de10b",
        "name": "",
        "statusCode": "",
        "headers": {},
        "x": 530,
        "y": 540,
        "wires": []
    },
    {
        "id": "8dd4c32aaebfd0e6",
        "type": "image",
        "z": "2af3578e1e4de10b",
        "name": "",
        "width": 160,
        "data": "payload",
        "dataType": "msg",
        "thumbnail": false,
        "active": true,
        "pass": false,
        "outputs": 0,
        "x": 780,
        "y": 600,
        "wires": []
    }
]

動かしてみる

image

Unity で Play ボタンをクリックして動かしてみると、連続でスクリーンショットが撮影されて Node-RED に送られます。

image

Node-RED にデータが届き、データが届くたび node-red-contrib-image-output ノードで画像が表示されます。