NodeRed,NodeJSでOpenCVをGUIフロー式開発を!

 

{{DZ_TITLE}}
OpenCVをNodeRedのGUIでフロー式開発をする方法を紹介します。

目的

OpenCVでフィルタを画像を比較しつつ目的の結果を探したいと思いました。
そこでNodeRedを使ってみました。 結果画像サンプル

初めに結果から

  • そこそこ使いやすいように思います。
  • Pythonでnumpyで色々補助している部分が、NodeRedではどうやるのかな? 出来ても遅そうだな…。と感じています。
  • PythonのOpenCVに慣れているので、NodeRedのOpenCVの命令等少し戸惑いました。
    詳しくは、リファレンスマニュアルを参考にしてください。 https://justadudewhohacks.github.io/opencv4nodejs/docs/cv/
  • opencv4nodejsのインストール少し難しかったです。
  • knimeでpython動かす方が楽かもしれません。

使い方

ノード

左は自のパレットからノードを探して追加していきます。
結果画像サンプル

今回必要となるnodeは以下の4つです。
結果画像サンプル

  • inject
    プログラムを実行するトリガーになります。
  • image
    image表示用のnodeです。
    後述しますが、『node-red-contrib-image-output』がインストールされていないと表示されません。
  • function
    NodeJS(JavaScript)を実行するnodeです。
  • join
    複数の入力を1つにまとめるnodeです。

処理の実行

injectionノードの左側にある四角いボタンを押すと処理が開始します。

簡単なサンプル

画像を読み込んでHSVに変換するサンプル。
結果画像サンプル
NodeにInjection → Function → Function → Image と並べました。
1つ目のFunctionにもImageを追加しておきます。

Injection(画像ファイル名)

Injectionのプロパティを開き、msg.payload部分を編集します。 msg.payloadはタイムスタンプになっていると思います。
ここを文字列に変更して画像おファイル名を書いておきます。

Function(1つめ)

Injectionから繋がる、Functionを開き、コードタブに以下のようなコードを記載します。
payloadにはencodeして送ります。 形式は.jpgではなく劣化のない.pngが良いと思います。
node重ねるごとに劣化すると困るので。

const cv = global.get("cv");

const img = cv.imread(msg.payload);

msg.payload = cv.imencode('.png',img);

return msg;

Function(2つめ)

1つめのFunctionから渡ってきた画像を、HSVに変換します。
payloadから渡ってきているデータをdecodeして読み出します。

const cv = global.get("cv");

var img = cv.imdecode(msg.payload);

img = img.cvtColor(cv.COLOR_BGR2HSV);

msg.payload = cv.imencode('.png',img);

return msg;

Image

payloadに画像が入っているFunction Nodeに繋ぐことでFunction Node実行後に画像が表示されます。

複数の画像を入力にするサンプル (And演算等)

andやor等、複数画像を入力する場合、joinというnodeを使う必要があります。
今回の例ではAnd演算とします。
結果画像サンプル

joinの設定

  • joinに画像node 2つを入力します。
  • 動作を「手動」にする。
  • 出力を「配列」にする。
  • 結合は「msg.payload」 入力順番が関係ない場合「配列」が楽です。
    入力に順番に関係がある場合「key/valueオブジェクト」を使います。
    詳細は後述
  • 『指定数のメッセージパーツを受信後』は数量を2にします。
    もちろん、3つ以上の入力も可能です。

functionの設定

msg.payloadに配列として画像が渡ってきています。

const cv = global.get("cv");

var img1 = cv.imdecode(msg.payload[0]);
var img2 = cv.imdecode(msg.payload[1]);

var img = img1.bitwiseAnd(img2);

msg.payload = cv.imencode('.png',img);

return msg;

入力順番を意識して複数の画像を入力するjoinについて

上記の節ではjoinの順番を意識しなくて良い場合でした。
入力順番を意識する場合、リスト型ではなく、連想配列で受け取る方法がベストです。

入力のfuctionの工夫

それぞれの入力するfunctionのmsgにtopicにて名前を付けます。

msg.payload = cv.imencode('.png',img);
msg.topic = 'Topic.1';
return msg;
msg.payload = cv.imencode('.png',img);
msg.topic = 'Topic.2';
return msg;

joinの工夫

  • 動作は「手動」
  • 結合は「msg.payload」
  • 出力は『key/valueオブジェクト』
  • 使用する値は『msg.topic』になっていると思います。
  • 『指定数のメッセージパーツを受信後』は数量を2にします。
    もちろん、3つ以上の入力も可能です。

joinを入力とするfunctionの設定

以下の様にpayloadが連想配列になっていて、それぞれ画像を取り出せます。

const cv = global.get("cv");

var img1 = cv.imdecode(msg.payload['Topic.1']);
var img2 = cv.imdecode(msg.payload['Topic.2']);

インストール

今回はWindowsにインストールしました。
NodeJS版OpenCVことopencv4nodejsのインストールに、かなりインストール苦戦しました。
Visual Studio 2015が入っている場合コンパイルもできますが、入っていないならOpenCVのコンパイル済みの物を用意した方が良いです。
私の場合、Visual Studio 2019が入っていて、アンインストールしないとVisual Studio 2015を入れられないので、諦めてOpenCVのコンパイル済みの物を使いました。

NodeJSのインストール

https://nodejs.org/ja/download/

NodeRedのインストール

npm i node-red

OpenCVのインストール

以下からファイルをダウンロードして、フォルダに展開してください。
削除しないので、それっぽいフォルダに保存してください。
https://opencv.org/releases/

opencv4nodejインストール

OpenCVは D:\opencv に入れたと仮定して下記の様に作業をしました。
npm install に -gを付けるとglobalに、-gを付けないとカレントフォルダ下のnode_modulesにopencv4nodejsがインストールされます。 global領域はwindowsの場合は C:\Users(UserName)\AppData\Roaming\npm\node_modules です。

set OPENCV4NODEJS_DISABLE_AUTOBUILD=1

set OPENCV_LIB_DIR=D:\opencv\build\x64\vc15\lib

set OPENCV_INCLUDE_DIR=D:\opencv\build\include

npm install opencv4nodejs

コンパイル済みのOpenCVを使うため、 OPENCV4NODEJS_DISABLE_AUTOBUILDに1をセットして、自前でコンパイルしない設定にします。
OPENCV_LIB_DIRとOPENCV_INCLUDE_DIRでOpenCVのLibraryとIncludeフォルダがどこにあるか教えました。

設定ファイルの修正

NodeRedでNodeJSにインストールしたモジュールを使うように指定します。
C:\Users(User Name).node-reds\settings.js ファイルのfunctionGlobalContext項目にcv:require(‘opencv4nodejs’)を追加してください。
opencv4nodejs を cv と言う名前で読込みます。

    functionGlobalContext: {
        // os:require('os'),
        cv:require('opencv4nodejs')
    },

set NODE_PATH=D:\node_modules
set PATH=%PATH%;D:\node_modules

set NODE_PATH=C:\Users\(UserName)\AppData\Roaming\npm\node_modules\
set PATH=%PATH%;=C:\Users\(UserName)\AppData\Roaming\npm\node_modules\

D:\opencv\build\setup_vars_opencv4.cmd

実行方法

以下の様に起動します。
毎回入力するのは面倒だと思うので、バッチファイル作るか、環境変数をWindowsの設定に保存した法方が良いと思います。

; D:\直下に入れた場合
set NODE_PATH=D:\node_modules
set PATH=%PATH%;D:\node_modules

; OpenCVの設定を有効にする。
; D:\opencvにopencvを入れた場合
D:\opencv\build\setup_vars_opencv4.cmd

; NodeRed起動
node-red
; npm -g install でglobalに入れた場合
set NODE_PATH=C:\Users\(UserName)\AppData\Roaming\npm\node_modules\
set PATH=%PATH%;=C:\Users\(UserName)\AppData\Roaming\npm\node_modules\

; OpenCVの設定を有効にする。
; D:\opencvにopencvを入れた場合
D:\opencv\build\setup_vars_opencv4.cmd

; NodeRed起動
node-red

起動メッセージに下記の様にURLが表示されるので、ブラウザで開いてください。

1 May 11:41:51 - [info] Server now running at http://127.0.0.1:1880/

画像表示用のimageノードをパレットを追加  

『右上のΞ』 → 『パレット管理』
ユーザ設定画面が起動
『パレット』 → 『ノード追加』にて『node-red-contrib-image-output』を追加してください。

おすすめ記事

全国の町丁目レベル(189,540件)の住所データのオープンデータをPython Pandasで処理してみた
全国の町丁目レベル(189,540件)の住所データのオープンデータをPython Pandasで処理してみた
その他ネタもの - Python
その他ネタもの - Python
サーバー以外の端末から接続する方法(開発環境版向け、本番環境以外向け) - Django
サーバー以外の端末から接続する方法(開発環境版向け、本番環境以外向け) - Django
OpenCVで動画作成 VideoWriter - Python徹底解説
OpenCVで動画作成 VideoWriter - Python徹底解説
PythonでSeleniumでスクレイピング時にClickでElementClickInterceptedException例外で失敗する。
PythonでSeleniumでスクレイピング時にClickでElementClickInterceptedException例外で失敗する。
プログラムは独学が良いか、スクールが良いか?【無償カウンセリング、無料体験あり】
プログラムは独学が良いか、スクールが良いか?【無償カウンセリング、無料体験あり】
Supponsered

外部サイト
↓プログラムを学んでみたい場合、学習コースなどもおすすめです!

Comments

comments powered by Disqus