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