yoppa.org


メディア芸術演習 VI - メディア・アート II

openFrameworks – addon を使う 3 : OpenCVを利用した映像認識

今回は、OpenCVという映像解析の技術を応用して、ライブ映像を用いたインタラクティブな表現に挑戦します。

「OpenCV」とは、「Open Computer Vision Library」の略で、オープンソースでコンピュータビジョンの技術を利用可能なライブラリです。米Intel社で開発され、画像処理・画像認識用のC/C++言語のライブラリとして配布されています。商用・非商用を問わず無料で使用することが可能です(BSDライセンス)。

OpenCVのコアとなる技術「コンピュータビジョン」とは、ひとことで言うと「ロボットの目」を作るという研究分野です。「コンピュータビジョン」の実現のために、画像のセンシングのためのハードウェアの研究から情報を認識するための人工知能の研究まで、広範囲な分野の研究が行われています。

OpenCVは、この「コンピュータビジョン」の研究の中でソフトウェアを用いて画像処理を行う用途に使用されています。映像をリアルタムに解析した結果からその構造を解析し、モーション検知や物体追跡、さらには機械学習(顔認識)など、様々な応用が可能となっています。

openFrameworksでは、ofxOpenCvというアドオンを使用することで、簡単にOpenCVの機能を活用することが可能です。

openFrameworks + OpenCVを活用した作品実例

OpenCVによる画像解析を用いてインタラクションを実現したメディアアート作品は、近年、数多く発表されています。ここ数年のメディアアートのメインストリームの一つといっても過言ではないかもしれません。現在活発に情報がやりとりされている「Kinect Hack」に関しても、こうしたリアルタイムの映像解析を用いたインタラクティブアートの一つの進化形とも考えられます。

OpenCVを分析のエンジンとして使用した過去の有名な作品をいくつか紹介します。

Graffiti Research Lab. “L.A.S.E.R. Tag”

“The EyeWriter”

Chris O’shea “Hand from Above”

YesYesNo “Night Lights”

Marco Tempest “Magic Projection”

Theodore Watson “Knee Deep”

Knee Deep – Cinekid 2009 from Theo Watson on Vimeo.

Theodore Watson “Boards Interactive Magazine”

Boards Interactive Magazine – Walkthrough from Theo Watson on Vimeo.

映像から物体を認識するアルゴリズム

では、実際にOpenCVによる映像解析を用いて、移動する物体を識別する方法について探っていきましょう。OpenCVのライブラリを使用することで比較的簡単に映像ソースから変化した部分だけを識別し、さらにその輪郭を抽出することが可能です。このデータを応用することで、様々なインタラクティブなメディアアート作品を作成していくことが可能となります。まずは、輪郭抽出までの手順を順番に理解していきましょう。

カラーの映像ソースから、移動する物体の輪郭を抽出するまでには、いくつかの手順を踏む必要があります。おおまかな流れは以下のような順番になっています。

  • カメラから映像をキャプチャー
  • グレースケールに変換
  • 背景画像を登録
  • 背景画像と現在の画像の差分を計算
  • 差分の画像を2値化
  • 2値化した画像を解析(輪郭抽出、重心を算出)

KeynoteScreenSnapz001.png

この手順に従って、実際にopenFrameworksでプログラミングしていきましょう。

物体検出の基本プログラム

まず、輪郭検出までの手順を、そのまま順番に実装した素直なプログラムを作ってみましょう。

ソース映像や、それぞれの解析過程の映像のためのメモリ領域を確保した上で、ofxOpenCvのメソッドを活用しながら、徐々に輪郭を抽出しています。

openFrameworksからofxOpenCvの機能を使用するには、addonsの中にofxOpenCvを加える必要があります。addonsフォルダ内が下記のようになるようファイルを追加してください。

XcodeScreenSnapz001.png

アドオンが追加できたら、下記のソースを入力します。

test.h

test.cpp

OpenCvBasicDebugScreenSnapz001.png

このプログラムはキーボード入力によってモードを切り替えられる仕組みになっています。実際にキー入力をしてみて、処理の過程を実感してみましょう。

  • [0]キー:オリジナルのカラー映像
  • [1]キー:グレースケールに変換した映像
  • [2]キー:背景としてキャプチャーした静止画
  • [3]キー:背景画像と現在のグレースケールの画像の差分をとって、2値化した映像
  • [space]キー:背景画像を新規にキャプチャーする
  • [a]キー:輪郭抽出の解析結果を表示する
  • [+]キー:2値化の閾値のレベルを増加
  • [-]キー:2値化の閾値のレベルを減少

輪郭抽出(ContorFinder)のためのパラメータ詳細

映像からモーションを検出し輪郭を抽出するためには、様々な画像処理が行われています。実際には処理を行う対象、周囲の環境、カメラの性能、明るさなど様々な要因の影響を受けるため、実際に分析結果をみながら細かくパラメータを調整していく必要があります。パラメータには下記のようなものがあります。

  • 閾値 (threshold) – グレースケールの映像を白黒に2値化する際に、白と黒を分ける境目の値
  • 物体の最小サイズ (minBlobSize) – どこまで小さい物体(Blob)まで検出するか
  • 物体の最大サイズ (minBlobSize) – どこまで大きい物体(Blob)まで検出するか
  • 最大認識数(maxNumBlobs) – 物体を最大何個検出するか
  • 穴検出 (findHoles) – 物体の中に空いた穴を検出するか
  • 近似 (useApproximation) – 近似値を使用するか

これらの値を、実際に検出結果を確かめながら適切にチューニングすることで、より正確な検出や計算量の軽減などを行うことが可能となります。

より実用的なプログラムへ – GUIの実装

次に、この輪郭抽出のプログラムをより実用的なものにしていきたいと思います。先程解説したように、正確な輪郭の抽出や、計算量を抑えた分析のためには、適切なパラメータのチューニングが必要となります。しかし、調整の際に毎回プログラムを修正してビルドをやりなおすのは効率が良くありません。

このように、状況に応じて細かなパラメータを調整した際に便利なアドオンを紹介します。ofxSimpleGuiTooというアドオンは、プログラム内で用いられているパラメータやbool値のtrue/falseの切り替えなどを、簡単なGUIを通してプログラムを作動させながらリアルタイムに行うことが可能です。さらに、分析中の画像を複数枚同時に小窓の中に表示することができるので、今回のようなOpenCVを用いた画像解析のプログラムにはうってつけです。

パラメータを設定した結果は、最終的にXML形式の外部ファイルとして保存され、次回プログラムを起動した際には調整したパラメータを再度読み込んで前回の状態を復元する機能もあります。この機能を活用することで、展示する場所の状況を記録しおくことが可能となり、作品制作の際の強力なサポートとなるでしょう。

ofxSimpleGuiTooを使用するためには、同時に付随するアドオンをいくつか読み込む必要があります。下記にofxSimpleGuiTooを作動させるためのアドオンを列挙します。

  • ofxSimpleGuiToo – GUI本体
  • ofxMSAInteractiveObject – インタラクティブな図形を作成するためのアドオン
  • ofxXmlSettings – 設定した項目をXML外部ファイルとして保存し、次回起動の際に再度読み込むための機能

これに加えて、ofxOpenCvも必要となるので、「グループとファイル」の中のaddonsフォルダは下記のようになります。

XcodeScreenSnapz002.png

アドオンの設定が完了したら、以下のプログラムを入力します。

testApp.h

testApp.cpp

OpenCvGuiScreenSnapz003.png

[g]キーでGUIの表示/非表示の切り替えができます。GUIを表示した解析のパラメータを細かく設定し、完了したらGUIを隠して使用します。

輪郭抽出の活用 – 移動点の中心から湧き出すパーティクル

では次に、この輪郭を検出した物体の情報を活用してみましょう。検出した物体(Blob)は、その図形をとりかこむ長方形の座標と重心点の座標を取得することが可能です。この重心の点を利用して、そこからパーティクルが湧き出てくるような表現に挑戦してみましょう。

パーティクル表現の基本原理は、以前の講義「openFrameworksで、オブジェクト指向プログラミング(OOP) 後編」で作成したパーティクルを活用しています。

testApp.h

testApp.cpp

CustomCircle.h

CustomCircle.cpp

OpenCvParticleScreenSnapz002.png

OpenCVを応用したプログラム – ベクトル場(Vector Field)

次に、単純な座標の情報だけを活用するのではなく、映像全体の動きや物体の移動する流れにより密接に絡みあった表現を追求していきたと思います。

ここで、ベクトル場(Vector Field)という概念を導入したいと思います。ベクトル場とは、空間内のベクトル的な量の分布を表したものです。例えば、流体の速さと向きや、磁力や重力の強さと向きなどが空間内にどのように分布しているかを表現するために用いられます。

OpenCVで解析した映像の変化を、このベクトル場としてとらえ、空間内でのベクトルの量と向きに変換してみます。すると、単純な座標ではなく映像の動きを流れとして感じさせるような表現が可能となってきます。

このプログラムのvectorFieldクラスは、映像の差分情報からベクトル場を計算しています。画面全体のベクトル場を算出して、その中にパーティクルをランダムに配置し、ベクトル場の流れをパーティクル一つ一つに力として伝えています。その結果、パーティクルは映像の動きに押し流されるように、空間内を漂います。

testApp.h

testApp.cpp

vectorField.h

vectorField.cpp

particle.h

particle.cpp

OpenCvGuiScreenSnapz002.png

OpenCVを応用したプログラム – Box2Dとの融合

最後にこのベクトル場を、より厳密な物理世界に適用してみましょう。

今度のプログラムは、一つ一つのパーティクルが単純なものではなく、物理演算を適用した物体に変更しています。物理演算には前回使用したBox2Dを活用しています。ベクトル場に配置されたパーティクルは、その力の影響を受けながら、重力やパーティクル同士の衝突などの物理法則が適用されています。このことにより、とてもリアルな粒の動きが再現されています。

testApp.h

testApp.cpp

vectorField.h

vectorField.cpp