OpenCV をビジュアルプログラミングできるアプリを Electron + Vue.js で作成

# 要約
Electron + Vue.js で、OpenCVをビジュアルプログラミング的に実行できるアプリ(仮称: [OpenCVFlow](https://github.com/ufield/opencvflow))を自分の勉強がてら作ってみました。
![top.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201540/676876e7-f37f-32fb-a8cb-e384034a5c65.gif)

上の動画のように、画像処理を定義したブロックを並べ、それをリンクでつなげることで、処理を順次実行して結果を確認、保存することができます。機能としてはそれほど多くなく、実用まではいかないかもしれませんが、なにか参考になれば幸いです。(個人的には、ElectronやVue.jsを本格的に使用するのは初めてでしたが、それなりに動くものが作れて満足しています。)

# 採用技術
- アプリケーションエンジン: [Electron](https://electronjs.org/)
- フロントエンドフレームワーク: [Vue.js](https://jp.vuejs.org/index.html)
- UIフレームワーク: [Photon](http://photonkit.com/)
- OpenCVライブラリ: [opencv4nodejs](https://www.npmjs.com/package/opencv4nodejs)
- デザインパターン: [アトミックデザイン](https://uxdaystokyo.com/articles/glossary/atomic-design/)

### アトミックデザインについて
今回は、UIを構築するためのデザインパターンとして、アトミックデザインを採用してみました。アトミックデザインの詳細については、他の記事を参照してください。アトミックデザインに基づいた設計・コーディングは初めてでしたが、Vue.jsの単一ファイルコンポーネントとの親和性がとてもよかったです。
#### Atoms・Molecules
本アプリでは、各種画像処理を定義する視覚的な要素として、下の図のようなものを採用し、"ブロック"と名付けました。
![block.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201540/1afd62a6-475c-c4ee-59aa-56a57b2a005c.png)
このブロックは、以下に示すようなさらに細かい要素を組み合わせて形成されており、この細かい要素1つ1つをAtom、ブロック1つをMoleculeと定義いたしました。
<img width="428" alt="atoms.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201540/637433ce-1556-ff12-4733-0c9b7fa8f61f.png">
ブロックの左側に伸びている線と付随する点は、"リンク"と名付けた別のMoleculeで定義しておりますので、ここでは除外します。

#### Organisms・Templates
Organisms・Templatesは、以下に示すように、アプリの左側の処理選択の領域、中央の処理のフローを組み立てるキャンバス領域、処理結果を表示する領域の1つ1つをOrganismとして定義し、それを組み合わせて1つのページのTemplateとしました。
<img width="861" alt="overview.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201540/f209630a-ac60-d3a0-0c3a-328545e166b3.png">

## 登録している画像処理の種類
現在、本アプリで実行できる画像処理の種類は以下のとおりです。どちらかというとGUI作成の練習をメインとして作成したので、処理の種類は多くありません。各種、詳細な画像処理については、[こちら](http://opencv.jp/cookbook/opencv_img.html)を参照してください。

* グレースケール
* 二値化
    * BINARY
    * TOZERO
    * OTSU
* フィルタ
    * Average
    * Gaussian
* 勾配・エッジ処理
    * Sobel
    * Laplacian
    * Canny

## GUI機能
GUIとして機能は以下のとおりです。

##### 処理対象の画像を入力
"File Input"ブロックをダブルクリックし、降りてくるダイアログで入力。 
![input_image.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201540/68714afe-8661-b0ef-f70c-7a71ab6de526.gif)

##### 処理の実行と保存
画像を入力し、各種ブロックをリンクで繋げると、"File Input"につながるブロックの上部に実行ボタンが表示されるので、クリックして実行できます。処理が終わったら、右側に処理結果が表示されますので、各処理結果のラベルをクリックすると、画像が保存できます。
![parameter_change.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201540/7c9479f4-ccff-b699-9184-1d6054d97a44.gif)

##### 処理のパラメータを変更
画像処理を定義している各種ブロック(グレースケール以外)をダブルクリックすると、処理のパラメータを変更するためのダイアログが表示されます。
![parameter_change.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201540/5cbb4095-55a2-9285-aead-2d39bb964691.gif)

##### 分岐の作成
一連の処理の途中で分岐を作成することが可能です。途中にフィルタ処理を入れて別の処理フローを定義するといったことに利用できます。分岐したブロックの実行ボタンを押すと、そのブロックから、"File Input"ブロックまでの一連のブロックが順に実行されます。別の分岐の処理は実行されません。
![branch.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201540/1cd0b3c5-22b8-6531-f1f2-26edb574eead.gif)

##### ブロックやリンクの削除
各種ブロックやリンクは、ポインタを合わせて右クリックをすることで削除することができます。誤った処理を繋いでしまった場合などに利用できます。
![remove.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201540/c81a9896-8fd8-e65f-e1ac-20180c58e2d5.gif)

# プロジェクトのインストール・実行・ビルド方法
opencv4node.jsとの依存関係のため、Node.jsのバージョンは8系にしてください。また、Macで開発しており、WindowsやLinux等での挙動は確認しておりません。クローンして、すぐに問題なくインストール&ビルドできるような環境にはならないかもしれませんが、ご了承ください。

OpenCVのインストール ([詳しくはこちらのページ](https://www.npmjs.com/package/opencv4nodejs))

```
brew update
brew install opencv@4
brew link --force opencv@4
```

opencv4nodejs インストールのための設定

```
export OPENCV4NODEJS_DISABLE_AUTOBUILD=1
```


プロジェクトインストール

```
npm install
```

開発向けの実行

```
npm run electron:serve
```

プロジェクトのビルド

```
npm run electron:build
```

# 終わりに
### 発展
さらに実用的なアプリとしていくためには、以下のようなことが必要になってくると思います。

* 画像処理の種類を増やす
* 作成したフローの保存とロード
* キャンバス領域をページングして切り替えられる

今のところ、これ以上手を加える予定はありませんが、気が向いたら機能を増やしていくかもしれません。

### 雑感
会社の勉強会で、ビジュアルプログラミング的にOpenCVで画像処理できるようなアプリを、各々作ってみようということになり、私は業務でフロントエンドまわりを中心にやっていたので、Web技術を使えるElectronをエンジンとして、Vue.jsをフロントエンドフレームワークとして採用しました。  
いずれも、本格的に触るのは初めてでしたが、ある程度使えるようになったので結果として満足しています。また、それなりに時間がかかりましたが、ちょっと触っただけではわからない、ある程度やり込むことによって理解できたことも多かったです。


# 補足
Mac OS Catalina では、数値パラメータの変更の際、入力領域右側の矢印を利用すると、変更が2倍されるという不具合が発生しています。これは、Chrome と Catalina の間の不具合で、最新のChormeではすでに解消されている事象ですが、テンプレートとして利用した electron-builder には反映されていないようでした。反映されたら、更新しておきたいと思います。