FLARToolKit

FLARToolKit version 2.x

Section 7 詳細説明 - ソースコード解説 3

前回に引き続きコード説明です。
最後はメインループの部分を説明します。

メインループ処理

このあたりの作り方にはルールは特になく、サンプルの中でも3種類の方法を用いて実装しています。
今回の説明で使っているものは、イベント処理方式で、FLARManagerでも採用されている振り分け方です。

まずはフレームごとに毎回呼ばれる部分を見てみましょう。

“SimpleCube.as”

/**
 * ここで処理振り分けを行っている
 */
public function run(e:Event):void
{
	this.capture.bitmapData.draw(this.video);

	// Marker detect
	var detected:Boolean = false;
	try {
		detected = this.detector.detectMarkerLite(this.raster, this._threshold) && this.detector.getConfidence() > 0.5;
	} catch (e:Error) {}

	// 認識時の処理
	if (detected) {
		// 一工夫できる場所
		// 前回認識した場所と今回認識した場所の距離を測り、
		// 一定範囲なら位置情報更新 MARKER_UPDATED を発行するなど、
		// 楽しい工夫が出来る。 参照: FLARManager
		this.dispatchEvent(new MarkerEvent(MarkerEvent.MARKER_ADDED));
	// 非認識時
	} else {
		this.dispatchEvent(new MarkerEvent(MarkerEvent.MARKER_REMOVED));
		// マーカがなければ、探索+DualPTailで基準輝度検索
		// マーカーが見つからない場合、処理が重くなるので状況に応じてコメントアウトすると良い
		var th:int=this._threshold_detect.analyzeRaster(this.raster);
		this._threshold=(this._threshold+th)/2;
	}
	this.renderer.render();
}

細かく見ていきましょう。

“SimpleCube.as”

var detected:Boolean = false;
try {
	detected = this.detector.detectMarkerLite(this.raster, this._threshold) && this.detector.getConfidence() > 0.5;
} catch (e:Error) {}

マーカー認識部分です。 this.rasterは、動画中から取り出した一枚の画像。 this._thresholdは二値化する時のしきい値になります。

その次の部分this.detector.getConfidence()は検出したマーカーの一致率を調べています。 この値を小さくすれば、低い一致率でも検出したことになるので誤認識が増えます。 大きくすれば一致率が高い場合でないと認識した事にならないので誤認識は減りますが、検出しづらい状態にもなります。 使用用途に応じて調整した方が良いです。

“SimpleCube.as”

// 認識時の処理
if (detected) {
	// 一工夫できる場所
	// 前回認識した場所と今回認識した場所の距離を測り、
	// 一定範囲なら位置情報更新 MARKER_UPDATED を発行するなど、
	// 楽しい工夫が出来る。 参照: FLARManager
	this.dispatchEvent(new MarkerEvent(MarkerEvent.MARKER_ADDED));
// 非認識時
} else {
	this.dispatchEvent(new MarkerEvent(MarkerEvent.MARKER_REMOVED));
	// マーカがなければ、探索+DualPTailで基準輝度検索
	// マーカーが見つからない場合、処理が重くなるので状況に応じてコメントアウトすると良い
	var th:int=this._threshold_detect.analyzeRaster(this.raster);
	this._threshold=(this._threshold+th)/2;
}

マーカー認識結果に応じて処理を分けます。
それぞれの状態に応じて、dispatchEventでイベントを発行しています。

イベントはstart()内で登録しています。

“SimpleCube.as”

// マーカー認識・非認識時用のイベントを登録
this.addEventListener(MarkerEvent.MARKER_ADDED, this.onMarkerAdded);
this.addEventListener(MarkerEvent.MARKER_UPDATED, this.onMarkerUpdated);
this.addEventListener(MarkerEvent.MARKER_REMOVED, this.onMarkerRemoved);

継続認識中を示すUpdate処理を含めていませんが、実装のヒントはコメントに書かれている通りです。
dispatchEventの代わりに、ここから説明する3Dオブジェクト描画の処理を埋め込んでも良いのですが、ネストが深くなるのでこのような作りにしています。

なお、Update処理部分まで含まれているのがFLARManagerです。

では、それぞれの処理部分を見てみましょう。

“SimpleCube.as”

/**
 * マーカーを認識するとこの処理が呼ばれる
 */
public function onMarkerAdded(e:Event=null):void
{
	this.detector.getTransformMatrix(this.resultMat);
	this.markerNode.setTransformMatrix(this.resultMat);
	this.markerNode.visible = true;
}

マーカー検出時は、座標変換行列と呼ばれるMatrixが取得できます。
getTransformMatrixで取得して、MarkerNodeにsetTransformMatrixであたえるということになります。
その後、visible で表示状態にしています。この部分で resultMat を確保しておけば、前回の位置情報と比較したりすることができるわけです。

マーカーが検出できなかった場合は、下記の通り。

“SimpleCube.as”

/**
 * マーカーが認識できなくなるとこれが呼ばれる
 */
public function onMarkerRemoved(e:Event=null):void
{
	this.markerNode.visible = false;
}

単純に visible を切り替えているだけです。
ここを工夫して、消えるまでのdelay処理を埋め込んだりすることも可能になりますので、チャレンジしてみてください。

まとめ

かなり適当に書いているので、適切じゃない部分など数多くあります。
あくまできっかけ程度にしてください。