TensorFlow.jsを用いた画像認識をNode-REDで行う手順

　こんにちは、(株)日立製作所 研究開発グループ サービスコンピューティング研究部の横井一仁です。

　今回は、[Node-RED](https://qiita.com/m-izumi/items/3f5a7a57274fe5a33b48)から[TensorFlow.js](https://qiita.com/yukagil/items/ca84c4bfcb47ac53af99)を用いて画像認識を行うフローをご紹介します。Node-REDが動くPCのカメラ画像やアップロードした画像に、何が映っているか(例えば、人物、犬、車、瓶など)を判定させてみます。

![imagerecognition.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/15fa3849-6825-abc8-0489-33510e3f78ba.png)

# Node-REDの事前設定
　今回は簡単にTensorFlow.jsを利用するため、[学習済みモデルが入ったTensorFlow.jsモジュール](https://www.npmjs.com/package/@codait/max-image-segmenter)をNode-REDのfunctionノードから呼び出してみます。functionノードで外部のnpmモジュールを利用する手順は、Node-REDの日本語サイトの[「追加モジュールのロード」のページ](https://nodered.jp/docs/user-guide/writing-functions#%E8%BF%BD%E5%8A%A0%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%AE%E3%83%AD%E3%83%BC%E3%83%89)が参考になります。

## (1) npmモジュールをインストール
　コマンドプロンプトを起動し、Node-REDのホームディレクトリ(Windowsの場合はC:\\Users\\<ユーザ名>\\.node-red)にて外部npmモジュール「max-image-segmenter」をインストールします。

```shell
cd
cd .node-red
npm install @codait/max-image-segmenter@0.1.4
```

　執筆時点の最新バージョンであるv0.1.12は仕様が変わり以降の手順で動作しないため、旧バージョンのv0.1.4を指定してください。

## (2) Node-REDの設定ファイルを編集

　Node-REDのホームディレクトリ(Windowsの場合はC:\\Users\\<ユーザ名>\\.node-red)の中にあるsettings.jsをテキストエディタで開き、216行目辺りのfunctionGlobalContextセクションの中に以下の定義を記載します。

```javascript
functionGlobalContext: {
    imageSegmenter: require('@codait/max-image-segmenter')
},
```

　これによってfunctionノードのグローバルコンテキスト経由で外部npmモジュールを呼び出すことができる様になります。

## (3) Node-REDを起動

　node-redコマンドでNode-REDを起動します。もし起動中の場合はCtrl+cで終了し、再度Node-REDを起動してください。

```shell
node-red
```

　Node-REDフローエディタ( http://\<Node-REDのIPアドレス\>:\<ポート番号\> )にアクセスすると、functionノード上でTensorFlow.jsモジュールを利用できる様になっています。

# 画像認識を行うフローを作成

## (1) 必要なノードをインストール

　Node-REDフローエディタから画像ファイルをアップロードしたり、カメラで撮影をしたりするため、[node-red-contrib-browser-utilsモジュール](https://flows.nodered.org/node/node-red-contrib-browser-utils)をインストールします。Node-REDフローエディタの右上のメニューから「設定」->「パレット」->「ノードを追加」を選択し、検索窓に「node-red-contrib-browser-utils」と入力してインストールしてください。

## (2) フローを作成

　file injectノード、functionノード、debugノードをワークスペース上に配置し、順にワイヤーで接続します。

![functionnodeflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/4149801f-bc95-b4f5-c637-7fec25c1b68f.png)

## (3) functionノードにコードを記載

　functionノードに下記のJavaScriptコードを記載します。このJavaScriptコードは、前のノードから受け取った画像のバイナリデータを外部npmモジュールに渡し、画像認識結果を後続のノードに渡す処理をしています。

- コード:

```javascript
var imageSegmenter = global.get('imageSegmenter');
imageSegmenter.predict(msg.payload).then(function (response) {
    msg.payload = response.objectsDetected;
    node.send(msg);
});
```

- 名前: image segmenter

　functionノードをライブラリに登録する際のトラブルを避けるため、名前は英数字と空白を用いた方が良いです。

![functionnodeproperty.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/0d5701f7-207c-a381-6766-f83cde6f659f.png)

　デプロイボタンを押した後、file injectノードの左側のボタンをクリックすると、画像ファイルをアップロードできるダイアログが表示されます。試しに、人物が写った画像をアップロードしてみると、デバッグタブに"person"と出力されました。

![result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/df5d2277-9b6d-0362-2ada-0aeec50a2b32.png)

　その他、犬や猫の画像をアップロードすると、正しく区別してデバックタブに"dog"や"cat"を出力してくれます。file injectノードの代わりにcameraノードを用いると、PCのカメラで撮影した画像を用いた画像認識もできますので、試してみてください。

# 最後に

　この様にNode-REDを用いて簡単に画像認識アプリを開発できました。今回ご紹介した手順の様にTensorFlow.jsを用いることで、Node-REDが搭載されているラズパイ等のデバイス上でエッジ分析ができる様になります。TensorFlowコミュニティでは、様々なモデルが公開されていますので、ぜひNode-REDと連携して遊んでみてください。