ARToolKitの物体認識 その② 指認識
最近はARToolKitのプログラムも少しできてきたので、
次は手とかをそのまま認識させたいと思っていました。
そしたらちょうどmasafumiさんという方のブログで手認識を使ったARという記事を見つけました。
この方法は認識精度が高そうなので、twoViewでの物体認識にも使えそうです。
この手認識ARの研究は、手を認識することによってマーカーの代わりにしようというものです。
ソースも公開されているので、すぐにこのプログラムを使った動画がアップされています。
見ての通り、指認識の精度は非常に高いです。
というわけで今回は、この指認識のアルゴリズムだけをいただき、
この情報を元にtweVIewから指の3次元座標を計算してみました。
これで綿棒や色の付いた目印を使う必要がなくなります。
--- < 指認識の概要 > ---
指認識では、おおまかに以下のような処理を行っています。
1.手の色に近い領域を探し、輪郭線で分ける
2.距離変換画像を作成する
3.輪郭線を使ったラベリング
4.手の輪郭のカーブ具合を調べる
5.カーブ具合から指の判定
僕が感動したのは、手の輪郭線から指を判定する処理です。
--- < 1.手の色に近い領域を探し、輪郭線で分ける > ---
やはり最初は手の色を判定し、それを元に2値画像を作成します。
元のプログラムではここでRGBをYCrCbという色空間に変換し、
ヒストグラムなどを使って肌色を判定していました。
ですが、僕のプログラムでは前回のHSV色空間を使用しました。
そしてさらに、この肌色の2値画像から輪郭線情報を作成します。
輪郭線はOpenCVのcvFindContoursを使用して作成します。
--- < 2.距離変換画像を作成する > ---
次に、2値化画像から距離変換画像を作成します。
距離変換とは、値のある現在の点から値のない点への最短距離を求める計算です。
この最短距離を画像に書き込むと、上の1つめの画像のようになります。
この距離変換によって、肌色に近い領域で一番大きなものが大体分かります。
今回は、「その一番大きな領域が手である」という判定をしています。
--- < 3.輪郭線を使ったラベリング > ---
この手の領域を判別するために、輪郭線を使用します。
1.まっさらな画像を用意
2.画像に対し、各輪郭ごとに内部を塗りつぶしていく
3.塗りつぶすたびに、「距離変換の値が最大となる座標」が塗り潰されたかどうか判定する。
4.もし塗りつぶされいれば、その輪郭が「求める手の領域」のものになる。
この処理によってラベリングを行わずに、最大面積の領域を判定できてしまいます。
ラベリング処理は重いものが多いので、これはとても便利です。
結果的に上の2つ目の画像のようなものができあがります。
--- < 4.手の輪郭のカーブ具合を調べる > ---
手の輪郭を取得できたので、次にこれを用いて指を判定します。
指判定には、各輪郭点の狭い範囲で内積と外積を計算します。
1.輪郭線上の全ての点を調べる
2.各点の狭い範囲で、先の輪郭点へのベクトルと、後の輪郭点へのベクトルを取得する。
3.2つのベクトルの内積を計算し、それがある程度大きければ、その点はカーブしていると判定
4.2つのベクトルの外積を計算し、そのカーブの方向を判定
5.調べる範囲を変えて、2~4の処理を繰り貸す。
6.求める値になったら、そのカーブが指に似た曲がり具合であると判断する。
この処理で、上の3つ目の画像ができあがります。
--- < 5.カーブ具合から指の判定 > ---
上記の処理で指っぽいカーブは分かりましたが、これが本当に指かどうかはまだ分かりません。
また、場合によってはその指がどの指なのかも判定が必要です。
ですが、今回のプログラムではその処理を入れていません。
ここでは最後に、前回同様ステレオでこの2次元座標を3次元に変換して終わりです。
これで上の最後の画像のようになります。
元の研究では、事前に指の理想的な位置を取得しておいて、
それと比較することで各指を認識したりしているようです。
僕のプログラムも指っぽい形状の認識の精度は高くなりましたが、
その後の指判定はまだできていません。
ソースの清書も含め、その辺が今後の課題となります。
次は手とかをそのまま認識させたいと思っていました。
そしたらちょうどmasafumiさんという方のブログで手認識を使ったARという記事を見つけました。
この方法は認識精度が高そうなので、twoViewでの物体認識にも使えそうです。
この手認識ARの研究は、手を認識することによってマーカーの代わりにしようというものです。
ソースも公開されているので、すぐにこのプログラムを使った動画がアップされています。
見ての通り、指認識の精度は非常に高いです。
というわけで今回は、この指認識のアルゴリズムだけをいただき、
この情報を元にtweVIewから指の3次元座標を計算してみました。
これで綿棒や色の付いた目印を使う必要がなくなります。
--- < 指認識の概要 > ---
指認識では、おおまかに以下のような処理を行っています。
1.手の色に近い領域を探し、輪郭線で分ける
2.距離変換画像を作成する
3.輪郭線を使ったラベリング
4.手の輪郭のカーブ具合を調べる
5.カーブ具合から指の判定
僕が感動したのは、手の輪郭線から指を判定する処理です。
--- < 1.手の色に近い領域を探し、輪郭線で分ける > ---
やはり最初は手の色を判定し、それを元に2値画像を作成します。
元のプログラムではここでRGBをYCrCbという色空間に変換し、
ヒストグラムなどを使って肌色を判定していました。
ですが、僕のプログラムでは前回のHSV色空間を使用しました。
そしてさらに、この肌色の2値画像から輪郭線情報を作成します。
輪郭線はOpenCVのcvFindContoursを使用して作成します。
--- < 2.距離変換画像を作成する > ---
次に、2値化画像から距離変換画像を作成します。
距離変換とは、値のある現在の点から値のない点への最短距離を求める計算です。
この最短距離を画像に書き込むと、上の1つめの画像のようになります。
この距離変換によって、肌色に近い領域で一番大きなものが大体分かります。
今回は、「その一番大きな領域が手である」という判定をしています。
--- < 3.輪郭線を使ったラベリング > ---
この手の領域を判別するために、輪郭線を使用します。
1.まっさらな画像を用意
2.画像に対し、各輪郭ごとに内部を塗りつぶしていく
3.塗りつぶすたびに、「距離変換の値が最大となる座標」が塗り潰されたかどうか判定する。
4.もし塗りつぶされいれば、その輪郭が「求める手の領域」のものになる。
この処理によってラベリングを行わずに、最大面積の領域を判定できてしまいます。
ラベリング処理は重いものが多いので、これはとても便利です。
結果的に上の2つ目の画像のようなものができあがります。
--- < 4.手の輪郭のカーブ具合を調べる > ---
手の輪郭を取得できたので、次にこれを用いて指を判定します。
指判定には、各輪郭点の狭い範囲で内積と外積を計算します。
1.輪郭線上の全ての点を調べる
2.各点の狭い範囲で、先の輪郭点へのベクトルと、後の輪郭点へのベクトルを取得する。
3.2つのベクトルの内積を計算し、それがある程度大きければ、その点はカーブしていると判定
4.2つのベクトルの外積を計算し、そのカーブの方向を判定
5.調べる範囲を変えて、2~4の処理を繰り貸す。
6.求める値になったら、そのカーブが指に似た曲がり具合であると判断する。
この処理で、上の3つ目の画像ができあがります。
--- < 5.カーブ具合から指の判定 > ---
上記の処理で指っぽいカーブは分かりましたが、これが本当に指かどうかはまだ分かりません。
また、場合によってはその指がどの指なのかも判定が必要です。
ですが、今回のプログラムではその処理を入れていません。
ここでは最後に、前回同様ステレオでこの2次元座標を3次元に変換して終わりです。
これで上の最後の画像のようになります。
元の研究では、事前に指の理想的な位置を取得しておいて、
それと比較することで各指を認識したりしているようです。
僕のプログラムも指っぽい形状の認識の精度は高くなりましたが、
その後の指判定はまだできていません。
ソースの清書も含め、その辺が今後の課題となります。
