/** * 予想位置を基準に四角形をトレースして、一定の基準をクリアするかを評価します。 * @param i_reader * @param i_edge_size * @param i_prevsq * @return * @throws NyARException */ private bool traceSquareLine(INyARVectorReader i_reader, int i_edge_size, NyARRectTargetStatus i_prevsq, NyARLinear[] o_line) { NyARDoublePoint2d p1, p2; VecLinearCoordinates vecpos = this._ref_my_pool._vecpos; //NyARIntRect i_rect p1 = i_prevsq.estimate_vertex[0]; int dist_limit = i_edge_size * i_edge_size; //強度敷居値(セルサイズ-1) // int min_th=i_edge_size*2+1; // min_th=(min_th*min_th); for (int i = 0; i < 4; i++) { p2 = i_prevsq.estimate_vertex[(i + 1) % 4]; //クリップ付きで予想位置周辺の直線のトレース i_reader.traceLineWithClip(p1, p2, i_edge_size, vecpos); //クラスタリングして、傾きの近いベクトルを探す。(限界は10度) this._ref_my_pool._vecpos_op.margeResembleCoords(vecpos); //基本的には1番でかいベクトルだよね。だって、直線状に取るんだもの。 int vid = vecpos.getMaxCoordIndex(); //データ品質規制(強度が多少強くないと。) // if(vecpos.items[vid].sq_dist<(min_th)){ // return false; // } //@todo:パラメタ調整 //角度規制(元の線分との角度を確認) if (vecpos.items[vid].getAbsVecCos(i_prevsq.vertex[i], i_prevsq.vertex[(i + 1) % 4]) < NyARMath.COS_DEG_5) { //System.out.println("CODE1"); return(false); } //@todo:パラメタ調整 //予想点からさほど外れていない点であるか。(検出点の移動距離を計算する。) double dist; dist = vecpos.items[vid].sqDistBySegmentLineEdge(i_prevsq.vertex[i], i_prevsq.vertex[i]); if (dist < dist_limit) { o_line[i].setVectorWithNormalize(vecpos.items[vid]); } else { //System.out.println("CODE2:"+dist+","+dist_limit); return(false); } //頂点ポインタの移動 p1 = p2; } return(true); }
/** * 状況に応じて矩形選択手法を切り替えます。 * @param i_vec_reader * サンプリングデータの基本画像にリンクしたVectorReader * @param i_source * サンプリングデータ * @param i_prev_status * 前回の状態を格納したオブジェクト * @return * @throws NyARException */ public bool setValueByAutoSelect(INyARVectorReader i_vec_reader, LowResolutionLabelingSamplerOut.Item i_source, NyARRectTargetStatus i_prev_status) { int current_detect_type = DT_SQDAILY; //移動速度による手段の切り替え int sq_v_ave_limit = i_prev_status.estimate_sum_sq_vertex_velocity_ave / 4; //速度が小さい時か、前回LineLogが成功したときはDT_LIDAILY if (((sq_v_ave_limit < 10) && (i_prev_status.detect_type == DT_SQDAILY)) || (i_prev_status.detect_type == DT_LIDAILY)) { current_detect_type = DT_LIDAILY; } //前回の動作ログによる手段の切り替え switch (current_detect_type) { case DT_LIDAILY: //LineLog-> if (setValueByLineLog(i_vec_reader, i_prev_status)) { //うまくいった。 this.detect_type = DT_LIDAILY; return(true); } if (i_source != null) { if (setValueWithDeilyCheck(i_vec_reader, i_source, i_prev_status)) { //うまくいった this.detect_type = DT_SQDAILY; return(true); } } break; case DT_SQDAILY: if (i_source != null) { if (setValueWithDeilyCheck(i_vec_reader, i_source, i_prev_status)) { this.detect_type = DT_SQDAILY; return(true); } } break; default: break; } //前回の動作ログを書き換え i_prev_status.detect_type = DT_FAILED; return(false); }
/** * 輪郭からの単独検出 * @param i_raster * @param i_prev_status * @return * @throws NyARException */ public bool setValueByLineLog(INyARVectorReader i_vec_reader, NyARRectTargetStatus i_prev_status) { //検出範囲からカーネルサイズの2乗値を計算。検出領域の二乗距離の1/(40*40) (元距離の1/40) int d = ((int)i_prev_status.estimate_rect.getDiagonalSqDist() / (NyARMath.SQ_40)); //二乗移動速度からカーネルサイズを計算。 int v_ave_limit = i_prev_status.estimate_sum_sq_vertex_velocity_ave; // if (v_ave_limit > d) { //移動カーネルサイズより、検出範囲カーネルのほうが大きかったらエラー(動きすぎ) return(false); } d = (int)Math.Sqrt(d); //最低でも2だよね。 if (d < 2) { d = 2; } //最大カーネルサイズ(5)を超える場合は5にする。 if (d > 5) { d = 5; } //ライントレースの試行 NyARLinear[] sh_l = this._ref_my_pool._line; if (!traceSquareLine(i_vec_reader, d, i_prev_status, sh_l)) { return(false); } else { } //4点抽出 for (int i = 3; i >= 0; i--) { if (!sh_l[i].crossPos(sh_l[(i + 3) % 4], this.vertex[i])) { //四角が作れない。 return(false); } } //頂点並び順の調整 rotateVertexL(this.vertex, checkVertexShiftValue(i_prev_status.vertex, this.vertex)); //差分パラメータのセット setEstimateParam(i_prev_status); return(true); }
/** * i_new_targetのアップグレードを試行します。 * アップグレードの種類は以下のにとおりです。1.一定期間経過後の破棄ルート(Ignoreへ遷移)2.正常認識ルート(Contourへ遷移) * @param i_new_target * @param i_base_raster * @return * @throws NyARException */ private void upgradeNewTarget(NyARTarget i_new_target, INyARVectorReader i_vecreader) { Debug.Assert(i_new_target._st_type == NyARTargetStatus.ST_NEW); //寿命を超えたらignoreへ遷移 if (i_new_target._status_life <= 0) { this.changeStatusToIgnore(i_new_target, LIFE_OF_IGNORE_FROM_NEW); return; } NyARNewTargetStatus st = (NyARNewTargetStatus)i_new_target._ref_status; //このターゲットをアップグレードできるか確認 if (st.current_sampleout == null) { //直近のsampleoutが無い。->なにもできない。 return; } //coordステータスを生成 NyARContourTargetStatus c = this.contourst_pool.newObject(); if (c == null) { //ターゲットがいっぱい。(失敗して何もしない) // System.out.println("upgradeNewTarget:status pool full"); return; } //ステータスの値をセット if (!c.setValue(i_vecreader, st.current_sampleout)) { //値のセットに失敗したので、Ignoreへ遷移(この対象は輪郭認識できない) this.changeStatusToIgnore(i_new_target, LIFE_OF_IGNORE_FROM_NEW); //System.out.println("drop:new->ignore[contoure failed.]"+t.serial+":"+t.last_update); c.releaseObject(); return; //失敗しようが成功しようが終了 } if (this.changeStatusToCntoure(i_new_target, c) == null) { c.releaseObject(); return; } return; }
/** * ContoureTargetのステータスを更新します。 * @param i_list * @param i_vecreader * @param i_stpool * @param source * @param index * @throws NyARException */ public static void updateContureStatus(NyARTargetList i_list, INyARVectorReader i_vecreader, NyARContourTargetStatusPool i_stpool, LowResolutionLabelingSamplerOut.Item[] source, int[] index) { NyARTarget[] crd = i_list.getArray(); NyARTarget d_ptr; //ターゲットの更新 for (int i = i_list.getLength() - 1; i >= 0; i--) { d_ptr = crd[i]; int sample_index = index[i]; //年齢を加算 d_ptr._status_life--; if (sample_index < 0) { //このターゲットに合致するアイテムは無い。 d_ptr._delay_tick++; continue; } LowResolutionLabelingSamplerOut.Item s = source[sample_index]; //失敗の可能性を考慮して、Statusを先に生成しておく NyARContourTargetStatus st = i_stpool.newObject(); if (st == null) { //失敗(作れなかった?) d_ptr._delay_tick++; continue; } if (!st.setValue(i_vecreader, s)) { //新しいステータスのセットに失敗? st.releaseObject(); d_ptr._delay_tick++; continue; } d_ptr.setSampleArea(s); d_ptr._delay_tick = 0; //ref_statusの切り替え d_ptr._ref_status.releaseObject(); d_ptr._ref_status = st; } }
public static void updateRectStatus(NyARTargetList i_list, INyARVectorReader i_vecreader, NyARRectTargetStatusPool i_stpool, LowResolutionLabelingSamplerOut.Item[] source, int[] index) { NyARTarget[] rct = i_list.getArray(); NyARTarget d_ptr; //ターゲットの更新 for (int i = i_list.getLength() - 1; i >= 0; i--) { d_ptr = rct[i]; //年齢を加算 d_ptr._status_life--; //新しいステータスの作成 NyARRectTargetStatus st = i_stpool.newObject(); if (st == null) { //失敗(作れなかった?) d_ptr._delay_tick++; continue; } int sample_index = index[i]; LowResolutionLabelingSamplerOut.Item s = sample_index < 0?null:source[sample_index]; if (!st.setValueByAutoSelect(i_vecreader, s, (NyARRectTargetStatus)d_ptr._ref_status)) { st.releaseObject(); d_ptr._delay_tick++; continue; } else { if (s != null) { d_ptr.setSampleArea(s); } } d_ptr._ref_status.releaseObject(); d_ptr._ref_status = st; d_ptr._delay_tick = 0; } }
/** * 値をセットします。この関数は、処理の成功失敗に関わらず、内容変更を行います。 * @param i_sampler_in * @param i_source * @param i_prev_status * @return * @throws NyARException */ public bool setValueWithDeilyCheck(INyARVectorReader i_vec_reader, LowResolutionLabelingSamplerOut.Item i_source, NyARRectTargetStatus i_prev_status) { VecLinearCoordinates vecpos = this._ref_my_pool._vecpos; //輪郭線を取る if (!i_vec_reader.traceConture(i_source.lebeling_th, i_source.entry_pos, vecpos)) { return(false); } //3,4象限方向のベクトルは1,2象限のベクトルに変換する。 vecpos.limitQuadrantTo12(); //ベクトルのマージ this._ref_my_pool._vecpos_op.margeResembleCoords(vecpos); if (vecpos.length < 4) { return(false); } //キーベクトルを取得 vecpos.getKeyCoord(this._ref_my_pool._indexbuf); //点に変換 NyARDoublePoint2d[] this_vx = this.vertex; if (!this._ref_my_pool._line_detect.line2SquareVertex(this._ref_my_pool._indexbuf, this_vx)) { return(false); } //頂点並び順の調整 rotateVertexL(this.vertex, checkVertexShiftValue(i_prev_status.vertex, this.vertex)); //パラメタチェック if (!checkDeilyRectCondition(i_prev_status)) { return(false); } //次回の予測 setEstimateParam(i_prev_status); return(true); }
/** * @param i_vecreader * @param i_sample * @return * @throws NyARException */ public bool setValue(INyARVectorReader i_vecreader, LowResolutionLabelingSamplerOut.Item i_sample) { return i_vecreader.traceConture(i_sample.lebeling_th, i_sample.entry_pos, this.vecpos); }
/** * Trackerの状態を更新します。 * @param i_source * @throws NyARException */ public void progress(NyARTrackerSource i_s) { //SampleOutを回収 LowResolutionLabelingSamplerOut sample_out = i_s.makeSampleOut(); NyARTargetList[] targets = this._temp_targets; NyARTargetList newtr = targets[NyARTargetStatus.ST_NEW]; NyARTargetList igtr = targets[NyARTargetStatus.ST_IGNORE]; NyARTargetList cotr = targets[NyARTargetStatus.ST_CONTURE]; NyARTargetList retw = targets[NyARTargetStatus.ST_RECT]; INyARVectorReader vecreader = i_s.getBaseVectorReader(); //ターゲットリストの振り分け NyARTarget[] target_array = this._targets.getArray(); newtr.clear(); igtr.clear(); cotr.clear(); retw.clear(); for (int i = this._targets.getLength() - 1; i >= 0; i--) { targets[target_array[i]._st_type].pushAssert(target_array[i]); } int[] index = this._index; //サンプルをターゲット毎に振り分け sampleMapper(sample_out, newtr, igtr, cotr, retw, this._newsource, this._igsource, this._coordsource, this._rectsource); //ターゲットの更新 this._map.makePairIndexes(this._igsource, igtr, index); updateIgnoreStatus(igtr, this._igsource.getArray(), index); this._map.makePairIndexes(this._newsource, newtr, index); updateNewStatus(newtr, this.newst_pool, this._newsource.getArray(), index); this._map.makePairIndexes(this._rectsource, retw, index); updateRectStatus(retw, vecreader, this.rect_pool, this._rectsource.getArray(), index); this._map.makePairIndexes(this._coordsource, cotr, index); updateContureStatus(cotr, vecreader, this.contourst_pool, this._coordsource.getArray(), index); //ターゲットのアップグレード for (int i = this._targets.getLength() - 1; i >= 0; i--) { switch (target_array[i]._st_type) { case NyARTargetStatus.ST_IGNORE: upgradeIgnoreTarget(i); continue; case NyARTargetStatus.ST_NEW: upgradeNewTarget(target_array[i], vecreader); continue; case NyARTargetStatus.ST_RECT: upgradeRectTarget(target_array[i]); continue; case NyARTargetStatus.ST_CONTURE: upgradeContourTarget(target_array[i]); continue; } } return; }
/** * 予想位置を基準に四角形をトレースして、一定の基準をクリアするかを評価します。 * @param i_reader * @param i_edge_size * @param i_prevsq * @return * @throws NyARException */ private bool traceSquareLine(INyARVectorReader i_reader, int i_edge_size, NyARRectTargetStatus i_prevsq, NyARLinear[] o_line) { NyARDoublePoint2d p1,p2; VecLinearCoordinates vecpos=this._ref_my_pool._vecpos; //NyARIntRect i_rect p1=i_prevsq.estimate_vertex[0]; int dist_limit=i_edge_size*i_edge_size; //強度敷居値(セルサイズ-1) // int min_th=i_edge_size*2+1; // min_th=(min_th*min_th); for(int i=0;i<4;i++) { p2=i_prevsq.estimate_vertex[(i+1)%4]; //クリップ付きで予想位置周辺の直線のトレース i_reader.traceLineWithClip(p1,p2,i_edge_size,vecpos); //クラスタリングして、傾きの近いベクトルを探す。(限界は10度) this._ref_my_pool._vecpos_op.margeResembleCoords(vecpos); //基本的には1番でかいベクトルだよね。だって、直線状に取るんだもの。 int vid=vecpos.getMaxCoordIndex(); //データ品質規制(強度が多少強くないと。) // if(vecpos.items[vid].sq_dist<(min_th)){ // return false; // } //@todo:パラメタ調整 //角度規制(元の線分との角度を確認) if(vecpos.items[vid].getAbsVecCos(i_prevsq.vertex[i],i_prevsq.vertex[(i+1)%4])<NyARMath.COS_DEG_5){ //System.out.println("CODE1"); return false; } //@todo:パラメタ調整 //予想点からさほど外れていない点であるか。(検出点の移動距離を計算する。) double dist; dist=vecpos.items[vid].sqDistBySegmentLineEdge(i_prevsq.vertex[i],i_prevsq.vertex[i]); if(dist<dist_limit){ o_line[i].setVectorWithNormalize(vecpos.items[vid]); }else{ //System.out.println("CODE2:"+dist+","+dist_limit); return false; } //頂点ポインタの移動 p1=p2; } return true; }
/** * 状況に応じて矩形選択手法を切り替えます。 * @param i_vec_reader * サンプリングデータの基本画像にリンクしたVectorReader * @param i_source * サンプリングデータ * @param i_prev_status * 前回の状態を格納したオブジェクト * @return * @throws NyARException */ public bool setValueByAutoSelect(INyARVectorReader i_vec_reader, LowResolutionLabelingSamplerOut.Item i_source, NyARRectTargetStatus i_prev_status) { int current_detect_type=DT_SQDAILY; //移動速度による手段の切り替え int sq_v_ave_limit=i_prev_status.estimate_sum_sq_vertex_velocity_ave/4; //速度が小さい時か、前回LineLogが成功したときはDT_LIDAILY if(((sq_v_ave_limit<10) && (i_prev_status.detect_type==DT_SQDAILY)) || (i_prev_status.detect_type==DT_LIDAILY)){ current_detect_type=DT_LIDAILY; } //前回の動作ログによる手段の切り替え switch(current_detect_type) { case DT_LIDAILY: //LineLog-> if(setValueByLineLog(i_vec_reader,i_prev_status)) { //うまくいった。 this.detect_type=DT_LIDAILY; return true; } if(i_source!=null){ if(setValueWithDeilyCheck(i_vec_reader,i_source,i_prev_status)) { //うまくいった this.detect_type=DT_SQDAILY; return true; } } break; case DT_SQDAILY: if(i_source!=null){ if(setValueWithDeilyCheck(i_vec_reader,i_source,i_prev_status)) { this.detect_type=DT_SQDAILY; return true; } } break; default: break; } //前回の動作ログを書き換え i_prev_status.detect_type=DT_FAILED; return false; }
/** * 輪郭からの単独検出 * @param i_raster * @param i_prev_status * @return * @throws NyARException */ public bool setValueByLineLog(INyARVectorReader i_vec_reader, NyARRectTargetStatus i_prev_status) { //検出範囲からカーネルサイズの2乗値を計算。検出領域の二乗距離の1/(40*40) (元距離の1/40) int d=((int)i_prev_status.estimate_rect.getDiagonalSqDist()/(NyARMath.SQ_40)); //二乗移動速度からカーネルサイズを計算。 int v_ave_limit=i_prev_status.estimate_sum_sq_vertex_velocity_ave; // if(v_ave_limit>d){ //移動カーネルサイズより、検出範囲カーネルのほうが大きかったらエラー(動きすぎ) return false; } d=(int)Math.Sqrt(d); //最低でも2だよね。 if(d<2){ d=2; } //最大カーネルサイズ(5)を超える場合は5にする。 if(d>5){ d=5; } //ライントレースの試行 NyARLinear[] sh_l=this._ref_my_pool._line; if(!traceSquareLine(i_vec_reader,d,i_prev_status,sh_l)){ return false; }else{ } //4点抽出 for(int i=3;i>=0;i--){ if(!sh_l[i].crossPos(sh_l[(i + 3) % 4],this.vertex[i])){ //四角が作れない。 return false; } } //頂点並び順の調整 rotateVertexL(this.vertex,checkVertexShiftValue(i_prev_status.vertex,this.vertex)); //差分パラメータのセット setEstimateParam(i_prev_status); return true; }
/** * 値をセットします。この関数は、処理の成功失敗に関わらず、内容変更を行います。 * @param i_sampler_in * @param i_source * @param i_prev_status * @return * @throws NyARException */ public bool setValueWithDeilyCheck(INyARVectorReader i_vec_reader, LowResolutionLabelingSamplerOut.Item i_source, NyARRectTargetStatus i_prev_status) { VecLinearCoordinates vecpos=this._ref_my_pool._vecpos; //輪郭線を取る if(!i_vec_reader.traceConture(i_source.lebeling_th,i_source.entry_pos,vecpos)){ return false; } //3,4象限方向のベクトルは1,2象限のベクトルに変換する。 vecpos.limitQuadrantTo12(); //ベクトルのマージ this._ref_my_pool._vecpos_op.margeResembleCoords(vecpos); if(vecpos.length<4){ return false; } //キーベクトルを取得 vecpos.getKeyCoord(this._ref_my_pool._indexbuf); //点に変換 NyARDoublePoint2d[] this_vx=this.vertex; if(!this._ref_my_pool._line_detect.line2SquareVertex(this._ref_my_pool._indexbuf,this_vx)){ return false; } //頂点並び順の調整 rotateVertexL(this.vertex,checkVertexShiftValue(i_prev_status.vertex,this.vertex)); //パラメタチェック if(!checkDeilyRectCondition(i_prev_status)){ return false; } //次回の予測 setEstimateParam(i_prev_status); return true; }
/** * @param i_vecreader * @param i_sample * @return * @throws NyARException */ public bool setValue(INyARVectorReader i_vecreader, LowResolutionLabelingSamplerOut.Item i_sample) { return(i_vecreader.traceConture(i_sample.lebeling_th, i_sample.entry_pos, this.vecpos)); }