/** * RealityTargetに一致するID値を特定します。 * 複数のパターンにヒットしたときは、一番初めにヒットした項目を返します。 * @param i_target * Realityが検出したターゲット。 * Unknownターゲットを指定すること。 * @param i_rtsorce * i_targetを検出したRealitySourceインスタンス。 * @param o_result * 返却値を格納するインスタンスを設定します。 * 返却値がtrueの場合のみ、内容が更新されています。 * @return * 特定に成功すると、trueを返します。 * @throws NyARException */ public bool identifyId(NyARRealityTarget i_target, NyARRealitySource i_rtsorce, IdentifyIdResult o_result) { //NyARDoublePoint2d[] i_vertex,NyARRgbRaster i_raster,SelectResult o_result return(this.identifyId( ((NyARRectTargetStatus)(i_target._ref_tracktarget._ref_status)).vertex, i_rtsorce.refRgbSource(), o_result)); }
/** * 指定したシリアル番号のUnknownターゲットを、Knownターゲットへ移動します。 * @param i_serial * ターゲットのシリアル番号を示す値 * @param i_dir * ターゲットの予備知識。ARToolkitのdirectionでどの方位であるかを示す値 * @param i_marker_width * ターゲットの予備知識。マーカーのサイズがいくらであるかを示す値[mm単位] * @return * 成功すると、trueを返します。 * @throws NyARException */ public bool ChangeTargetToKnownBySerial(long i_serial, int i_dir, double i_marker_width) { NyARRealityTarget item = this.target.getItemBySerial(i_serial); if (item == null) { return(false); } return(ChangeTargetToKnown(item, i_dir, i_marker_width)); }
/** * 指定したシリアル番号のKnown/UnknownターゲットをDeadターゲットへ遷移します。 * @param i_serial * @throws NyARException */ public NyARRealityTarget ChangeTargetToDeadBySerial(long i_serial) { NyARRealityTarget item = this.target.getItemBySerial(i_serial); if (item == null) { return(null); } ChangeTargetToDead(item); return(item); }
/** * 指定したターゲットを、UnknownターゲットからKnownターゲットへ遷移させます。 * @param i_item * 移動するターゲット * @param i_dir * ターゲットの予備知識。ARToolkitのdirectionでどの方位であるかを示す値 * @param i_marker_width * ターゲットの予備知識。マーカーの高さがいくらであるかを示す値[mm単位] * @param i_marker_height * ターゲットの予備知識。マーカーの幅がいくらであるかを示す値[mm単位] * @return * 成功するとtrueを返します。 * @throws NyARException */ public bool ChangeTargetToKnown(NyARRealityTarget i_item, int i_dir, double i_marker_width, double i_marker_height) { //遷移元制限 if (i_item._target_type != NyARRealityTarget.RT_UNKNOWN) { return(false); } //ステータス制限 if (i_item._ref_tracktarget._st_type != NyARTargetStatus.ST_RECT) { return(false); } //個数制限 if (this._number_of_known >= this.MAX_LIMIT_KNOWN) { return(false); } //ステータス制限 i_item._target_type = NyARRealityTarget.RT_KNOWN; //マーカのサイズを決めておく。 i_item._offset.setSquare(i_marker_width, i_marker_height); //directionに応じて、元矩形のrectを回転しておく。 ((NyARRectTargetStatus)(i_item._ref_tracktarget._ref_status)).shiftByArtkDirection((4 - i_dir) % 4); //矩形セット NyARDoublePoint2d[] vx = ((NyARRectTargetStatus)(i_item._ref_tracktarget._ref_status)).vertex; for (int i = 3; i >= 0; i--) { i_item._screen_square.sqvertex[i].setValue(vx[i]); i_item._screen_square.line[i].makeLinearWithNormalize(vx[i], vx[(i + 1) % 4]); } //3d座標計算 if (!this._transmat.transMat(i_item._screen_square, i_item._offset, i_item._transform_matrix, i_item._result_param)) { return(false); } //数の調整 this._number_of_unknown--; this._number_of_known++; return(true); }
/** * Realityターゲットリストの全ての項目のアップグレード処理を行います。この関数内でリスト要素の加算/減算/種別変更処理を行います。 * {@link #progress}のサブ関数です。 * @throws NyARException */ private void UpdateLists() { NyARRealityTarget[] rt_array = this.target.getArray(); for (int i = this.target.getLength() - 1; i >= 0; i--) { NyARRealityTarget tar = rt_array[i]; if (tar._ref_tracktarget._delay_tick == 0) { //30fps前後で1秒間の認識率とする。 tar.grab_rate += 3; if (tar.grab_rate > 100) { tar.grab_rate = 100; } switch (tar._target_type) { case NyARRealityTarget.RT_DEAD: //何もしない continue; case NyARRealityTarget.RT_KNOWN: //矩形座標計算 SetSquare(((NyARRectTargetStatus)(tar._ref_tracktarget._ref_status)).vertex, tar._screen_square); //3d座標計算 // this._transmat.transMat(tar._screen_square,tar._offset,tar._transform_matrix); this._transmat.transMatContinue(tar._screen_square, tar._offset, tar._transform_matrix, tar._result_param.last_error, tar._transform_matrix, tar._result_param); continue; case NyARRealityTarget.RT_UNKNOWN: continue; default: break; } } else { //更新をパスして補足レートの再計算(混ぜて8で割る) tar.grab_rate = tar.grab_rate - (3 * tar._ref_tracktarget._delay_tick); if (tar.grab_rate < 0) { tar.grab_rate = 0; } } } }
//RealityTargetの編集関数 /** * Realityターゲットリストへ新しい{@link NyARRealityTarget}を追加する。 * @param i_track_target * UnknownTargetに関連付ける{@link NyARTarget}.このターゲットは、{@link NyARTargetStatus#ST_RECT}であること? */ private NyARRealityTarget AddUnknownTarget(NyARTarget i_track_target) { Debug.Assert(i_track_target._st_type == NyARTargetStatus.ST_RECT); NyARRealityTarget rt = this._pool.newNewTarget(i_track_target); if (rt == null) { return(null); } //個数制限 if (this._number_of_unknown >= this.MAX_LIMIT_UNKNOWN) { return(null); } rt._target_type = NyARRealityTarget.RT_UNKNOWN; this.target.pushAssert(rt); this._number_of_unknown++; return(rt); }
/** * 指定したKnown,またはUnknownターゲットを、Deadターゲットにします。 * Deadターゲットは次回のサイクルでRealityターゲットリストから削除され、一定のサイクル期間の間システムから無視されます。 * @param i_item * @param i_dead_cycle * 無視するサイクルを指定します。1サイクルは1フレームです。デフォルトは50です。 * @throws NyARException */ public void ChangeTargetToDead(NyARRealityTarget i_item, int i_dead_cycle) { Debug.Assert(i_item._target_type == NyARRealityTarget.RT_UNKNOWN || i_item._target_type == NyARRealityTarget.RT_KNOWN); //IG検出して遷移した場合 if (i_item._ref_tracktarget._st_type != NyARTargetStatus.ST_IGNORE) { //所有するトラックターゲットがIGNOREに設定 this._tracker.changeStatusToIgnore(i_item._ref_tracktarget, i_dead_cycle); } //数の調整 if (i_item._target_type == NyARRealityTarget.RT_UNKNOWN) { this._number_of_unknown--; } else { this._number_of_known--; } i_item._target_type = NyARRealityTarget.RT_DEAD; this._number_of_dead++; return; }
/** * RealityTargetに最も一致するパターンをテーブルから検索して、メタデータを返します。 * @param i_target * Realityが検出したターゲット。 * Unknownターゲットを指定すること。 * @param i_rtsorce * i_targetを検出したRealitySourceインスタンス。 * @param o_result * 返却値を格納するインスタンスを設定します。 * 返却値がtrueの場合のみ、内容が更新されています。 * @return * 特定に成功すると、trueを返します。 * @throws NyARException */ public bool getBestMatchTarget(NyARRealityTarget i_target, NyARRealitySource i_rtsorce, GetBestMatchTargetResult o_result) { //パターン抽出 NyARMatchPattResult tmp_patt_result = this.__tmp_patt_result; INyARPerspectiveCopy r = i_rtsorce.refPerspectiveRasterReader(); r.copyPatt(i_target.refTargetVertex(), this._edge_x, this._edge_y, this._sample_per_pix, this._tmp_raster); //比較パターン生成 this._deviation_data.setRaster(this._tmp_raster); int ret = -1; int dir = -1; double cf = Double.MinValue; for (int i = this._table.getLength() - 1; i >= 0; i--) { this._match_patt.setARCode(this._table.getItem(i).code); this._match_patt.evaluate(this._deviation_data, tmp_patt_result); if (cf < tmp_patt_result.confidence) { ret = i; cf = tmp_patt_result.confidence; dir = tmp_patt_result.direction; } } if (ret < 0) { return(false); } //戻り値を設定 MarkerTable.SerialTableRow row = this._table.getItem(ret); o_result.artk_direction = dir; o_result.confidence = cf; o_result.idtag = row.idtag; o_result.marker_height = row.marker_height; o_result.marker_width = row.marker_width; o_result.name = row.name; return(true); }
/** * 指定したKnown,またはUnknownターゲットを、50サイクルの間Deadターゲットにします。 * Deadターゲットは次回のサイクルでRealityターゲットリストから削除され、一定のサイクル期間の間システムから無視されます。 * @param i_item * @throws NyARException */ public void ChangeTargetToDead(NyARRealityTarget i_item) { ChangeTargetToDead(i_item, 50); }
//////////////////////////////////////////////////////////////////////////////// //Public: //RealityTargetの操作関数 // //////////////////////////////////////////////////////////////////////////////// /** * 指定したターゲットを、UnknownターゲットからKnownターゲットへ遷移させます。 * @param i_item * 移動するターゲット * @param i_dir * ターゲットの予備知識。ARToolkitのdirectionでどの方位であるかを示す値 * @param i_marker_size * ターゲットの予備知識。マーカーの高さ/幅がいくらであるかを示す値[mm単位] * @return * 成功するとtrueを返します。 * @throws NyARException */ public bool ChangeTargetToKnown(NyARRealityTarget i_item, int i_dir, double i_marker_size) { return(ChangeTargetToKnown(i_item, i_dir, i_marker_size, i_marker_size)); }
/** * Unknown/Knownを維持できる条件を書きます。 * @param i_target * @return */ private bool IsTargetAlive(NyARRealityTarget i_target) { return(i_target._ref_tracktarget._st_type == NyARTargetStatus.ST_RECT); }
/** * Unknownターゲットを検索して、配列に返します。 * @param o_result * 結果を格納する配列です。格納されるターゲットの最大数は、コンストラクタの設定値と同じです。 * 配列サイズが不足した場合は、発見した順に最大数を返します。 * @return * 配列に格納したターゲットの数を返します。 */ public int SelectUnKnownTargets(NyARRealityTarget[] o_result) { return this.target.selectTargetsByType(NyARRealityTarget.RT_UNKNOWN, o_result); }
/** * i_targetの大きさを推定して、{@link UnknownRectInfo}に結果を保存します。この関数は{@link UnknownRectInfo}の状態を変化させるだけです。 * @param i_target * 大きさを推定するターゲット。 * @param io_result * 入出力パラメータ。前段までの推定結果と現在の推定値をマージして返します。 * はじめてターゲットの推定をするときは、リセットした{@link UnknownRectInfo}を入力してください。 * @return * 認識状況を返します。 * @throws NyARException */ public void detectCardDirection(NyARRealityTarget i_target, UnknownRectInfo io_result) { //成功点数が20点を超えたら推定完了。 if (io_result._success_point > 20) { io_result.last_status = ESTIMATE_COMPLETE; return; } //10回失敗したら推定失敗 if (io_result._failed > 10) { io_result.last_status = FAILED_ESTIMATE; return; } NyARDoublePoint2d[] pos = i_target.refTargetVertex(); //正面から一回認識させてほしい。 for (int i = 0; i < 4; i++) { //正面判定。辺のなす角が90、または-90度の10度以内であること。 if (getAbsSin(pos[0 + i], pos[(1 + i) % 4], pos[(2 + i) % 4]) < 0.984) { io_result.last_status = MORE_FRONT_CENTER; return; } } //線の長さを4本計算 double d1 = Math.Sqrt(pos[0].sqDist(pos[1])); double d2 = Math.Sqrt(pos[1].sqDist(pos[2])); double d3 = Math.Sqrt(pos[2].sqDist(pos[3])); double d4 = Math.Sqrt(pos[3].sqDist(pos[0])); //現在の比率を計算 double t, t2, t3; t = d1 + d3 * 0.5; t2 = d2 + d4 * 0.5; t3 = t / t2; t3 = t3 < 1 ? 1 / t3 : t3; if (io_result._target_serial == NyARRealityTarget.INVALID_REALITY_TARGET_ID) { //サイクルをリセット io_result._target_serial = i_target.getSerialId(); io_result.rate = t3; io_result._success_point = 0; io_result._failed = 0; io_result.artk_direction = t < t2 ? 1 : 0; } else { if (io_result._target_serial != i_target.getSerialId()) { //ターゲットが一致しない。 io_result.last_status = FAILED_TARGET_MISSMATCH; return; } if (t3 / io_result.rate > 0.98 && t3 / io_result.rate < 1.02) { io_result.rate = (io_result.rate + t3) * 0.5; io_result._success_point++; } else { io_result._failed++; } } //推定中 io_result.last_status = ESTIMATE_NOW; return; }
/** * このターゲットについて、非同期に認識依頼を出します。このプログラムはサンプルなので、別スレッドでIDマーカ判定をして、 * 三秒後に適当なサイズとDirectionを返却するだけです。 * @param i_target * @return * @throws NyARException */ public void requestAsyncMarkerDetect(NyARReality i_reality, NyARRealitySource i_source, NyARRealityTarget i_target) { //ターゲットから画像データなどを取得するときは、スレッドからではなく、ここで同期して取得してコピーしてからスレッドに引き渡します。 //100x100の領域を切りだして、Rasterを作る。 NyARRgbRaster raster = new NyARRgbRaster(100, 100, NyARBufferType.INT1D_X8R8G8B8_32); i_reality.GetRgbPatt2d(i_source, i_target.refTargetVertex(), 1, raster); //コピーしたラスタとターゲットのIDをスレッドへ引き渡す。 Thread t = new Thread(new AsyncThread(this, i_target.getSerialId(), raster).Run); t.Start(); return; }
/** * Unknown/Knownを維持できる条件を書きます。 * @param i_target * @return */ private bool IsTargetAlive(NyARRealityTarget i_target) { return i_target._ref_tracktarget._st_type == NyARTargetStatus.ST_RECT; }
//////////////////////////////////////////////////////////////////////////////// //Public: //RealityTargetの操作関数 // //////////////////////////////////////////////////////////////////////////////// /** * 指定したターゲットを、UnknownターゲットからKnownターゲットへ遷移させます。 * @param i_item * 移動するターゲット * @param i_dir * ターゲットの予備知識。ARToolkitのdirectionでどの方位であるかを示す値 * @param i_marker_size * ターゲットの予備知識。マーカーの高さ/幅がいくらであるかを示す値[mm単位] * @return * 成功するとtrueを返します。 * @throws NyARException */ public bool ChangeTargetToKnown(NyARRealityTarget i_item, int i_dir, double i_marker_size) { return ChangeTargetToKnown(i_item, i_dir, i_marker_size, i_marker_size); }
/** * 指定したターゲットを、UnknownターゲットからKnownターゲットへ遷移させます。 * @param i_item * 移動するターゲット * @param i_dir * ターゲットの予備知識。ARToolkitのdirectionでどの方位であるかを示す値 * @param i_marker_width * ターゲットの予備知識。マーカーの高さがいくらであるかを示す値[mm単位] * @param i_marker_height * ターゲットの予備知識。マーカーの幅がいくらであるかを示す値[mm単位] * @return * 成功するとtrueを返します。 * @throws NyARException */ public bool ChangeTargetToKnown(NyARRealityTarget i_item, int i_dir, double i_marker_width, double i_marker_height) { //遷移元制限 if (i_item._target_type != NyARRealityTarget.RT_UNKNOWN) { return false; } //ステータス制限 if (i_item._ref_tracktarget._st_type != NyARTargetStatus.ST_RECT) { return false; } //個数制限 if (this._number_of_known >= this.MAX_LIMIT_KNOWN) { return false; } //ステータス制限 i_item._target_type = NyARRealityTarget.RT_KNOWN; //マーカのサイズを決めておく。 i_item._offset.setSquare(i_marker_width, i_marker_height); //directionに応じて、元矩形のrectを回転しておく。 ((NyARRectTargetStatus)(i_item._ref_tracktarget._ref_status)).shiftByArtkDirection((4 - i_dir) % 4); //矩形セット NyARDoublePoint2d[] vx = ((NyARRectTargetStatus)(i_item._ref_tracktarget._ref_status)).vertex; for (int i = 3; i >= 0; i--) { i_item._screen_square.sqvertex[i].setValue(vx[i]); i_item._screen_square.line[i].makeLinearWithNormalize(vx[i], vx[(i + 1) % 4]); } //3d座標計算 if (!this._transmat.transMat(i_item._screen_square, i_item._offset, i_item._transform_matrix, i_item._result_param)) { return false; } //数の調整 this._number_of_unknown--; this._number_of_known++; return true; }