JavaScript
OpenCV
Emscripten
OpenCVDay 23

OpenCV.js をちょっとだけ試してみた。

この記事はOpenCV Advent Calendar 2017の23日目の記事です。他の記事は目次にまとめられています。

この話のオチ

Web上でアプリケーションを開発するツール・ライブラリもいろいろありますが、JavaScriptで動作する画像解析ライブラリとしてOpenCVが活用できるようになりました!

単純な色変換のみならず、Webカメラからの入力・表示をはじめとして、様々な機能が使えるようになっています。

2018年は、もっと身近に、コンピュータビジョンが使える時代になりそうですね!

はじめに

OpenCVアプリケーションを作るときの課題の1つに、ポータビリティがあります。GUIとして共通化できるhighguiモジュールがあってもWindows, MacOS, Android, iOS それぞれのプラットフォームで動かすためには、それなりの苦労が必要。多様なクライアントに対応するには、コンパイルとデプロイは各環境に必要になるので、なかなか面倒。これはどうにかしたい。

しかし、画像処理部をサーバーに集約させると、画像データ処理するためだけに大量のアップロードが必要になってしまう。これも良くない。クラウドの使用料も膨大になり、セキュリティ的にも・・・・。ローカルに画像処理が実行できる必要がありますね!

こういう事を踏まえると、前処理なら、JavaScriptで組んで全プラットフォーム共通にしたくなりますよね! むしろ、なってください!ということで、OpenCV 3.3.1で導入された、OpenCV.jsのお話です。

実現方法は?

本家のドキュメントにも詳しく書いていますが、図にするとこういうイメージです。

image.png

従来は、OpenCVのソースコードは、コンパイラ(例えばGCC)でライブラリにコンパイル・リンクされていました。これに対して、LLVMフロントエンドであるclangによってLLVM bitcode(中間コード)に変換し、これをEmscriptenでJavaScriptコードにコンパイルしたのが、OpenCV.jsとなります。なお、実際に動かす場合には、asm.js/WebAssemblyなどを使って高速処理できるようになっている、とのことです。

OpenCV.jsの入手元は?

公式に配布されていないので、探せば見つかりますが…頑張りましょう!(Releases に欲しいなあ)

OpenCV.jsの作り方

本家マニュアル の手順に従って、Ubuntuで作業したらできます。コンフィギュレーションはこんな感じで、core/imgproc/objdetect/video/jsしか対象にならない…。

image.png

core i7 の4770 8コアでぶん回しで、これくらい。
image.png

OpenCV.jsの使い方

OpenCVを使ったことがある人ならば、非常に簡単に始められます!例えば、画像を2値化する例はこうなります。

let src = cv.imread('canvasInput');
let dst = new cv.Mat();
// You can try more different parameters
cv.threshold(src, dst, 177, 200, cv.THRESH_BINARY);
cv.imshow('canvasOutput', dst);
src.delete();
dst.delete();

ポイント

src.delete() ってあるけど、勝手に消してくれないの?と感じた方がいるかもしれません。これを補足しますとECMA-262 Edition 5.1では、finalizers/weak references with callbacksがサポートされていないので、EmscriptenはC++オブジェクトのdestructorを自動的に呼び出せない、とのことですね。そのため、利用したMatオブジェクトは手動で削除する必要があります。

Note
You have to call delete method of cv.Mat to free memory allocated in Emscripten's heap. Please refer to Memeory management of Emscripten for details.

どんな機能が使えるの?

GUI Feature

  • HTML5 Canvasからの画像読み込み・書き込み
  • カメラからの動画フレームの読み込み(表示はCanvasで)
  • トラックバーの追加

Core Operations

  • 基本的なMatオブジェクト操作(構築、複製、フォーマット変換、etc...)
  • 算術処理(加法、減法、ビット操作などなど)

Image Processing

  • 色空間変換
  • 形状変換
  • 2値化
  • スムージング
  • モーフィング
  • エッジ抽出 etc...

Video Analysis

  • Meanshift/Camshift
  • Optical Flow
  • Background Subtraction

Object Detection

- Face Detection

そして、JavaScript bindings for dnn moduleと、夢は広がりまくりですね!

現状の問題点

OpenCV.jsが配布されていない。

これが一番大きい問題ですね……。node.jsやらVue.jsやらであれば公式リリースがあるのですが、OpenCV.jsはまだ配布されていないのか、配布場所が分かりにくいのか、見つからないです。

「使いたい」と思ったときに、すぐ使えないことは機会損失にもつながります。やはりここは、OpenCV.jsの公式配布を希望したいですね!

OpenCV.jsが巨大すぎる

私の手元で作成したものでも6MBあります。初回ダウンロード時のみ必要になるとはいえ、やはりこれでは…。

アプリケーション側が参照していない関数を削除するなどして、OpenCV.jsをシュリンクする機能が必要になるかもしれません。あるいは、OpenCV.jsがメインルーチンをロードした後、機能が呼ばれるたびに必要なサブjsを読みだす仕組み、などなど。

重たい処理の進捗不明

重たい処理をしているときに、OpenCV側ががっつりCPU/メモリをもっていってしまうので、やはりこの部分については何かしらシステムにフィードバックできる仕組みが必要になる気がします。

例えば、100ms以上OpenCV側が処理から応答がない場合には、イベントが発行するような仕組み、などなど。

特徴量抽出あたりが早くほしい

ほしいです!というのは、画像特徴量だけをやりとりするようにできれば、例えば個人情報なども除去した状態でのやり取りになるので、非常に扱いやすくなります!

明日は、tomoaki_teshima さんの投稿で、執筆時点でのタイトルは 「去年書いた浮動小数点数の精度問題のネタ」 です!組込大好き人間としては気になります(IAとARMで泣かされた……)よろしくお願いいたします。