2012年10月29日

Parzen推定による動的背景モデルについて

気分転換?にパターン認識ネタをひとつ試してみました。

統計的パターン認識の手法として、パラメトリック法とノンパラメトリック法があります。

・パラメトリック法
−モデルがある分布(ガウス分布等)に従っていると仮定して推定
使用例:特異値分解と白色化について
・セミパラメトリック法
−モデルが複数のある分布の重ね合わせでできていると仮定して推定
使用例:混合ガウス分布とEMアルゴリズムについて
・ノンパラメトリック法
−モデルの分布は仮定せずに与えられた訓練データからモデルを推定
使用例:今回の背景モデル推定

パラメトリック法とセミパラメトリック法はこれまでに試しているので、今回はノンパラメトリック法で背景モデルの推定を試してみます。

動画像から動く物体を検出するために、背景モデルをノンパラメトリック推定する手法が提案されています。
今回は、ノンパラメトリック推定のひとつであるParzen推定を用いて、物体検出を行います。

Parzen推定の参考文献としては、以下のようなものがあります。
[1] http://sunak2.cs.shinshu-u.ac.jp/~maruyama/course/learning/2002/slides/parzen.pdf
[2] http://nlp.dse.ibaraki.ac.jp/~shinnou/zemi2010/staml/staml-okazaki-0713.pdf
[3] http://ci.nii.ac.jp/naid/110006991102

このParzen推定で背景モデルを構築する場合には、訓練データとして過去Nフレームの画像データを使用して、各画素の色や輝度値を入力とした場合に、そこが背景かどうかの確率を出力とするような確率密度関数を求めることになります。

parzen_001.png

今回、サンプル動画として、PRMUアルゴリズムコンテスト2010の画像を使用させていただいております。
オクルージョンの有無などLV1〜3に分かれており、各レベルに5つの各101枚サンプル画像があります。

通常は過去N枚使って求めた確率密度関数から、現在のフレームの画素値が背景か前景かを閾値により判定することで前景の検出を行うのですが、今回は全部で101枚に固定されているため、この101枚の画像で確率密度関数を推定した後、もう一度101枚の画像で動物体検出を行います。

実行結果

ttp://www.murase.m.is.nagoya-u.ac.jp/alcon2010/?page=download
上記ページのLv3の3(自転車に乗っている)画像で試した結果です。
上がParzen推定による結果で、下が輝度値の差分の絶対値を10倍した結果です。
赤い矩形がアルコンのデータについている正解矩形データです。




差分の絶対値をとった場合、フレームの前後の像が現れるので、二人乗りをしているように見えます。
Parzen推定だと画素毎に背景か前景かを判定するので、こういったことは起こりませんが、今回高速化の手法を全く行っていないので、処理時間的にはお話になりません。
また、Parzen推定は平滑化パラメータや閾値で結果が変わるのですが、2,3種類試しただけで特に最適化は行っていません。
精度的にもこれぐらいの問題であればフレーム間差分で十分な気がしますね。



web拍手 by FC2
posted by シンドラー at 18:23 | Comment(0) | TrackBack(0) | Pattern Recognition | このブログの読者になる | 更新情報をチェックする

2012年10月20日

パーティクルエンジンについて その2

前回の続きです。

SPARKでは、ZoneとEmitterで粒子の放出方法を色々変えられるようです。
Zoneの領域から、Emitterにより粒子を放出するような関係です。

spark_002.png spark_003.png
SPARK Particle Engine documentより引用

ZoneでAABBやPoint、Ringなど、色々な領域を指定できます。
Emitterの方は、真っ直ぐ飛ぶStraightEmitterや、ランダムな方向に飛ぶRandomEmitterなど、粒子が飛ぶ方向や数、放出数などを色々指定できます。

今回は水しぶきっぽいものということで、StraightEmitterだと直線的すぎて、RandomEmitterだと反対方向にも飛んでしまいますので、RingのZoneとRandomEmitterを使用して、Ringの法線方向と速度の内積を計算して、反対方向を向いていれば速度を逆にするのと、内積の2乗を速度に掛けて法線ベクトル方向の方が初速度が大きくなるように修正してみました。

実行結果



波がぶつかったときにこれを出せばいいかと思いますが、波がぶつかった判定をどうするかについて考えてませんでしたので、ちょっと考えてみたいと思います。
web拍手 by FC2
posted by シンドラー at 17:08 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2012年10月18日

パーティクルエンジンについて その1

水しぶきをつけたかったので、パーティクルエンジンを試してみようと思います。
適当に探した結果、zlibライセンスで基本C++とSTLしか使っていないSPARK particle engine[1]が良さそうでしたので使ってみることにしました。

まずは最初のチュートリアル1です。デモプロジェクトに含まれており、ソースコード自体はそちらが参考になります。

サンプルではSDLを使用しているようでしたので、自分用ではその部分を外してコアなライブラリだけ使用することにしました。

実行結果

printfで座標を表示しているだけです。

spark_tutorial_001.png

ソースコード

一応実行結果を動画にすると以下のようになっていました。
OpenGLのレンダラを使用すれば、z座標に応じてパーティクルの大きさが変わりますので、もっと見栄えが良いはずです。



OpenGLのレンダラを使用したバージョンは、SPARKのデモソリューション(SPARK_Demos)の中にSPARK Tuto 1というプロジェクト名で入っています。

[1] http://spark.developpez.com/

以下適当和訳です。続きを読む
web拍手 by FC2
posted by シンドラー at 19:43 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2012年10月11日

FFTによる法線ベクトルの計算

海面の生成で、FFTを使って高さとChoppyと法線ベクトルを計算していましたが、なぜChoppyや法線ベクトルが計算できるのかは考えずにそのまま使用していました。

一応以下のようなことだと思いますが、間違っている可能性もありますのでご了承ください。

高さ情報から法線ベクトルを計算する場合、その面に垂直なベクトルを計算したいので、その面の接線ベクトルと従接線ベクトルを求めて、それを外積して法線ベクトルを求めることが多いかと思われます。

で、接線というのは、その面の勾配になるのですが、その面の関数が分かっている(微分できる)のであれば関数の微分を行って、その位置の傾きを計算することで接線ベクトルを求めることができます。

しかし、離散的な高さ情報しか持っていないので、基本的には関数近似など行わずに、近傍の高さ情報から差分(Sobelフィルタなど)を使って簡易的に接線ベクトルを計算します。

この辺のやり方は以下のサイトに詳しく書かれております。
[1] t-pot『動的法線マップ』:http://www.t-pot.com/program/71_wave/index.html

要するに関数がわからないので微分できないから差分で近似しましょう、というやり方になります。

で、関数がわかっていれば微分できるので、それを使ったのがFFTによる法線ベクトルの計算になります。
離散フーリエ変換は、信号を三角関数の和で関数近似することになりますので、関数がわかっているということになります。

数学で習うかと思いますが、三角関数や指数関数の微分はとても簡単ですので、関数を微分してそこの勾配を計算してそこから法線ベクトルを求めようということです。

フーリエ解析の本によると、微分できる条件のようなものがあるみたいですが、とりあえず気にせずやってみます。

簡単にするために、1次元の信号(高さ情報)で考えます。ランダムノイズを生成するプログラムを以前作っているので、それで適当に高さを作ります。

そして、参考サイト[1]の方法で、差分により法線ベクトルを求めると、以下のような結果になりました。
sobel_normal.png

dx = 1.0;
dy = 0.5*(h[i+1]-h[i-1]);
dz = 0;
normalize(dx, dy, dz);

のような感じで差分によりdyを計算して、dxは適当な定数にして正規化を行い接線ベクトルを求めます。

で、このベクトルと、zaxis[3] = {0, 0, 1.0};のようなZ軸方向のベクトルとの外積を計算することで求めたのが図の法線ベクトルになります。

隣の高さ情報しか見ていませんので、細かく法線ベクトルの向きが変わっているかと思います。

次に、FFTによる接線ベクトルの計算方法です。
fft_normal_slide1.png
fft_normal_slide2.png
fft_normal_slide3.png

計算が合っているのかどうかは知りませんが、結局接線ベクトルは下記方法で求めることができます。

// Refが高さ情報、Imfが0、ReFとImFがFFT後の実部と虚部の係数
fft(Ref, Imf, ReF, ImF);
// 実部と虚部の計算
for (int i=0; i<size; i++)
{
  // 接線ベクトル計算用
  ReF1[i] = -(2.0*M_PI*i/size)*ImF[i];
  ImF1[i] = (2.0*M_PI*i/size)*ReF[i];
  // Choppy変位量計算用
  ReF2[i] = (2.0*M_PI*i/size)*ImF[i];
  ImF2[i] = -(2.0*M_PI*i/size)*ReF[i];
}
// 逆FFT
ifft(ReF1, ImF1, Ref1, Imf1);
ifft(ReF2, ImF2, Ref2, Imf2);

後は、Ref1をdyとして接線ベクトル→法線ベクトルを外積を使って計算します。
choppyに関しては、λ*Ref2をx座標に足して尖らせます。
それぞれの実行結果が以下のようになります。
fft_normal.png
fft_choppy.png
法線ベクトルは、滑らかなのですがあまり正しくなさそうです。何か間違っているかもしれません。

FFTにかかる時間を考えるとあまり実用的ではないかもしれませんが、こういう方法もあるということで。





web拍手 by FC2
posted by シンドラー at 01:07 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。