ARToolKit プログラムの仕組み
1: ヘッダファイルのインクルード 2: Main 関数 3: Main Loop 関数 4: マウス入力処理関数 5: キーボード入力処理関数 6: 終了処理関数 ARUint8 *image; ARMarkerInfo *marker_info; int marker_num; int j, k; ARVideoGetImage()関数によって,ビデオデバイス(USB カメラ)から画像を取得する. この関数は画像データへのポインタを返す.ポインタの型はARUnit8 というオリジナルの型だが,これはunsigned char 型と同じ.ARToolKit では画像データを格納するためのバ ッファを内部に持っていて,自前でメモリを管理する必要はない. 3: Main Loop 関数 ①カメラ画像の取得 ②カメラ画像の描画 ③マーカの検出と認識 ④次の画像のキャプチャ指示 ⑤マーカの信頼度の比較 ⑥マーカの位置・姿勢の計算 ⑦バッファの内容を画面に表示 //メインループ関数--- void MainLoop(void)
{ ARUint8 *image; ARMarkerInfo *marker_info; int marker_num; int j, k; //カメラ画像の取得
if((image = (ARUint8 *)arVideoGetImage()) == NULL) { arUtilSleep(2);
return; }
①カメラ画像の取得 //カメラ画像の取得
if((image = (ARUint8 *)arVideoGetImage()) == NULL) {
↑ビデオデバイス(USBカメラ)から画像を取得→ 画像データへのポインタ arUtilSleep(2); ↑スリープ.()の中は休止時間 return; } 画像の準備ができていない時はNULL を返す.画像データが準備できないと以後の処理を 行えないので,arUtilSleep()によって適当なスリープ(休止時間)を置いた後,一度メイ ンループを抜ける ②カメラ画像の描画 argDrawMode2D(); argDispImage( image, 0, 0 ); AR アプリケーションではカメラ画像を描画した後で,3Dオブジェクトを重ねて描画する. ARToolKit ではカメラ画像を描画する際にレンズによるゆがみの補正も行うようになって いる.カメラ画像を描画するためには,まずargDrawMode2D()という関数によって2次元 画像を描画するための準備をした後でargDispImage()関数を使って画像を描画する. argDispImage( image: image 画像データへのポインタ 0 : xwin 表示領域の番号(表示領域が1つしかない場合は“0”) 0 : ywin 〃 ) //カメラ画像の描画 argDrawMode2D(); argDispImage( image, 0, 0 );
xwin と ywin は,ウィンドウ内に複数の表示領域を設けた際に,描画する場所を指定する ために使う.
③マーカの検出と認識
if( arDetectMarker( image, thresh, &marker_info, &marker_num) < 0){ Cleanup(); exit(0); } カ メ ラ 画 像 の 中 か ら マ ー カ を 見 つ け , そ の マ ー カ の パ タ ー ン を 認 識 す る 関 数 が arDetectMarker()である. arDetectMarker( image :dataPtr 画像データへのポインタ thresh : 二値化の閾値(ARToolKit では,画像を二値化して検出) &marker_info : マーカ情報を格納する配列へのポインタ ↑ARToolKit では,検出したマーカの情報を内部のバッファに保存している.そのバッファ へのポインタを marker_info が返す仕組みになっている. &marker_num : 検出されたマーカの数 ) //マーカの検出と認識
if( arDetectMarker( image, thresh, &marker_info, &marker_num) < 0){ Cleanup();
exit(0); }
④次の画像のキャプチャ画像 arVideoCapNext(); 取得した画像について画像の描画とマーカの検出が終わったら,次の画像の指令を出す必 要がある.次フレームのキャプチャを支持するには arVideoCapNext();を使う. ⑤マーカの信頼度の比較 マーカとして検出される領域の中にはマーカではない領域(誤検出)も含まれる. マーカごとに対応したオブジェクトを正しく表示するためには,検出されたマーカの中か ら特定のパターンIDをもち,かつ最も高い信頼度を持つものを探し出す必要がある. k = -1; for(j =0; j < marker_num; j++ ){ if (patt_id == marker_info[j].id ){ if( k == -1) k = j;
else if ( marker_info[k].cf < marker_info[j].cf ) k = j; } } //次の画像のキャプチャ指示 arVideoCapNext(); //マーカの信頼度の比較 k = -1; for(j =0; j < marker_num; j++ ){ if (patt_id == marker_info[j].id ){ if( k == -1) k = j;
elseif ( marker_info[k].cf < marker_info[j].cf ) k = j; }
for ループを抜けると,パターンID((marker_info[j].id)=カメラでとらえた画像) が patt_id(検出されるマーカ)に一致し,かつ信頼度(marker_info[j].cf)が最も高いマ ーカの番号が変数 k に格納される. パターン ID が一致するものが無ければ k=-1 となる.複数のマーカを扱う場合は,パター ンIDごとにこの処理を行う必要がある. ⑥マーカの位置・姿勢の計算 この arGetTransMat()では検出されたマーカの情報からマーカ・カメラ間の座標変換行列を 求めている.「座標変換行列」とは,ここでいうカメラに対するマーカの三次元位置・姿 勢のことである. arGetTransMat ↑座標変換行列を求める. ( &marker_info[k], : marker_info マーカ情報を格納した変数へのポインタ patt_center, : center マーカの原点位置(マーカ上のどこに原点を置くか) patt_width, : width マーカのサイズ patt_trans : conv マーカ・カメラ間の座標変換行列(マーカ座標系をカメラ 座標系)が返ってくる ); Conv[3][4]は, 3×4の行列になっている. マーカ位置・姿勢を計算した後は3Dオブジェクトの描画処理を行う.サンプルプログラ ムでは,描画処理の部分を DrawObject()という関数にまとめる. if ( k != -1){ //マーカの位置・姿勢(座標変換行列)の計算
arGetTransMat( &marker_info[k], patt_center,
patt_width, patt_trans );
//3Dオブジェクトの描画
DrawObject(); }
⑦バッファの内容を画面に表示する ARToolKit のグラフィックス処理系ではダブルバッファが使われている. ダブルバッファとは,画像やCGを連続で描画する際にちらつきが起きないようにするた めの仕組みである.画面のちらつきが起きるのは描画している過程が見えてしまうためで あり,表画面(フロントバッファ)と裏画面(バックバッファ)という2つのバッファを 用意して,表画面を表示している間に裏画面に描画し,表と裏を入れ替えることにより描 画の過程が見えないようにする. argSwapBuffers()関数は表画面と裏画面を入れ替える関数であり,これによって以前の描 画処理が画面に反映される. //バッファの内容を画面に表示 argSwapBuffers();