/** * 予想位置を基準に四角形をトレースして、一定の基準をクリアするかを評価します。 * @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); }
public bool traceConture(int i_th, NyARIntPoint2d i_entry, VecLinearCoordinates o_coord) { NyARIntCoordinates coord = this._coord_buf; // Robertsラスタから輪郭抽出 if (!this._cpickup.getContour(this._ref_rob_raster, i_th, i_entry.x, i_entry.y, coord)) { // 輪郭線MAXならなにもできないね。 return(false); } // 輪郭線のベクトル化 return(traceConture(coord, this._rob_resolution, this._rob_resolution * 2, o_coord)); }
/** * 値をセットします。この関数は、処理の成功失敗に関わらず、内容変更を行います。 * @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_pos1 * @param i_pos2 * @param i_edge * @param o_coord * @return * @throws NyARException */ public bool traceLineWithClip(NyARDoublePoint2d i_pos1, NyARDoublePoint2d i_pos2, int i_edge, VecLinearCoordinates o_coord) { NyARIntSize s = this._ref_base_raster.getSize(); bool is_p1_inside_area, is_p2_inside_area; NyARIntPoint2d[] pt = this.__pt; // 線分が範囲内にあるかを確認 is_p1_inside_area = s.isInnerPoint(i_pos1); is_p2_inside_area = s.isInnerPoint(i_pos2); // 個数で分岐 if (is_p1_inside_area && is_p2_inside_area) { // 2ならクリッピング必要なし。 if (!this.traceLine(i_pos1, i_pos2, i_edge, o_coord)) { return(false); } return(true); } // 1,0個の場合は、線分を再定義 if (!this.__temp_l.makeLinearWithNormalize(i_pos1, i_pos2)) { return(false); } if (!this.__temp_l.makeSegmentLine(s.w, s.h, pt)) { return(false); } if (is_p1_inside_area != is_p2_inside_area) { // 1ならクリッピング後に、外に出ていた点に近い輪郭交点を得る。 if (is_p1_inside_area) { // p2が範囲外 pt[(i_pos2.sqDist(pt[0]) < i_pos2.sqDist(pt[1])) ? 1 : 0].setValue(i_pos1); } else { // p1が範囲外 pt[(i_pos1.sqDist(pt[0]) < i_pos2.sqDist(pt[1])) ? 1 : 0].setValue(i_pos2); } } else { // 0ならクリッピングして得られた2点を使う。 if (!this.__temp_l.makeLinearWithNormalize(i_pos1, i_pos2)) { return(false); } if (!this.__temp_l.makeSegmentLine(s.w, s.h, pt)) { return(false); } } if (!this.traceLine(pt[0], pt[1], i_edge, o_coord)) { return(false); } return(true); }
/** * 輪郭線を取得します。 * 取得アルゴリズムは、以下の通りです。 * 1.輪郭座標(n)の画素周辺の画素ベクトルを取得。 * 2.輪郭座標(n+1)周辺の画素ベクトルと比較。 * 3.差分が一定以下なら、座標と強度を保存 * 4.3点以上の集合になったら、最小二乗法で直線を計算。 * 5.直線の加重値を個々の画素ベクトルの和として返却。 */ public bool traceConture(NyARIntCoordinates i_coord, int i_pos_mag, int i_cell_size, VecLinearCoordinates o_coord) { VecLinearCoordinates.VecLinearCoordinatePoint[] pos = this._tmp_coord_pos; // ベクトル化 int MAX_COORD = o_coord.items.Length; int i_coordlen = i_coord.length; NyARIntPoint2d[] coord = i_coord.items; VecLinearCoordinates.VecLinearCoordinatePoint pos_ptr; //0個目のライン探索 int number_of_data = 0; int sq; long sq_sum = 0; //0番目のピクセル pos[0].scalar = sq = this.getAreaVector33(coord[0].x * i_pos_mag, coord[0].y * i_pos_mag, i_cell_size, i_cell_size, pos[0]); sq_sum += (int)sq; //[2]に0を保管 //1点目だけは前方と後方、両方に探索をかける。 //前方探索の終点 int coord_last_edge = i_coordlen; //後方探索 int sum = 1; double ave_dx = pos[0].dx; double ave_dy = pos[0].dy; for (int i = i_coordlen - 1; i > 0; i--) { // ベクトル取得 pos_ptr = pos[sum]; pos_ptr.scalar = sq = this.getAreaVector33(coord[i].x * i_pos_mag, coord[i].y * i_pos_mag, i_cell_size, i_cell_size, pos_ptr); sq_sum += (int)sq; // 類似度判定 if (checkVecCos(pos[sum], pos[sum - 1], ave_dx, ave_dy)) { //相関なし->前方探索へ。 ave_dx = pos_ptr.dx; ave_dy = pos_ptr.dy; coord_last_edge = i; break; } else { //相関あり- 点の蓄積 ave_dx += pos_ptr.dx; ave_dy += pos_ptr.dy; sum++; } } //前方探索 for (int i = 1; i < coord_last_edge; i++) { // ベクトル取得 pos_ptr = pos[sum]; pos_ptr.scalar = sq = this.getAreaVector33(coord[i].x * i_pos_mag, coord[i].y * i_pos_mag, i_cell_size, i_cell_size, pos_ptr); sq_sum += (int)sq; if (sq == 0) { continue; } //if (pos_ptr.getAbsVecCos(pos[sum-1]) < NyARMath.COS_DEG_5 && pos_ptr.getAbsVecCos(ave_dx,ave_dy)<NyARMath.COS_DEG_20) { if (checkVecCos(pos[sum], pos[sum - 1], ave_dx, ave_dy)) { //相関なし->新しい要素を作る。 if (this.leastSquaresWithNormalize(pos, sum, o_coord.items[number_of_data], sq_sum / (sum * 5))) { number_of_data++; } ave_dx = pos_ptr.dx; ave_dy = pos_ptr.dy; //獲得した値を0へ移動 pos[0].setValue(pos[sum]); sq_sum = 0; sum = 1; } else { //相関あり- 点の蓄積 ave_dx += pos_ptr.dx; ave_dy += pos_ptr.dy; sum++; } // 輪郭中心を出すための計算 if (number_of_data == MAX_COORD) { // 輪郭ベクトルバッファの最大を超えたら失敗 return(false); } } if (this.leastSquaresWithNormalize(pos, sum, o_coord.items[number_of_data], sq_sum / (sum * 5))) { number_of_data++; } // ベクトル化2:最後尾と先頭の要素が似ていれば連結する。 // sq_distの合計を計算 o_coord.length = number_of_data; return(true); }
public bool traceLine(NyARDoublePoint2d i_pos1, NyARDoublePoint2d i_pos2, int i_edge, VecLinearCoordinates o_coord) { NyARIntCoordinates coord = this._coord_buf; NyARIntSize base_s = this._ref_base_raster.getSize(); // (i_area*2)の矩形が範囲内に収まるように線を引く // 移動量 // 点間距離を計算 int dist = (int)Math.Sqrt(i_pos1.sqDist(i_pos2)); // 最低AREA*2以上の大きさが無いなら、ラインのトレースは不可能。 if (dist < 4) { return(false); } // dist最大数の決定 if (dist > 12) { dist = 12; } // サンプリングサイズを決定(移動速度とサイズから) int s = i_edge * 2 + 1; int dx = (int)(i_pos2.x - i_pos1.x); int dy = (int)(i_pos2.y - i_pos1.y); int r = base_s.w - s; int b = base_s.h - s; // 最大24点を定義して、そのうち両端の2個を除いた点を使用する。 for (int i = 1; i < dist - 1; i++) { int x = (int)(i * dx / dist + i_pos1.x - i_edge); int y = (int)(i * dy / dist + i_pos1.y - i_edge); // limit coord.items[i - 1].x = x < 0 ? 0 : (x >= r ? r : x); coord.items[i - 1].y = y < 0 ? 0 : (y >= b ? b : y); } coord.length = dist - 2; // 点数は10点程度を得る。 return(traceConture(coord, 1, s, o_coord)); }