ARToolKitのtwoView その⑤ ステレオのソースの公開
お待たせしました。
twoViewを使った、ステレオマッチングプログラムのソース公開です。
StereoAnyColor1.0.zip
--- < プログラムの使い方 > ---
0.Webカメラが2つあることが最低条件です。
ちなみに僕のは"Qcam Pro for Notebooks"。他のカメラでは試していないので、動くかどうかはわからないです。
あと、2つのカメラの設定を同じにしてください。
1.2つのカメラの向きを平行にして、まっすぐに並べる。
2.赤・黄・青など特徴的な色の物体を用意し、場所は白いテーブルの上など選んだ色が他にはないような所にする。
3.TwoViewに関する説明を読み、"WDM_camera_flipV_01.xml"、"WDM_camera_flipV_02.xml"を作成。
4.プログラムを起動して"Video Source 1"ウィンドウで、用意した特長的な色の物体を画面に表示して、それを左クリックします。
5.物体が画面に映っている状態で、Fキーを押してラベリング画像を表示。
6.Kキーを押して続けて閾値を下げ、目的の物体が一番大きくラベリングされるようにします。
7.押しすぎて全くラベリングされなくなったら、Jキーを押して閾値を上げます。
8.もう1つの物体を認識させたいときは、右クリックで画面上の物体の色を指定します。
9.2つの物体が一番大きくラベリングされるようになったらOKです、Fキーを押して元の画面に戻ります。
10.マーカーを表示し、マーカーと2つの物体の距離が表示されることを確認します。
11.2つの物体の距離を近づけて、カーソルがクリック状態になるかどうか(2つの物体間の線が赤くなる)を確認します。
12.マーカー上の立方体にカーソルを重ねて、クリック状態にします。
13.クリック状態でカーソルを移動すると、立方体も移動します。
14.立方体の移動中にクリックを解除すると、立方体の移動が止まります。
以上です。
まだ色の識別が甘いので、上手く認識しないかもしれません。
今後の課題です。
--- < ソースの概要 > ---
今回のプログラムでは、いくつかのクラスを追加しました。
・CCamerasRelationクラス:カメラ間の関係
・CStereoAnyColorPointクラス:指定色のステレオ処理を行う
・CFindColorPosInImgクラス:画像認識を行い、指定色のスクリーン上の座標等を計算
・CCamSimpleTriangulationクラス:3角測量を行う
以上のクラスは次のように使います。
1.インスタンスの定義
2.クラスの初期化
3.画像認識の計算
4.結果の取得
--- < 1.インスタンスの定義 > ---
改良したtwoView.cでは、以下のようにクラスのインスタンスを作成します。
--- < 2.クラスの初期化 > ---
次に、この変数を初期化します。
CCamerasRelationの初期化では、SetCamParamで各カメラに透視投影行列を設定します。
マーカーを認識できた時点で、もう1度別の初期化を行います
CCamerasRelationで、カメラ間の関係を計算します
--- < 3.画像認識の計算 > ---
必要な情報をセットできたら、画像処理を行います。
--- < 4.結果の取得 > ---
計算が上手くいったら、結果の3次元ベクトルを取得します
twoViewを使った、ステレオマッチングプログラムのソース公開です。
StereoAnyColor1.0.zip
--- < プログラムの使い方 > ---
0.Webカメラが2つあることが最低条件です。
ちなみに僕のは"Qcam Pro for Notebooks"。他のカメラでは試していないので、動くかどうかはわからないです。
あと、2つのカメラの設定を同じにしてください。
1.2つのカメラの向きを平行にして、まっすぐに並べる。
2.赤・黄・青など特徴的な色の物体を用意し、場所は白いテーブルの上など選んだ色が他にはないような所にする。
3.TwoViewに関する説明を読み、"WDM_camera_flipV_01.xml"、"WDM_camera_flipV_02.xml"を作成。
4.プログラムを起動して"Video Source 1"ウィンドウで、用意した特長的な色の物体を画面に表示して、それを左クリックします。
5.物体が画面に映っている状態で、Fキーを押してラベリング画像を表示。
6.Kキーを押して続けて閾値を下げ、目的の物体が一番大きくラベリングされるようにします。
7.押しすぎて全くラベリングされなくなったら、Jキーを押して閾値を上げます。
8.もう1つの物体を認識させたいときは、右クリックで画面上の物体の色を指定します。
9.2つの物体が一番大きくラベリングされるようになったらOKです、Fキーを押して元の画面に戻ります。
10.マーカーを表示し、マーカーと2つの物体の距離が表示されることを確認します。
11.2つの物体の距離を近づけて、カーソルがクリック状態になるかどうか(2つの物体間の線が赤くなる)を確認します。
12.マーカー上の立方体にカーソルを重ねて、クリック状態にします。
13.クリック状態でカーソルを移動すると、立方体も移動します。
14.立方体の移動中にクリックを解除すると、立方体の移動が止まります。
以上です。
まだ色の識別が甘いので、上手く認識しないかもしれません。
今後の課題です。
--- < ソースの概要 > ---
今回のプログラムでは、いくつかのクラスを追加しました。
・CCamerasRelationクラス:カメラ間の関係
・CStereoAnyColorPointクラス:指定色のステレオ処理を行う
・CFindColorPosInImgクラス:画像認識を行い、指定色のスクリーン上の座標等を計算
・CCamSimpleTriangulationクラス:3角測量を行う
以上のクラスは次のように使います。
1.インスタンスの定義
2.クラスの初期化
3.画像認識の計算
4.結果の取得
--- < 1.インスタンスの定義 > ---
改良したtwoView.cでは、以下のようにクラスのインスタンスを作成します。
CCamerasRelation gCamRelate(CONTEXTSACTIVECOUNT);今回はグローバル変数で定義しました。
CStereoAnyColorPoint g_stereoOperator;
--- < 2.クラスの初期化 > ---
次に、この変数を初期化します。
// グローバル変数の初期化CStereoAnyColorPointの初期化では、指定色をAddTargetColorで追加します。
static void InitGlobalValue()
{
// 画像認識の色を指定
g_stereoOperator.ClearTargetColor();
g_stereoOperator.AddTargetColor( g_cnColorRealRed );
g_stereoOperator.AddTargetColor( g_cnColorRealYellow );
// カメラの投影行列
gCamRelate.SetCamParam( 0, arParam.mat );
gCamRelate.SetCamParam( 1, arParam.mat );
}
CCamerasRelationの初期化では、SetCamParamで各カメラに透視投影行列を設定します。
マーカーを認識できた時点で、もう1度別の初期化を行います
CCamerasRelationで、カメラ間の関係を計算します
// 2つのカメラが、同じマーカーを認識できてるかどうかCStereoAnyColorPointでは、新しいカメラ画像をセット
if ( gContextsActive[0].id == gContextsActive[1].id )
{
// カメラ1の変換行列を保存
CopyArray3x4ToMatrix4x4( mtrxTemp1, gContextsActive[0].patt_trans );
CopyArray3x4ToMatrix4x4( mtrxTemp2, gContextsActive[1].patt_trans );
gCamRelate.CalcRelation(0, 1, mtrxTemp1, mtrxTemp2 );
}
g_stereoOperator.InitImgSource( arImXsize, arImYsize,
gContextsActive[0].ARTImage,
gContextsActive[1].ARTImage );
--- < 3.画像認識の計算 > ---
必要な情報をセットできたら、画像処理を行います。
g_stereoOperator.RecognitionColor3DPos(&gCamRelate);画像処理では、カメラの関係を引数として指定します。
--- < 4.結果の取得 > ---
計算が上手くいったら、結果の3次元ベクトルを取得します
for ( int iTarget = 0 ; iTarget < g_stereoOperator.GetTargetPosCount() ; iTarget++ )GetTargetPos(const int ciTarget, double dPos[3])で、指定色のベクトルを取得できます。
{
double dPos[3];
if ( !g_stereoOperator.GetTargetPos(iTarget, dPos) )
continue;
}
