TensorFlow.jsノードをNode-REDで使ってみる

日立製作所OSSソリューションセンタの横井です。今回は、画像認識を行うNode-REDのTensorflow.jsノードの使い方をご紹介します。

# Tensorflow.jsとNode-RED
 TensorFlow.jsとは、TensorFlowのJavaScript実装です。TensorFlow.jsを用いることで、ブラウザ上やサーバサイドのNode.jsで学習や推論処理をリアルタイムに実行できます。また、Node-REDは、主にIoT向けに開発されたピジュアルプログラミングツールです。[InfoQの記事](https://www.infoq.com/articles/javascript-web-development-trends-2020/)によると、2020年のトレンドとしてTensorlow.jsはEarly Majority、Node-REDはEarly Adoptersという流行っている/流行りつつあるOSSとして位置付けられています。

![infoq.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/f3a4942d-12bc-18ad-d582-2078e1c2da49.jpeg)

本記事では、これらトレンドの2つのOSSを組み合わせて何ができるか見てみましょう。

# 開発するフロー
本記事では、下のスクリーンショットの様な画像のどこに何が写っているか認識するフローを作成してみます。

<img width="1152" alt="flow2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/33f89efc-fd24-fd7c-6faf-e411b246725f.png">

このフローは、黄色のノード部品を用いてブラウザからファイルをアップロードすると、右下の「元の画像」のノードにアップロードした画像を表示します。同時に橙色の「画像認識」のノードにて、TensorFlow.jsの学習済モデルを用いて画像に何が写っているかを分析します。最後に、右上緑色の「認識結果出力」のノードを用いて右側のデパッグタブに写っている物の名前を表示します。同時に「認識結果付き画像」のノードの下に橙色の四角でアノテーションを付けた画像も表示してくれます。画像のどこの部分を認識したかが分かりやすいですね。

以降で、本フローの作成手順を説明します。今回の手順はローカル環境、[Raspberry Pi環境](https://qiita.com/utaani/items/7155c62d6c5e96822afb)、クラウド環境のNode-REDのどれを使っても動作します。ブラウザはNode-REDプロジェクトの[UI動作テスト](https://www.slideshare.net/nodered_ug_jp/current-status-and-future-trends-in-nodered/36)で用いられているGoogle Chromeが良いでしょう。

# Tensorflowノードをインストール
 Node-REDのフローサイトには、TensorFlowを利用できるノードが複数公開されています。その中でも、学習済のモデルが入った[node-red-contrib-tensorflow](https://flows.nodered.org/node/node-red-contrib-tensorflow)モジュールをインストールしてみます。Node-REDにTensorFlowノードをインストールするには、フローエディタの右上のメニュー -> 「パレットの管理」 -> 「パレット」 -> 「ノードを追加」と移動します。その後、検索キーワード入力欄に「node-red-contrib-tensorflow」と入力しましょう。

<img width="1078" alt="tensorflownode.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/9bc8f07a-09e5-7e60-532e-7c3616ae4bc1.png">

上の画像の様に、検索結果に今回用いるTensorFlow.jsノードが表示されるため、「インストール」ボタンをクリックしてTensorFlowノードをインストールします。インストールが完了すると、左側パレットの分析カテゴリの中に橙色のTensorFlow.jsノードが4つ登場します。

<img width="274" alt="palette.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/18ffd2c4-0710-3c3f-8536-a43571206fea.png">

各TensorFlow.jsノードの説明は以下の表の通りです。全て画像認識を行うノードですが、画像認識の機能以外にも認識結果付きの画像データを生成したり、エッジ分析で必要となるオフラインでの利用ができたりする等の違いがあります。

| # |名前      |説明             | 認識結果付き画像 | オフライン利用 |
|:-:|:-------:|:---------------------------------:|:-:|:---:|
| 1 |cocossd  |画像に写っている物体名を返すノード          |有り|可能|
| 2 |handpose |手の画像から指や関節の位置を推定するノード   |無し|不可|
| 3 |mobilenet|画像に写っている物体名を返すノード          |無し|可能|
| 4 |posenet  |人物の画像から腕や頭、足の位置を推定するノード|有り|可能|

その他、Node-REDで画像データを扱うために必要な以下のノードも同じ手順でインストールしておきます。

- [node-red-contrib-browser-utils](https://flows.nodered.org/node/node-red-contrib-browser-utils) : フローエディタ上から画像ファイルや音声ファイルをアップロードするノード
- [node-red-contrib-image-output](https://flows.nodered.org/node/node-red-contrib-image-output) : フローエディタ上に画像を表示するノード

node-red-contrib-browser-utilsのインストールが終わると、入力カテゴリの中にfile-injectノード、microphoneノード、cameraノードが入っているはずです。また、node-red-contrib-image-outputのインストールが完了すると、出力カテゴリの中にimageノードが表示されていると思います。

# フローを作成
必要なノードを準備できたため、早速フローを開発してみましょう。
右側のパレットから黄色のfile injectノード、橙色のcocossdノード、緑色のdebugノード(ワークスペースに配置すると、msg.payloadという名前に変わります)を配置し、各ノードの端子をワイヤーで接続します。ワイヤーを流れている画像データを確認するため、2つのimageノード(ワークスペース上に置くとimage previewという名前になります)をフローの下へ配置し、それぞれfile injectノードの出力端子、debugノードの入力端子に接続します。

<img width="1113" alt="flow1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/92507a32-e18b-9774-ca82-1598330606a9.png">

右側のimage previewノードのみは、表示する画像データの変数を指定するため、ノードの設定を変更する必要があります。設定を変更するには、image previewノードをダブルクリックしてノードプロパティ画面を開きます。ノードプロパティ画面では、デフォルトではmsg.payloadに入っている画像データを表示する様になっています。これを以下のスクリーンショットの様に、msg.annotatedInputに変更することで、cocossdノードがアノテーションを付けた画像を表示できる様になります。

<img width="778" alt="image_preview_node.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/897695e2-e3fa-7b00-fb43-91d4e9c450b7.png">

各ノードに適切な名前を付けて右上の赤いデプロイボタンを押した後、file injectノードの左側のボタンをクリックして、ローカルPCにある空港の画像ファイルをアップロードしてみましょう。

<img width="1152" alt="flow2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/33f89efc-fd24-fd7c-6faf-e411b246725f.png">

「認識結果付き画像」のノードの下に機体に対して橙色のアノテーションが着いた画像が表示されました。また、右側のデバッグタブには、正しく「airplane(飛行機)」と表示されました。ぜひ手元にある画像をアップロードして、正しく認識できるか遊んでみてください。

# 最後に
今回は、cocossdというTensorFlow.jsノードをご紹介しました。その他のノードについてもほぼ同様のフロー作成手順で画像認識を行うことができます。本フローの応用例については、[次回の記事](https://qiita.com/kazuhitoyokoi/items/b79ce8e3f0f695c36e1f)で紹介してゆこうと思います。

※ 本記事はThe Linux FoundationのサイトLinux.comに投稿した下記記事の和訳です。
https://www.linux.com/news/using-tensorflow-js-and-node-red-with-image-recognition-applications/

※ 本記事で紹介したTensorFlowノードがNode-RED開発者のハンズオンドキュメントでも紹介されました！
https://knolleary.net/node-red-workshop-photobooth/part3/index.html#node-red-contrib-tensorflow