Node.jsでOpenCVを使おう！　〜インストール編〜

Node.js　それはJavascriptであんな事やこんな事ができる素敵なプラットフォームですよね！
最近お仕事で「Node.jsでカメラ画像をとって、WebRTCに載せて発信する」という案件が出てきました

しかし、意外にNode.jsからカメラ画像を取得する用途に需要がないらしく、しっかり資料がまとまっていて扱いやすそうだったのがOpenCVくらいでした
それでも導入に詰まってしまったので備忘録がてらまとめていこうと思います

# Node.jsでカメラ画像を取得する時の選択肢
あまり選択肢的には多くありません。代表格として扱われている印象の強かった２つをあげておきます。

- [OpenCV4Nodejs](https://www.npmjs.com/package/opencv4nodejs)
- [node-webcam](https://www.npmjs.com/package/node-webcam)

タイトルにあるとおり、今回はOpenCVラッパーであるOpenCV4Nodejsを使用します。

# 準備／必要な物
インストール前に何が必要かを確認しましょう！
この記事で掲載するのは２０２０年１１月末の物なので、もしかしたらみなさんが使うときには変わってる可能性もありますが、
そこまで大きくは違わないはず！

- node-gyp (Node.js標準のものでよいみたい）
- Python 2.7 
- CMake

なお、Windowsの場合は

- windows-build-tools

も必要になります。

## インストールの選択肢
Opencv4Nodejsにはインストールに対して２つの選択肢があります。
この記事では２番目の一緒にインストールコースで説明します

- OpenCV本体をインストール後、Opencv4Nodejsを別にインストールする
    - 他のPJとかですでにOpenCVを使ってるから別にインストールしたくない場合はこっち
    - ただし、とってもめんどくさい上に問題が発生しまくりで成功しませんでした
    
- Opencv4Nodejsにバンドルされているのを一緒にインストール
    - 全自動でOpenCVのビルド等々をやってくれます。素敵
    - 一部`インストール（ビルド）時に干渉する`パッケージがあります。以下のものは事前にアンインストールしておくことをお勧めします
        - ffmpeg
        - tesseract
        - 上記２つのパッケージはOpencv4Nodejsインストール後であれば再インストール可能と思われる

# Nodeプロジェクトの作成
作りましょう

```
mkdir test
cd test
npm init
```

package.jsonができてれば一丁あがり♪

# opencv4nodejsのインストール実行
## インストールの前に
package.jsonに細工をする必要があると書かれているStackoverflowの記事とかもあるのですが
それは一緒にインストールコースでは不要です。
デフォルト設定でOpenCVの自動ビルド ＆ それを使う様に設定されるので無視しましょう〜

## npm install
```
npm install opencv4nodejs@5.2.0
```

コツはバージョンを指定してあげることです。5.4以上あたりからビルドに問題が出るらしくより安心できる５．２を使用しました

たくさんwarningやnoteが出て意味不明ですが、最後までいけてエラーと言われければおそらくOKです

# 成功しましたか？
きっと失敗します:innocent:
それくらい失敗率が高いです。
このへんを参考にしてみてください。

https://www.366service.com/jp/qa/cfbda42f824f4ed3c16004c872820b88

https://github.com/justadudewhohacks/opencv4nodejs/issues/645

https://github.com/justadudewhohacks/opencv4nodejs/issues/546

# 動作確認
インストールに成功してるのかどうかは、使ってみればわかります。
例えば以下のような簡単なプログラムをつくって数字がたくさん出てきていればOpencv４Nodejsはインストール成功していて
カメラ画像の取得ができています

```app.js
const cv = require('opencv4nodejs');
const wCap = new cv.VideoCapture(0);

setTimeout(function() {
  let frame = wCap.read();
  console.log(frame.getDataAsArray());
}, 2000)
```

もっと実感が欲しい方は以下のサイトを参考にしてみてください！
https://kokensha.xyz/javascript/yes-you-can-do-opencv-with-node-js-and-tensorflow/

# 余談：OpenCVと別でインストールについて
上の方で「問題が発生しまくりで成功しませんでした」としている方のお話。
失敗した要因的には２つあります

１つが「OpenCVへの参照」になぜか成功できなかったこと
package.jsonに以下の様なセクションを追加する必要があるのですが、そもそも何を設定すればいいのか正解を探し切れず、下記の様にbrewインストールディレクトリへの指定では`core.h`が見つからない！　みたいなエラーばかりで解消できませんでした
どなたか正解知ってる方いらっしゃいましたらコメントいただけると嬉しいです！

```package.json
{
  "name": "sample",
  "version": "1.0.0",
  "main": "app.js",
  ...
  "opencv4nodejs": {
    "disableAutoBuild": 1, <= 別にインストールコースでは１に、一緒にコースの場合は０に設定します
    "opencvIncludeDir": "/usr/local/opt/opencv@3/include/opencv",
    "opencvLibDir": "/usr/local/opt/opencv@3/lib",
    "opencvBinDir": "/usr/local/opt/opencv@3/bin"
  }
}
```

２つ目が「opencv_contrib」の存在
これも厄介です。
contribというのは特許その他ライセンス上の問題でOpenCV本体から分離された機能たちを指します。
opencv3nodejsでは、SHIFTと言うものをどこかで使っているらしくcontribのインストールが必要だった様です。

ただ、私はMacのbrewコマンドからインストールしていたのでcontribも一緒に入ってるはずらしかったのですが
解決できず諦めました。。。

# おわり
インストール編はこれで終わりです
私はこの後さらにnode-webrtc(wrtc)のフレームワークにOpenCVから取得した画像を載せて発信すると言うところまでやっていきます
「node-webrtcから画像を発信する」と言う分野もなかなかまとまった資料がなかったので備忘録しとして投稿する予定です
その時はぜひ読んでくださいね〜:hugging: