« 2009年5月 | トップページ | 2009年7月 »

2009年6月22日 (月)

Jitterで動体検知して遊ぶ

この前赤色検知でやってみたけどイマイチだったので普通に動体検知をやってみました。
内容としては映像を入力し、色を取得して●に変換。カメラで動体検知して、動いた場所の●を反応させます。

とりあえずは動きいたけど、かなり頭の悪いやり方になってるはず。
●が20x15になってるのも単にCPU負荷的にこのくらいじゃないとダメだっただけで
ほんとはもっと細かくしてみたい。ちゃんとしたやり方でやれば軽くなるはず。。

jitter17

今回は下記のような考え方でやってます。


●動体検知
FLASHでやる時と同じ考え方です。
1つ前のコマと比べて色が違ってる部分が動いた部分として認識します。

1)カメラの取得
jit.dx.grab 20 15

Macだとjit.qt.grabです。
20x15のサイズで取得します。
20x15なのは処理軽減のため。。
最初から20x15にするのと、最初は320x240で後から20x15にするのとでどの程度違いがあるかは分からないけど、これでも一応大丈夫でした。

2)カメラ映像の調整
jit.brcosa

映像の明るさ、コントラストを調整し、検知しやすくします。
環境によって変わると思うので数値をいじれるようにしておきます。

3)滑らかに変化させる
jit.slide @slide_up 4 @slide_down 8

暗い場所だとカメラのフレームレートがかなり落ちるので、反応が悪くなります。
元映像をjit.slideで滑らかに変化させることでごまかそうという考えです。

4)反転
jit.dimmap @map 0 1 @invert 1 0

鏡っぽくしたいので映像を反転します。

5)Matrixへ
jit.matrix 7 float32 20 15

最終的なMatrixは色(ARGB)、座標(X,Y)、大きさ(scale)の7つの要素を持たせたいので
plane数が7のMatrixに入れ込みます。
このへんがまず効率悪そう。

6)現在のコマを取っておく
jit.matrix oldmt 4 float32 20 15

次のフレームで1つ前のコマとの違いを調べるために今のコマを取っておきます。

7)1つ前のコマとの違いを調べる
jit.op @op absdiff @val 0.

「absdiff」で違いを調べます。
FLASHでいうブレンドモードのdifferenceみたいなものです。
右のインレットには「jit.matrix oldmt 4 float32 20 15」を入力します。
これは「6」でやった1つ前のコマになります。
このへんは頭使いました。処理の順番が分かりにくい。
これで合ってるのかも分からないけど動いてるからOK。

8)値の調整
jit.op @op * @val 5.

色の違いを使って●のサイズを決めるので、そのへんの調整ができるようにしときます。

9)Matrixへ
jit.matrix 7 float32 20 15

これいらないんじゃないかな。。

10)Matrixの値の変更
jit.expr @expr 0. 0. 0. 0. (cell[0]/6-2.6) -(cell[1]/6-1.2) (in[0].p[1]+in[0].p[2]+in[0].p[3])*0.1+0.05

左から、アルファ、赤、緑、青、X、Y、サイズとなるようにMatrixの中身を変更します。
アルファ、赤、緑、青は別で処理するのでここでは0にしておきます。
「cell[0]」はセルのX値、「cell[1]」がY値になります。表示位置を調整するために少し値をいじります。
「in[0].p[1]」、「in[0].p[2]」、「in[0].p[3]」はそれぞれRGB値。値が大きいほどたくさん動いた部分になります。

11)Matrixへ
jit.matrix 7 float32 20 15

これもいらないんじゃないかな。。


●映像ファイルの入力
1)映像ファイルの読み込み
jit.qt.movie

「read」メッセージを送ることで映像ファイルを読み込みます。
ほんとは外部のDVD映像とかを読み込みたい。

2)滑らかに変化
jit.slide @slide_up 4 @slide_down 8

滑らかに変わったほうがいい感じだったので。

3)plane7のMatrixへ
jit.matrix 7 float32 20 15

動体検知したMatrixと合体させるためにplane数7のMatrixへ。

4)空いてる部分の数値を初期化
jit.op @op * pass pass pass pass 0. 0. 0.

「3」のままだと後ろの3つのplaneは前のplaneの値が繰り返し入ってしまうのでここで0に初期化します。

●Matrixの合成、表示
1)Matrixの合成
jit.op @op +

映像のMatrixと動体検知のMatrixを合体させます。
映像のはアルファ、赤、緑、青、0、0、0になってます。
動体検知のは0、0、0、0、X、Y、サイズになってます。
それぞれを足します。

2)Matrixの中身を1セルずつリストにしする
jit.iter

Matrixの各セルの値の全plane分をリストで出力します。
アルファ、赤、緑、青、X、Y、サイズのリストがセル数分出力されていきます。

3)黒いとこは表示しない
if $f1+$f2+$f3 > 0. then bang

黒いとこは見た目的にあんまり分からないので、処理の軽減のためにも表示させないようにします。
黒じゃない時だけbangを出力します。

4)●の描画
jit.gl.gridshape jit17 @color 0.2 0.9 0.6 0.1 @scale 0.08 0.08 0.08 @shape circle @depth_enable 1 @smooth_shading @automatic 0 @blend_enable 1 @blend_mode 3 1

「2」の出力結果を使ってjit.gl.gridshapeに色、座標、サイズのメッセージを送り、●を描画します。


こんな効率の悪そうな内容になってます。
ほんと誰かに教えてもらいたい。。

| | コメント (2) | トラックバック (0)

2009年6月 9日 (火)

ねんぴょー

なんか流行っているみたいで。。

http://nenpyo.org/primevision

けっこう夢中で書いちゃうなあ。
昔を思い出すのもボケ防止にいいみたいなので昔のもちょこちょこ追加しよう。

| | コメント (0) | トラックバック (0)

Jitterの赤色検知で遊ぶ。

前回のJitterでの赤色検知を使って、ちょっとした動きを追加。

画面内の赤い部分にパーティクルを発生させたいだけなんだけど、これが難しい。。
Flashだったら簡単にできるのになあ。単に俺が理解してないだけなのでこのソフトが悪いわけではないんだけども。

jit13

jit13_patch

1.処理軽減
MAX/MSPだったらパーティクルたくさんあっても軽い、みたいな先入観があったけど
そのへんはちゃんと作らないとやっぱり重くなるね。
カメラの取得サイズが160x120の場合19200となるわけで、それ全部パーティクルにしたらそれなりに重いか。

前回の赤色検知では160x120でやってたけど、そこはそのまま使いつつ、その後にサイズを小さくします。

jit.matrix 1 float32 20 15 @planemap 1

新しくMatrixを作ります。
赤色検知では最初にカメラの取得があるのでARGBの4つのplaneが存在してたけど、
最終的に使うのは赤の部分だけなので、新しいMatrixはplaneを1個だけにします。
「@planemap 1」で渡されたMatrixのplaneの1のやつ(0から始まるので2番目)がコピーされます。
とりあえずこれでデータ的には4分の1になるのかなと。
サイズは「20 15」としました。8分の1に圧縮されます。セル数的には64分の1。
セル数は300になり、この300個分のパーティクルを作るようにします。

2.パーティクル
「jit.gl.mesh」を使います。
2つあるのは四角を表示する用と、それらをつなぐラインを表示する用になってます。
@draw_mode が違うだけで他は同じです。

3.条件分岐
先ほど小さくしたmatrixの各セルごとに値を調べます。
その値が0.001より大きいときはその座標に向かってパーティクルは動き、
そうでない場合は真ん中に戻るようにしたいので、条件分岐をしたいなと。
最初は「if文なんてねーだろ」って思っていろいろ調べちゃったけど、普通にありました。

if $f1 > 0.001 then $i2 $i3 $f1 bang else 10 7.5 0. bang

$f1=1つめのインレットに渡される値=赤色の値
$i2=セルのX座標
$i3=セルのY座標
です。
「$f1」の「f」はfloatを意味してるっぽいです。
ここを最初「$i1」としてたら出力結果が整数にまるめられちゃって、if文で小数点ダメなのかって諦めかけてしまいました。。

この文は、
$f1が0.001より大きかったら「$i2 $i3 $f1 bang」というリストを返し、
そうでない時は「10 7.5 0. bang」というリストを返します。
「10 7.5 0.」は真ん中に来させるための値です。
「bang」はその後のcounterを動かすためのものです。

4.表示用Matrixの作成
300個のパーティクルに使う座標を格納するためのMatrixを作ります。
サイズは300x1です。XYZの値があるのでplaneは3つです。
1つめのplaneにX座標、2つめにY座標、3つめにZ座標を格納します。

その前に「setcell $1 0 val $2 $3 $4」というメッセージを作り、このMatrixへ渡してあげることで各セルへ値を入れていきます。

その前の部分では各値の調整をし、格納するセルのX座標を「counter」を使って制御して
packでリストにまとめています。
このへんはすごく頭を使いました。もっと楽な方法、速い方法があるはず。

5.動きをスムーズに。
「4」のMatrixを「jit.gl.mesh」に渡す時に「jit.slide」を通すことで、位置がパッと変わるのではなく、滑らかに動くようにします。
@slide_upはおそらく値が大きくなる時の変化の速さ、
@slide_downはおそらく値が小さくなる時の変化の速さだと思います。
よくFlashで簡単なイージングをかける時に、
this._x += (_xmouse - this._x) / 10;
などとしたりしますが、この式の「10」に相当するような感じです。
つまり値が小さいほど動きは速くなり、大きいほど遅くなります。

という感じで作ってみましたが、実際に動かしてみると赤よりもオレンジや黄色に反応しやすい。。
カメラの性能もあるけど映像が暗くなってしまうので、単に赤いものだと暗くなりやすいっぽい。黄色とかオレンジのほうが明るいので取得しやすい。
その前に赤色検知のやり方も微妙なんだけども。

カメラはどういうのがいいのかねー。

| | コメント (0) | トラックバック (0)

2009年6月 5日 (金)

Jitterで赤色検知

jit.exprを使ってカメラの映像の赤色検知をしてみました。
jit.exprはサンプルとかでよく使われてるけど意味が分かりにくい。
実験してみてやっとちょっとだけ分かった気がします。

Jitter12

<カメラの映像取得>
「jit.dx.grab 160 120」というオブジェクトを作って「open」メッセージを
送ってあげるとカメラの映像を取得できます。
ちなみにWindowsとMacでやり方が違ってて、これはWindowsの場合。
MacだとQuicktimeの機能を使うので「jit.qt.grab」となります。
「160 120」の部分はサイズ。

<映像の色データをMatrixへ>
「jit.matrix 4 float32 160 120」としてMatrixを作成。
「160 120」はMatrixのサイズ。これはカメラの取得サイズに合わせます。
「4」という数字はこの場合「160x120のサイズのMatrixを4枚」という感じの意味です。
「plane」というパラメータになります。
なぜ4つかというと、映像の色データ=ARGBの各値を各planeに割り振るわけです。

<赤色検知>
「jit.expr @expr 1 (in[0].p[1]-(in[0].p[2]+in[0].p[3])/2-0.1)*10 0 0」とします。
@exprのとこはスペースで区切って各planeに対する計算値を書きます。

1つめはアルファ値。だと思うんだけど値変えても特に変化ないので違うのかな。。

3つめ、4つめは緑、青の値。そこはいらないので0にします。

2つめがややこしくなってます。
考え方としては赤い部分を検出するにはR値が大きい部分が分かればよさそうですが
白いところか明るい部分は赤くなくてもR値は大きくなります。
なので「赤い部分だけ」を取得するにはR値が大きく、GとBの値が小さい部分を取得すればいいのかなと。

というわけで、計算は適当だけど「R値-(G値+B値)/2」ってしてみました。
これをexprでやる場合にどうしたらいいのか。

ドキュメントを見てみると「in」というのがあって、それが渡ってくるMatrixの値っぽい。
「in[0]」って[]内に数字を書きます。これはなんだろうな。。おそらくMatrixが複数渡ってくる場合があって、どのMatrixかを指定するためなのかと。分かんないけどここは通常0でいいかと。

例えば「jit.expr @expr in[0] in[0] in[0] in[0]」とすると各値に渡ってきたMatrixがそのまま設定されます。
「jit.expr @expr in[0]*0.5 in[0]*0.5 in[0]*0.5 in[0]*0.5」とすると全部半分の値になるので暗くなります。
ちなみに全部同じ計算をするのであれば「jit.expr @expr in[0]*0.5」と1つだけ書けばいいです。

まずは「jit.expr @expr 1 in[0] 0 0」としてみます。
R=赤は渡ってきたMatrixの中身そのままになります。GとBは0になります。
これで赤のチャンネルのみ表示できました。

先ほどの計算「R値-(G値+B値)/2」をしてみます。
「in[0]」で渡ってきたMatrixを取得できるけども、これは2つめに「in[0]」と書いたら渡ってきたMatrixの2つめのplaneの値を受け取ることになります。
なので「in[0]」だけだと赤(2つめ)のとこで緑(3つめ)と青(4つめ)の値が取れません。
他のとこの値をとるには「in[0].p[1]」とします。
「p」ってのが「plane」の略っぽいですね。
「in[0]」が渡ってきたMatrix(の1つめ)、その中にあるplaneを「p[1]」で[]内でplaneの番号を
指定して値を取得できるということです。
「p[1]」を省略したら勝手に対応するplaneの値を取得できるってことですね。
なので「jit.expr @expr in[0] in[0] in[0] in[0]」と書くと、それは勝手に
「jit.expr @expr in[0].p[0] in[0].p[1] in[0].p[2] in[0].p[3]」としたのと
同じになるってことみたいです。

というわけで「R値-(G値+B値)/2」を計算するには
「in[0].p[1]-(in[0].p[2]+in[0].p[3])/2」
とすればOKです。

表示確認用にちょっと計算を変えてます。
0.1を引いて暗い赤は完全に暗くして、残った赤は10倍にしてより明るい赤にしてます。

あとはこの結果のMatrixで、2つめのplaneの値を見れば赤色部分が分かるのでそれを
使えばいいのかなと思います。

| | コメント (0) | トラックバック (0)

« 2009年5月 | トップページ | 2009年7月 »