/*
* PROJECT: NyARToolkitAS3
* --------------------------------------------------------------------------------
* This work is based on the original ARToolKit developed by
* Hirokazu Kato
* Mark Billinghurst
* HITLab, University of Washington, Seattle
* http://www.hitl.washington.edu/artoolkit/
*
* The NyARToolkitAS3 is AS3 edition ARToolKit class library.
* Copyright (C)2010 Ryo Iizuka
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* For further information please contact.
* http://nyatla.jp/nyatoolkit/
* or
*
*/
package jp.nyatla.nyartoolkit.as3.processor
{
import jp.nyatla.as3utils.*;
import jp.nyatla.nyartoolkit.as3.*;
import jp.nyatla.nyartoolkit.as3.core.*;
import jp.nyatla.nyartoolkit.as3.core.analyzer.raster.threshold.*;
import jp.nyatla.nyartoolkit.as3.core.match.*;
import jp.nyatla.nyartoolkit.as3.core.param.*;
import jp.nyatla.nyartoolkit.as3.core.pickup.*;
import jp.nyatla.nyartoolkit.as3.core.raster.*;
import jp.nyatla.nyartoolkit.as3.core.raster.rgb.*;
import jp.nyatla.nyartoolkit.as3.core.rasterfilter.rgb2bin.*;
import jp.nyatla.nyartoolkit.as3.core.squaredetect.*;
import jp.nyatla.nyartoolkit.as3.core.transmat.*;
import jp.nyatla.nyartoolkit.as3.core.types.*;
import jp.nyatla.nyartoolkit.as3.nyidmarker.data.*;
public class SingleNyIdMarkerProcesser
{
/**
* オーナーが自由に使えるタグ変数です。
*/
public var tag:Object;
/**
* ロスト遅延の管理
*/
private var _lost_delay_count:int = 0;
private var _lost_delay:int = 5;
private var _square_detect:NyARSquareContourDetector_Rle;
protected var _transmat:INyARTransMat;
private var _offset:NyARRectOffset;
private var _is_active:Boolean;
private var _current_threshold:int=110;
// [AR]検出結果の保存用
private var _bin_raster:NyARBinRaster;
private var _tobin_filter:NyARRasterFilter_ARToolkitThreshold;
private var _callback:DetectSquareCB;
private var _data_current:INyIdMarkerData;
public function SingleNyIdMarkerProcesser()
{
return;
}
private var _initialized:Boolean=false;
protected function initInstance(i_param:NyARParam, i_encoder:INyIdMarkerDataEncoder ,i_marker_width:Number, i_raster_format:int):void
{
//初期化済?
NyAS3Utils.assert(this._initialized==false);
var scr_size:NyARIntSize = i_param.getScreenSize();
// 解析オブジェクトを作る
this._square_detect = new NyARSquareContourDetector_Rle(scr_size);
this._transmat = new NyARTransMat(i_param);
this._callback=new DetectSquareCB(i_param,i_encoder);
// 2値画像バッファを作る
this._bin_raster = new NyARBinRaster(scr_size.w, scr_size.h);
//ワーク用のデータオブジェクトを2個作る
this._data_current=i_encoder.createDataInstance();
this._tobin_filter =new NyARRasterFilter_ARToolkitThreshold(110,i_raster_format);
this._threshold_detect=new NyARRasterThresholdAnalyzer_SlidePTile(15,i_raster_format,4);
this._initialized=true;
this._is_active=false;
this._offset = new NyARRectOffset();
this._offset.setSquare(i_marker_width);
return;
}
public function setMarkerWidth(i_width:int):void
{
this._offset.setSquare(i_width);
return;
}
public function reset(i_is_force:Boolean):void
{
if (i_is_force == false && this._is_active){
// 強制書き換えでなければイベントコール
this.onLeaveHandler();
}
//マーカ無効
this._is_active=false;
return;
}
public function detectMarker(i_raster:INyARRgbRaster):void
{
// サイズチェック
if (!this._bin_raster.getSize().isEqualSize_int(i_raster.getSize().w, i_raster.getSize().h)) {
throw new NyARException();
}
// ラスタを2値イメージに変換する.
this._tobin_filter.setThreshold(this._current_threshold);
this._tobin_filter.doFilter(i_raster, this._bin_raster);
// スクエアコードを探す(第二引数に指定したマーカ、もしくは新しいマーカを探す。)
this._callback.init(i_raster,this._is_active?this._data_current:null);
this._square_detect.detectMarkerCB(this._bin_raster, this._callback);
// 認識状態を更新(マーカを発見したなら、current_dataを渡すかんじ)
var is_id_found:Boolean=updateStatus(this._callback.square,this._callback.marker_data);
//閾値フィードバック(detectExistMarkerにもあるよ)
if(is_id_found){
//マーカがあれば、マーカの周辺閾値を反映
this._current_threshold=(this._current_threshold+this._callback.threshold)/2;
}else{
//マーカがなければ、探索+DualPTailで基準輝度検索
var th:int=this._threshold_detect.analyzeRaster(i_raster);
this._current_threshold=(this._current_threshold+th)/2;
}
return;
}
private var _threshold_detect:NyARRasterThresholdAnalyzer_SlidePTile;
private var __NyARSquare_result:NyARTransMatResult = new NyARTransMatResult();
/**オブジェクトのステータスを更新し、必要に応じてハンドル関数を駆動します。
*/
private function updateStatus(i_square:NyARSquare,i_marker_data:INyIdMarkerData):Boolean
{
var is_id_found:Boolean=false;
var result:NyARTransMatResult = this.__NyARSquare_result;
if (!this._is_active) {// 未認識中
if (i_marker_data==null) {// 未認識から未認識の遷移
// なにもしないよーん。
this._is_active=false;
} else {// 未認識から認識の遷移
this._data_current.copyFrom(i_marker_data);
// イベント生成
// OnEnter
this.onEnterHandler(this._data_current);
// 変換行列を作成
this._transmat.transMat(i_square, this._offset, result);
// OnUpdate
this.onUpdateHandler(i_square, result);
this._lost_delay_count = 0;
this._is_active=true;
is_id_found=true;
}
} else {// 認識中
if (i_marker_data==null) {
// 認識から未認識の遷移
this._lost_delay_count++;
if (this._lost_delay < this._lost_delay_count) {
// OnLeave
this.onLeaveHandler();
this._is_active=false;
}
} else if(this._data_current.isEqual(i_marker_data)) {
//同じidの再認識
this._transmat.transMatContinue(i_square, this._offset, result);
// OnUpdate
this.onUpdateHandler(i_square, result);
this._lost_delay_count = 0;
is_id_found=true;
} else {// 異なるコードの認識→今はサポートしない。
throw new NyARException();
}
}
return is_id_found;
}
//通知ハンドラ
protected function onEnterHandler(i_code:INyIdMarkerData):void
{
throw new NyARException("onEnterHandler not implemented.");
}
protected function onLeaveHandler():void
{
throw new NyARException("onLeaveHandler not implemented.");
}
protected function onUpdateHandler(i_square:NyARSquare, result:NyARTransMatResult):void
{
throw new NyARException("onUpdateHandler not implemented.");
}
}
}
import jp.nyatla.nyartoolkit.as3.core.param.*;
import jp.nyatla.nyartoolkit.as3.core.match.*;
import jp.nyatla.nyartoolkit.as3.core.pickup.*;
import jp.nyatla.nyartoolkit.as3.core.squaredetect.*;
import jp.nyatla.nyartoolkit.as3.core.transmat.*;
import jp.nyatla.nyartoolkit.as3.core.raster.*;
import jp.nyatla.nyartoolkit.as3.core.raster.rgb.*;
import jp.nyatla.nyartoolkit.as3.core.*;
import jp.nyatla.nyartoolkit.as3.core.rasterfilter.rgb2bin.*;
import jp.nyatla.nyartoolkit.as3.core.types.*;
import jp.nyatla.nyartoolkit.as3.*;
import jp.nyatla.nyartoolkit.as3.nyidmarker.data.*;
import jp.nyatla.nyartoolkit.as3.nyidmarker.*;
/**
* detectMarkerのコールバック関数
*/
class DetectSquareCB implements NyARSquareContourDetector_IDetectMarkerCallback
{
//公開プロパティ
public var square:NyARSquare=new NyARSquare();
public var marker_data:INyIdMarkerData;
public var threshold:int;
//参照
private var _ref_raster:INyARRgbRaster;
//所有インスタンス
private var _current_data:INyIdMarkerData;
private var _id_pickup:NyIdMarkerPickup = new NyIdMarkerPickup();
private var _coordline:NyARCoord2Linear;
private var _encoder:INyIdMarkerDataEncoder;
private var _data_temp:INyIdMarkerData;
private var _prev_data:INyIdMarkerData;
public function DetectSquareCB(i_param:NyARParam,i_encoder:INyIdMarkerDataEncoder)
{
this._coordline=new NyARCoord2Linear(i_param.getScreenSize(),i_param.getDistortionFactor());
this._data_temp=i_encoder.createDataInstance();
this._current_data=i_encoder.createDataInstance();
this._encoder=i_encoder;
return;
}
private var __tmp_vertex:Vector.=NyARIntPoint2d.createArray(4);
/**
* Initialize call back handler.
*/
public function init(i_raster:INyARRgbRaster,i_prev_data:INyIdMarkerData):void
{
this.marker_data=null;
this._prev_data=i_prev_data;
this._ref_raster=i_raster;
}
private var _marker_param:NyIdMarkerParam=new NyIdMarkerParam();
private var _marker_data:NyIdMarkerPattern =new NyIdMarkerPattern();
/**
* 矩形が見付かるたびに呼び出されます。
* 発見した矩形のパターンを検査して、方位を考慮した頂点データを確保します。
*/
public function onSquareDetect(i_sender:NyARSquareContourDetector,i_coordx:Vector.,i_coordy:Vector.,i_coor_num:int,i_vertex_index:Vector.):void
{
//既に発見済なら終了
if(this.marker_data!=null){
return;
}
//輪郭座標から頂点リストに変換
var vertex:Vector.=this.__tmp_vertex;
vertex[0].x=i_coordx[i_vertex_index[0]];
vertex[0].y=i_coordy[i_vertex_index[0]];
vertex[1].x=i_coordx[i_vertex_index[1]];
vertex[1].y=i_coordy[i_vertex_index[1]];
vertex[2].x=i_coordx[i_vertex_index[2]];
vertex[2].y=i_coordy[i_vertex_index[2]];
vertex[3].x=i_coordx[i_vertex_index[3]];
vertex[3].y=i_coordy[i_vertex_index[3]];
var param:NyIdMarkerParam=this._marker_param;
var patt_data:NyIdMarkerPattern=this._marker_data;
// 評価基準になるパターンをイメージから切り出す
if (!this._id_pickup.pickFromRaster(this._ref_raster,vertex, patt_data, param)){
return;
}
//エンコード
if(!this._encoder.encode(patt_data,this._data_temp)){
return;
}
//継続認識要求されている?
if (this._prev_data==null){
//継続認識要求なし
this._current_data.copyFrom(this._data_temp);
}else{
//継続認識要求あり
if(!this._prev_data.isEqual((this._data_temp))){
return;//認識請求のあったIDと違う。
}
}
//新しく認識、または継続認識中に更新があったときだけ、Square情報を更新する。
//ココから先はこの条件でしか実行されない。
var sq:NyARSquare=this.square;
//directionを考慮して、squareを更新する。
var i:int;
for(i=0;i<4;i++){
var idx:int=(i+4 - param.direction) % 4;
this._coordline.coord2Line(i_vertex_index[idx],i_vertex_index[(idx+1)%4],i_coordx,i_coordy,i_coor_num,sq.line[i]);
}
for (i= 0; i < 4; i++) {
//直線同士の交点計算
if(!NyARLinear.crossPos(sq.line[i],sq.line[(i + 3) % 4],sq.sqvertex[i])){
throw new NyARException();//ここのエラー復帰するならダブルバッファにすればOK
}
}
this.threshold=param.threshold;
this.marker_data=this._current_data;//みつかった。
}
}