示例#1
0
 /**
  * コンストラクタです。
  * 入力画像のサイズを指定して、インスタンスを生成します。
  * @param i_size
  * 入力画像のサイズ
  */
 public NyARSquareContourDetector_Rle(NyARIntSize i_size)
 {
     this.setupImageDriver(i_size);
     //ラベリングのサイズを指定したいときはsetAreaRangeを使ってね。
     this._coord = new NyARIntCoordinates((i_size.w + i_size.h) * 2);
     return;
 }
 /**
  * コンストラクタです。
  * 入力画像のサイズを指定して、インスタンスを生成します。
  * @param i_size
  * 入力画像のサイズ
  */
 public NyARSquareContourDetector_Rle(NyARIntSize i_size)
 {
     this.setupImageDriver(i_size);
     //ラベリングのサイズを指定したいときはsetAreaRangeを使ってね。
     this._coord = new NyARIntCoordinates((i_size.w + i_size.h) * 2);
     return;
 }
示例#3
0
        public override bool getContour(int i_l, int i_t, int i_r, int i_b, int i_entry_x, int i_entry_y, int i_th, NyARIntCoordinates o_coord)
        {
            Debug.Assert(i_t <= i_entry_x);
            int[] buf   = (int[])this._ref_raster.getBuffer();
            int[] xdir  = _getContour_xdir;   // static int xdir[8] = { 0, 1, 1, 1, 0,-1,-1,-1};
            int[] ydir  = _getContour_ydir;   // static int ydir[8] = {-1,-1, 0, 1, 1, 1, 0,-1};
            int   width = this._ref_raster.getWidth();

            //クリップ領域の上端に接しているポイントを得る。
            NyARIntPoint2d[] coord = o_coord.items;
            int max_coord          = o_coord.items.Length;

            coord[0].x = i_entry_x;
            coord[0].y = i_entry_y;
            int coord_num = 1;
            int dir       = 5;

            int c = i_entry_x;
            int r = i_entry_y;

            for (;;)
            {
                dir = (dir + 5) % 8;        //dirの正規化
                //ここは頑張ればもっと最適化できると思うよ。
                //4隅以外の境界接地の場合に、境界チェックを省略するとかね。
                if (c > i_l && c < i_r && r > i_t && r < i_b)
                {
                    for (;;)            //gotoのエミュレート用のfor文
                                        //境界に接していないとき(暗点判定)
                    {
                        if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th)
                        {
                            break;
                        }
                        dir++;
                        if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th)
                        {
                            break;
                        }
                        dir++;
                        if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th)
                        {
                            break;
                        }
                        dir++;
                        if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th)
                        {
                            break;
                        }
                        dir++;
                        if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th)
                        {
                            break;
                        }
                        dir++;
                        if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th)
                        {
                            break;
                        }
                        dir++;
                        if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th)
                        {
                            break;
                        }
                        dir++;
                        if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th)
                        {
                            break;
                        }
                        //8方向全て調べたけどラベルが無いよ?
                        throw new NyARException();
                    }
                }
                else
                {
                    //境界に接しているとき
                    int i;
                    for (i = 0; i < 8; i++)
                    {
                        int x = c + xdir[dir];
                        int y = r + ydir[dir];
                        //境界チェック
                        if (x >= i_l && x <= i_r && y >= i_t && y <= i_b)
                        {
                            if (buf[(y) * width + (x)] <= i_th)
                            {
                                break;
                            }
                        }
                        dir++;                //倍長テーブルを参照するので問題なし
                    }
                    if (i == 8)
                    {
                        //8方向全て調べたけどラベルが無いよ?
                        throw new NyARException();                // return(-1);
                    }
                }
                // xcoordとycoordをc,rにも保存
                c = c + xdir[dir];
                r = r + ydir[dir];
                coord[coord_num].x = c;
                coord[coord_num].y = r;
                //終了条件判定
                if (c == i_entry_x && r == i_entry_y)
                {
                    //開始点と同じピクセルに到達したら、終点の可能性がある。
                    coord_num++;
                    //末端のチェック
                    if (coord_num == max_coord)
                    {
                        //輪郭bufが末端に達した
                        return(false);
                    }
                    //末端候補の次のピクセルを調べる
                    dir = (dir + 5) % 8;            //dirの正規化
                    int i;
                    for (i = 0; i < 8; i++)
                    {
                        int x = c + xdir[dir];
                        int y = r + ydir[dir];
                        //境界チェック
                        if (x >= i_l && x <= i_r && y >= i_t && y <= i_b)
                        {
                            if (buf[(y) * width + (x)] <= i_th)
                            {
                                break;
                            }
                        }
                        dir++;                //倍長テーブルを参照するので問題なし
                    }
                    if (i == 8)
                    {
                        //8方向全て調べたけどラベルが無いよ?
                        throw new NyARException();
                    }
                    //得たピクセルが、[1]と同じならば、末端である。
                    c = c + xdir[dir];
                    r = r + ydir[dir];
                    if (coord[1].x == c && coord[1].y == r)
                    {
                        //終点に達している。
                        o_coord.length = coord_num;
                        break;
                    }
                    else
                    {
                        //終点ではない。
                        coord[coord_num].x = c;
                        coord[coord_num].y = r;
                    }
                }
                coord_num++;
                //末端のチェック
                if (coord_num == max_coord)
                {
                    //輪郭が末端に達した
                    return(false);
                }
            }
            return(true);
        }
示例#4
0
 public abstract bool getContour(int i_l, int i_t, int i_r, int i_b, int i_entry_x, int i_entry_y, int i_th, NyARIntCoordinates o_coord);
示例#5
0
 /**
  * この関数は、ラスタの指定点を基点に、画像の特定の範囲内から輪郭線を抽出します。
  * 開始点は、輪郭の一部である必要があります。
  * 通常は、ラべリングの結果の上辺クリップとX軸エントリポイントを開始点として入力します。
  * @param i_raster
  * 輪郭線を抽出するラスタを指定します。
  * @param i_area
  * 輪郭線の抽出範囲を指定する矩形。i_rasterのサイズ内である必要があります。
  * @param i_th
  * 輪郭とみなす暗点の敷居値を指定します。
  * @param i_entry_x
  * 輪郭抽出の開始点です。
  * @param i_entry_y
  * 輪郭抽出の開始点です。
  * @param o_coord
  * 輪郭点を格納するオブジェクトを指定します。
  * @return
  * 輪郭線がo_coordの長さを超えた場合、falseを返します。
  * @
  */
 public bool getContour(INyARGrayscaleRaster i_raster, NyARIntRect i_area, int i_th, int i_entry_x, int i_entry_y, NyARIntCoordinates o_coord)
 {
     //ラスタドライバの切り替え
     if (i_raster != this._ref_last_input_raster)
     {
         this._imdriver = (IRasterDriver)i_raster.createInterface(typeof(IRasterDriver));
         this._ref_last_input_raster = i_raster;
     }
     return(this._imdriver.getContour(i_area.x, i_area.y, i_area.x + i_area.w - 1, i_area.h + i_area.y - 1, i_entry_x, i_entry_y, i_th, o_coord));
 }
示例#6
0
        /**
         * この関数は、ラスタから矩形を検出して、自己コールバック関数{@link #onSquareDetect}で通知します。
         * ARToolKitのarDetectMarker2を基にしています。
         * @param i_raster
         * 検出元のラスタ画像
         * 入力できるラスタの画素形式は、{@link NyARLabeling_Rle#labeling(NyARGrayscaleRaster, int)}と同じです。
         * @param i_th
         * 画素の二値判定敷居値です。この値は、ラベリングと、輪郭線追跡時に使われます。
         */
        public void detectMarker(INyARGrayscaleRaster i_raster, int i_th, NyARSquareContourDetector.CbHandler i_cb)
        {
            NyARRleLabelFragmentInfoPtrStack flagment = this._labeling.label_stack;
            NyARLabelOverlapChecker <NyARRleLabelFragmentInfo> overlap = this._overlap_checker;

            flagment.clear();
            //ラベルの生成エラーならここまで
            if (!this._labeling.labeling(i_raster, i_th))
            {
                return;
            }
            int label_num = flagment.getLength();

            // ラベル数が0ならここまで
            if (label_num < 1)
            {
                return;
            }
            //ラベルをソートしておく
            flagment.sortByArea();
            //ラベルリストを取得
            NyARRleLabelFragmentInfo[] labels = flagment.getArray();

            NyARIntCoordinates coord = this._coord;

            int[] mkvertex = this.__detectMarker_mkvertex;


            //重なりチェッカの最大数を設定
            overlap.setMaxLabels(label_num);

            for (int i = 0; i < label_num; i++)
            {
                NyARRleLabelFragmentInfo label_pt = labels[i];
                int label_area = label_pt.area;

                // 既に検出された矩形との重なりを確認
                if (!overlap.check(label_pt))
                {
                    // 重なっているようだ。
                    continue;
                }
                //輪郭を取得
                if (!this._cpickup.getContour(i_raster, i_th, label_pt.entry_x, label_pt.clip_t, coord))
                {
                    continue;
                }
                //輪郭線をチェックして、矩形かどうかを判定。矩形ならばmkvertexに取得
                if (!this._coord2vertex.getVertexIndexes(coord, label_area, mkvertex))
                {
                    // 頂点の取得が出来なかった
                    continue;
                }
                //矩形を発見したことをコールバック関数で通知
                i_cb.detectMarkerCallback(coord, mkvertex);

                // 検出済の矩形の属したラベルを重なりチェックに追加する。
                overlap.push(label_pt);
            }
            return;
        }
 /**
  * 継承クラスのコンストラクタから呼び出す。
  * @param i_ref_raster
  * 基本画像
  * @param i_ref_raster_distortion
  * 歪み解除オブジェクト(nullの場合歪み解除を省略)
  * @param i_ref_rob_raster
  * エッジ探索用のROB画像
  * @param i_contour_pickup
  * 輪郭線取得クラス
  * @param
  */
 public void initInstance(NyARGrayscaleRaster i_ref_raster,INyARCameraDistortionFactor i_ref_raster_distortion,NyARGrayscaleRaster i_ref_rob_raster,NyARContourPickup i_contour_pickup)
 {
     this._rob_resolution=i_ref_raster.getWidth()/i_ref_rob_raster.getWidth();
     this._ref_rob_raster=i_ref_rob_raster;
     this._ref_base_raster=i_ref_raster;
     this._coord_buf = new NyARIntCoordinates((i_ref_raster.getWidth() + i_ref_raster.getHeight()) * 4);
     this._factor=i_ref_raster_distortion;
     this._tmp_coord_pos = VecLinearCoordinates.VecLinearCoordinatePoint.createArray(this._coord_buf.items.Length);
     this._cpickup = i_contour_pickup;
     return;
 }
        /**
         * 内部関数です。
         * この関数は、thisの二次元矩形情報プロパティを更新します。
         * @param i_coord
         * @param i_vertex_index
         * @
         */
        protected internal void updateSquareInfo(NyARIntCoordinates i_coord, int[] i_vertex_index)
        {
            NyARMatchPattResult mr = this.__detectMarkerLite_mr;
              //輪郭座標から頂点リストに変換
              NyARIntPoint2d[] vertex = this.__ref_vertex;  //C言語ならポインタ扱いで実装
              vertex[0] = i_coord.items[i_vertex_index[0]];
              vertex[1] = i_coord.items[i_vertex_index[1]];
              vertex[2] = i_coord.items[i_vertex_index[2]];
              vertex[3] = i_coord.items[i_vertex_index[3]];

              //画像を取得
              if (!this._inst_patt.pickFromRaster(this._last_input_raster, vertex)) { return; }

              //取得パターンをカラー差分データに変換して評価する。
              this._deviation_data.setRaster(this._inst_patt);
              if (!this._match_patt.evaluate(this._deviation_data, mr)) { return; }

              //現在の一致率より低ければ終了
              if (this._confidence > mr.confidence) { return; }

              //一致率の高い矩形があれば、方位を考慮して頂点情報を作成
              NyARSquare sq = this._square;
              this._confidence = mr.confidence;

              //directionを考慮して、squareを更新する。
              for (int i = 0; i < 4; i++) {
            int idx = (i + 4 - mr.direction) % 4;
            this._coordline.coord2Line(i_vertex_index[idx], i_vertex_index[(idx + 1) % 4], i_coord, sq.line[i]);
              }

              //ちょっと、ひっくり返してみようか。
              for (int i = 0; i < 4; i++) {
            //直線同士の交点計算
            if (!sq.line[i].crossPos(sq.line[(i + 3) % 4], sq.sqvertex[i])) {
              throw new NyARException();//ここのエラー復帰するならダブルバッファにすればOK
            }
              }
        }
示例#9
0
        public override bool getContour(int i_l, int i_t, int i_r, int i_b, int i_entry_x, int i_entry_y, int i_th, NyARIntCoordinates o_coord)
        {
            Debug.Assert(i_t<=i_entry_x);
            int[] buf=(int[])this._ref_raster.getBuffer();
            int[] xdir = _getContour_xdir;// static int xdir[8] = { 0, 1, 1, 1, 0,-1,-1,-1};
            int[] ydir = _getContour_ydir;// static int ydir[8] = {-1,-1, 0, 1, 1, 1, 0,-1};
            int width=this._ref_raster.getWidth();
            //クリップ領域の上端に接しているポイントを得る。
            NyARIntPoint2d[] coord=o_coord.items;
            int max_coord=o_coord.items.Length;
            coord[0].x = i_entry_x;
            coord[0].y = i_entry_y;
            int coord_num = 1;
            int dir = 5;

            int c = i_entry_x;
            int r = i_entry_y;
            for (;;) {
            dir = (dir + 5) % 8;//dirの正規化
            //ここは頑張ればもっと最適化できると思うよ。
            //4隅以外の境界接地の場合に、境界チェックを省略するとかね。
            if(c>i_l && c<i_r && r>i_t && r<i_b){
                for(;;){//gotoのエミュレート用のfor文
                    //境界に接していないとき(暗点判定)
                    if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
                        break;
                    }
                    dir++;
                    if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
                        break;
                    }
                    dir++;
                    if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
                        break;
                    }
                    dir++;
                    if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
                        break;
                    }
                    dir++;
                    if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
                        break;
                    }
                    dir++;
                    if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
                        break;
                    }
                    dir++;
                    if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
                        break;
                    }
                    dir++;
                    if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
                        break;
                    }
                    //8方向全て調べたけどラベルが無いよ?
                    throw new NyARException();
                }
            }else{
                //境界に接しているとき
                int i;
                for (i = 0; i < 8; i++){
                    int x=c + xdir[dir];
                    int y=r + ydir[dir];
                    //境界チェック
                    if(x>=i_l && x<=i_r && y>=i_t && y<=i_b){
                        if (buf[(y)*width+(x)] <= i_th) {
                            break;
                        }
                    }
                    dir++;//倍長テーブルを参照するので問題なし
                }
                if (i == 8) {
                    //8方向全て調べたけどラベルが無いよ?
                    throw new NyARException();// return(-1);
                }
            }
            // xcoordとycoordをc,rにも保存
            c = c + xdir[dir];
            r = r + ydir[dir];
            coord[coord_num].x = c;
            coord[coord_num].y = r;
            //終了条件判定
            if (c == i_entry_x && r == i_entry_y){
                //開始点と同じピクセルに到達したら、終点の可能性がある。
                coord_num++;
                //末端のチェック
                if (coord_num == max_coord) {
                    //輪郭bufが末端に達した
                    return false;
                }
                //末端候補の次のピクセルを調べる
                dir = (dir + 5) % 8;//dirの正規化
                int i;
                for (i = 0; i < 8; i++){
                    int x=c + xdir[dir];
                    int y=r + ydir[dir];
                    //境界チェック
                    if(x>=i_l && x<=i_r && y>=i_t && y<=i_b){
                        if (buf[(y)*width+(x)] <= i_th) {
                            break;
                        }
                    }
                    dir++;//倍長テーブルを参照するので問題なし
                }
                if (i == 8) {
                    //8方向全て調べたけどラベルが無いよ?
                    throw new NyARException();
                }
                //得たピクセルが、[1]と同じならば、末端である。
                c = c + xdir[dir];
                r = r + ydir[dir];
                if(coord[1].x ==c && coord[1].y ==r){
                    //終点に達している。
                    o_coord.length=coord_num;
                    break;
                }else{
                    //終点ではない。
                    coord[coord_num].x = c;
                    coord[coord_num].y = r;
                }
            }
            coord_num++;
            //末端のチェック
            if (coord_num == max_coord) {
                //輪郭が末端に達した
                return false;
            }
            }
            return true;
        }
示例#10
0
 public abstract bool getContour(int i_l, int i_t, int i_r, int i_b, int i_entry_x, int i_entry_y, int i_th, NyARIntCoordinates o_coord);
示例#11
0
 /**
  * この関数は、ラスタの指定点を基点に、画像の特定の範囲内から輪郭線を抽出します。
  * 開始点は、輪郭の一部である必要があります。
  * 通常は、ラべリングの結果の上辺クリップとX軸エントリポイントを開始点として入力します。
  * @param i_raster
  * 輪郭線を抽出するラスタを指定します。
  * @param i_area
  * 輪郭線の抽出範囲を指定する矩形。i_rasterのサイズ内である必要があります。
  * @param i_th
  * 輪郭とみなす暗点の敷居値を指定します。
  * @param i_entry_x
  * 輪郭抽出の開始点です。
  * @param i_entry_y
  * 輪郭抽出の開始点です。
  * @param o_coord
  * 輪郭点を格納するオブジェクトを指定します。
  * @return
  * 輪郭線がo_coordの長さを超えた場合、falseを返します。
  * @
  */
 public bool getContour(INyARGrayscaleRaster i_raster, NyARIntRect i_area, int i_th, int i_entry_x, int i_entry_y, NyARIntCoordinates o_coord)
 {
     //ラスタドライバの切り替え
     if (i_raster != this._ref_last_input_raster)
     {
         this._imdriver = (IRasterDriver)i_raster.createInterface(typeof(IRasterDriver));
         this._ref_last_input_raster = i_raster;
     }
     return this._imdriver.getContour(i_area.x, i_area.y, i_area.x + i_area.w - 1, i_area.h + i_area.y - 1, i_entry_x, i_entry_y, i_th, o_coord);
 }
            /**
               * 矩形が見付かるたびに呼び出されます。
               * 発見した矩形のパターンを検査して、方位を考慮した頂点データを確保します。
               */
            public void detectMarkerCallback(NyARIntCoordinates i_coord, int[] i_vertex_index)
            {
                if (this._match_patt == null) { return; }

                //輪郭座標から頂点リストに変換
                NyARIntPoint2d[] vertex = this.__ref_vertex;
                vertex[0] = i_coord.items[i_vertex_index[0]];
                vertex[1] = i_coord.items[i_vertex_index[1]];
                vertex[2] = i_coord.items[i_vertex_index[2]];
                vertex[3] = i_coord.items[i_vertex_index[3]];

                //画像を取得
                if (!this._inst_patt.pickFromRaster(this._ref_raster, vertex)) { return; } //取得失敗

                //取得パターンをカラー差分データに変換して評価する。
                this._deviation_data.setRaster(this._inst_patt);

                //code_index,dir,c1にデータを得る。
                NyARMatchPattResult mr = this.__detectMarkerLite_mr;
                int lcode_index = 0;
                int dir = 0;
                double c1 = 0;
                for (int i = 0; i < this._match_patt.Length; i++) {
                  this._match_patt[i].evaluate(this._deviation_data, mr);
                  double c2 = mr.confidence;
                  if (c1 < c2) {
                lcode_index = i;
                c1 = c2;
                dir = mr.direction;
                  }
                }

                //認識処理
                if (this._target_id == -1) { // マーカ未認識
                  if (c1 < this.cf_threshold_new) { return; }  // 現在は未認識
                  if (this.confidence > c1) { return; }        // 一致度が低い。
                  //認識しているマーカIDを保存
                  this.code_index = lcode_index;
                }
                else {
                  //現在はマーカ認識中
                  // 現在のマーカを認識したか?
                  if (lcode_index != this._target_id) {
                // 認識中のマーカではないので無視
                return;
                  }
                  //認識中の閾値より大きいか?
                  if (c1 < this.cf_threshold_exist) {
                return;
                  }
                  //現在の候補よりも一致度は大きいか?
                  if (this.confidence > c1) {
                return;
                  }
                  this.code_index = this._target_id;
                }

                //新しく認識、または継続認識中に更新があったときだけ、Square情報を更新する。
                //ココから先はこの条件でしか実行されない。

                //一致率の高い矩形があれば、方位を考慮して頂点情報を作成
                this.confidence = c1;
                NyARSquare sq = this.square;
                //directionを考慮して、squareを更新する。
                for (int i = 0; i < 4; i++) {
                  int idx = (i + 4 - dir) % 4;
                  this._coordline.coord2Line(i_vertex_index[idx], i_vertex_index[(idx + 1) % 4], i_coord, sq.line[i]);
                }
                for (int i = 0; i < 4; i++) {
                  //直線同士の交点計算
                  if (!sq.line[i].crossPos(sq.line[(i + 3) % 4], sq.sqvertex[i])) {
                throw new NyARException();//ここのエラー復帰するならダブルバッファにすればOK
                  }
                }
            }
            /**
               * 矩形が見付かるたびに呼び出されます。
               * 発見した矩形のパターンを検査して、方位を考慮した頂点データを確保します。
               */
            public void detectMarkerCallback(NyARIntCoordinates i_coord, int[] i_vertex_index)
            {
                //既に発見済なら終了
                if (this.marker_data != null) { return; }

                //輪郭座標から頂点リストに変換
                NyARIntPoint2d[] vertex = this.__ref_vertex;
                vertex[0] = i_coord.items[i_vertex_index[0]];
                vertex[1] = i_coord.items[i_vertex_index[1]];
                vertex[2] = i_coord.items[i_vertex_index[2]];
                vertex[3] = i_coord.items[i_vertex_index[3]];

                NyIdMarkerParam param = this._marker_param;
                NyIdMarkerPattern patt_data = this._marker_data;

                // 評価基準になるパターンをイメージから切り出す
                if (!this._id_pickup.pickFromRaster(this._ref_raster.getGsPixelDriver(), 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情報を更新する。
                //ココから先はこの条件でしか実行されない。
                NyARSquare sq = this.square;
                //directionを考慮して、squareを更新する。
                for (int i = 0; i < 4; i++) {
                  int idx = (i + 4 - param.direction) % 4;
                  this._coordline.coord2Line(i_vertex_index[idx], i_vertex_index[(idx + 1) % 4], i_coord, sq.line[i]);
                }

                for (int i = 0; i < 4; i++) {
                  //直線同士の交点計算
                  if (!sq.line[i].crossPos(sq.line[(i + 3) % 4], sq.sqvertex[i])) {
                throw new NyARException();//ここのエラー復帰するならダブルバッファにすればOK
                  }
                }
                this.threshold = param.threshold;
                this.marker_data = this._current_data;//みつかった。
            }
示例#14
0
        public void detectMarkerCallback(NyARIntCoordinates i_coord, int[] i_vertex_index)
        {
            //とりあえずSquareスタックを予約
              SquareStack.Item sq_tmp = this._sq_stack.prePush();

              //確保できない(1つのdetectorが複数の候補を得る場合(同じARマーカが多くある場合など)に発生することがある。)
              if (sq_tmp == null) { return; }

              //観測座標点の記録
              for (int i2 = 0; i2 < 4; i2++) {
            sq_tmp.ob_vertex[i2].setValue(i_coord.items[i_vertex_index[i2]]);
              }

              //頂点分布を計算
              sq_tmp.vertex_area.setAreaRect(sq_tmp.ob_vertex, 4);

              //頂点座標の中心を計算
              sq_tmp.center2d.setCenterPos(sq_tmp.ob_vertex, 4);

              //矩形面積
              sq_tmp.rect_area = sq_tmp.vertex_area.w * sq_tmp.vertex_area.h;

              bool is_target_marker = false;
              for (;;) {
            //トラッキング対象か確認する。
            if (this._ref_tracking_list.update(sq_tmp)) {
              //トラッキング対象ならブレーク
              is_target_marker = true;
              break;
            }
            //@todo 複数マーカ時に、トラッキング済のarmarkerを探索対象外に出来ない?

            //nyIdマーカの特定(IDマーカの特定はここで完結する。)
            if (this._ref_idmk_list.Count > 0) {
              if (this._ref_idmk_list.Update(this._ref_input_gs, sq_tmp)) {
            is_target_marker = true;
            break;//idマーカを特定
              }
            }
            //PSARマーカの特定(IDマーカの特定はここで完結する。)
            if (this._ref_psmk_list.Count > 0) {
              if (this._ref_psmk_list.Update(this._ref_input_gs, sq_tmp)) {
            is_target_marker = true;
            break;//idマーカを特定
              }
            }
            //ARマーカの特定
            if (this._ref_armk_list.Count > 0) {
              //敷居値により1個のマーカに対して複数の候補が見つかることもある。
              if (this._ref_armk_list.Update(this._ref_input_rfb, sq_tmp)) {
            is_target_marker = true;
            break;
              }
            }
            break;
              }

              //この矩形が検出対象なら、矩形情報を精密に再計算
              if (is_target_marker) {
            //矩形は検出対象にマークされている。
            for (int i2 = 0; i2 < 4; i2++) {
              this._coordline.coord2Line(i_vertex_index[i2], i_vertex_index[(i2 + 1) % 4], i_coord, sq_tmp.line[i2]);
            }
            for (int i2 = 0; i2 < 4; i2++) {
              //直線同士の交点計算
              if (!sq_tmp.line[i2].crossPos(sq_tmp.line[(i2 + 3) % 4], sq_tmp.sqvertex[i2])) {
            throw new NyARException();//まずない。ありえない。
              }
            }
              }
              else {
            //この矩形は検出対象にマークされなかったので、解除
            this._sq_stack.pop();
              }
        }
示例#15
0
        public override bool getContour(int i_l, int i_t, int i_r, int i_b, int i_entry_x, int i_entry_y, int i_th, NyARIntCoordinates o_coord)
        {
            Debug.Assert(i_t <= i_entry_x);
            INyARGsPixelDriver reader = this._ref_raster.getGsPixelDriver();

            int[] xdir = _getContour_xdir; // static int xdir[8] = { 0, 1, 1, 1, 0,-1,-1,-1};
            int[] ydir = _getContour_ydir; // static int ydir[8] = {-1,-1, 0, 1, 1, 1, 0,-1};
            //クリップ領域の上端に接しているポイントを得る。
            NyARIntPoint2d[] coord = o_coord.items;
            int max_coord          = o_coord.items.Length;

            coord[0].x = i_entry_x;
            coord[0].y = i_entry_y;
            int coord_num = 1;
            int dir       = 5;

            int c = i_entry_x;
            int r = i_entry_y;

            for (; ;)
            {
                dir = (dir + 5) % 8;//dirの正規化
                //境界に接しているとき
                int i;
                for (i = 0; i < 8; i++)
                {
                    int x = c + xdir[dir];
                    int y = r + ydir[dir];
                    //境界チェック
                    if (x >= i_l && x <= i_r && y >= i_t && y <= i_b)
                    {
                        if (reader.getPixel(x, y) <= i_th)
                        {
                            break;
                        }
                    }
                    dir++;//倍長テーブルを参照するので問題なし
                }
                if (i == 8)
                {
                    //8方向全て調べたけどラベルが無いよ?
                    throw new NyARException();// return(-1);
                }
                // xcoordとycoordをc,rにも保存
                c = c + xdir[dir];
                r = r + ydir[dir];
                coord[coord_num].x = c;
                coord[coord_num].y = r;
                //終了条件判定
                if (c == i_entry_x && r == i_entry_y)
                {
                    //開始点と同じピクセルに到達したら、終点の可能性がある。
                    coord_num++;
                    //末端のチェック
                    if (coord_num == max_coord)
                    {
                        //輪郭bufが末端に達した
                        return(false);
                    }
                    //末端候補の次のピクセルを調べる
                    dir = (dir + 5) % 8;//dirの正規化
                    for (i = 0; i < 8; i++)
                    {
                        int x = c + xdir[dir];
                        int y = r + ydir[dir];
                        //境界チェック
                        if (x >= i_l && x <= i_r && y >= i_t && y <= i_b)
                        {
                            if (reader.getPixel(x, y) <= i_th)
                            {
                                break;
                            }
                        }
                        dir++;//倍長テーブルを参照するので問題なし
                    }
                    if (i == 8)
                    {
                        //8方向全て調べたけどラベルが無いよ?
                        throw new NyARException();
                    }
                    //得たピクセルが、[1]と同じならば、末端である。
                    c = c + xdir[dir];
                    r = r + ydir[dir];
                    if (coord[1].x == c && coord[1].y == r)
                    {
                        //終点に達している。
                        o_coord.length = coord_num;
                        break;
                    }
                    else
                    {
                        //終点ではない。
                        coord[coord_num].x = c;
                        coord[coord_num].y = r;
                    }
                }
                coord_num++;
                //末端のチェック
                if (coord_num == max_coord)
                {
                    //輪郭が末端に達した
                    return(false);
                }
            }
            return(true);
        }
示例#16
0
        public override bool getContour(int i_l, int i_t, int i_r, int i_b, int i_entry_x, int i_entry_y, int i_th, NyARIntCoordinates o_coord)
        {
            Debug.Assert(i_t <= i_entry_x);
            INyARGsPixelDriver reader = this._ref_raster.getGsPixelDriver();
            int[] xdir = _getContour_xdir;// static int xdir[8] = { 0, 1, 1, 1, 0,-1,-1,-1};
            int[] ydir = _getContour_ydir;// static int ydir[8] = {-1,-1, 0, 1, 1, 1, 0,-1};
            //クリップ領域の上端に接しているポイントを得る。
            NyARIntPoint2d[] coord = o_coord.items;
            int max_coord = o_coord.items.Length;
            coord[0].x = i_entry_x;
            coord[0].y = i_entry_y;
            int coord_num = 1;
            int dir = 5;

            int c = i_entry_x;
            int r = i_entry_y;
            for (; ; )
            {
                dir = (dir + 5) % 8;//dirの正規化
                //境界に接しているとき
                int i;
                for (i = 0; i < 8; i++)
                {
                    int x = c + xdir[dir];
                    int y = r + ydir[dir];
                    //境界チェック
                    if (x >= i_l && x <= i_r && y >= i_t && y <= i_b)
                    {
                        if (reader.getPixel(x, y) <= i_th)
                        {
                            break;
                        }
                    }
                    dir++;//倍長テーブルを参照するので問題なし
                }
                if (i == 8)
                {
                    //8方向全て調べたけどラベルが無いよ?
                    throw new NyARException();// return(-1);
                }
                // xcoordとycoordをc,rにも保存
                c = c + xdir[dir];
                r = r + ydir[dir];
                coord[coord_num].x = c;
                coord[coord_num].y = r;
                //終了条件判定
                if (c == i_entry_x && r == i_entry_y)
                {
                    //開始点と同じピクセルに到達したら、終点の可能性がある。
                    coord_num++;
                    //末端のチェック
                    if (coord_num == max_coord)
                    {
                        //輪郭bufが末端に達した
                        return false;
                    }
                    //末端候補の次のピクセルを調べる
                    dir = (dir + 5) % 8;//dirの正規化
                    for (i = 0; i < 8; i++)
                    {
                        int x = c + xdir[dir];
                        int y = r + ydir[dir];
                        //境界チェック
                        if (x >= i_l && x <= i_r && y >= i_t && y <= i_b)
                        {
                            if (reader.getPixel(x, y) <= i_th)
                            {
                                break;
                            }
                        }
                        dir++;//倍長テーブルを参照するので問題なし
                    }
                    if (i == 8)
                    {
                        //8方向全て調べたけどラベルが無いよ?
                        throw new NyARException();
                    }
                    //得たピクセルが、[1]と同じならば、末端である。
                    c = c + xdir[dir];
                    r = r + ydir[dir];
                    if (coord[1].x == c && coord[1].y == r)
                    {
                        //終点に達している。
                        o_coord.length = coord_num;
                        break;
                    }
                    else
                    {
                        //終点ではない。
                        coord[coord_num].x = c;
                        coord[coord_num].y = r;
                    }
                }
                coord_num++;
                //末端のチェック
                if (coord_num == max_coord)
                {
                    //輪郭が末端に達した
                    return false;
                }
            }
            return true;
        }
示例#17
0
        /**
         * この関数は、ラスタの指定点を基点に、輪郭線を抽出します。
         * 開始点は、輪郭の一部である必要があります。
         * 通常は、ラべリングの結果の上辺クリップとX軸エントリポイントを開始点として入力します。
         * @param i_raster
         * 輪郭線を抽出するラスタを指定します。
         * @param i_th
         * 輪郭とみなす暗点の敷居値を指定します。
         * @param i_entry_x
         * 輪郭抽出の開始点です。
         * @param i_entry_y
         * 輪郭抽出の開始点です。
         * @param o_coord
         * 輪郭点を格納する配列を指定します。i_array_sizeよりも大きなサイズの配列が必要です。
         * @return
         * 輪郭の抽出に成功するとtrueを返します。輪郭抽出に十分なバッファが無いと、falseになります。
         * @
         */
        public bool getContour(INyARGrayscaleRaster i_raster, int i_th, int i_entry_x, int i_entry_y, NyARIntCoordinates o_coord)
        {
            NyARIntSize s = i_raster.getSize();

            //ラスタドライバの切り替え
            if (i_raster != this._ref_last_input_raster)
            {
                this._imdriver = (IRasterDriver)i_raster.createInterface(typeof(IRasterDriver));
                this._ref_last_input_raster = i_raster;
            }
            return(this._imdriver.getContour(0, 0, s.w - 1, s.h - 1, i_entry_x, i_entry_y, i_th, o_coord));
        }
示例#18
0
 /**
  * この関数は、ラスタの指定点を基点に、輪郭線を抽出します。
  * 開始点は、輪郭の一部である必要があります。
  * 通常は、ラべリングの結果の上辺クリップとX軸エントリポイントを開始点として入力します。
  * @param i_raster
  * 輪郭線を抽出するラスタを指定します。
  * @param i_th
  * 輪郭とみなす暗点の敷居値を指定します。
  * @param i_entry_x
  * 輪郭抽出の開始点です。
  * @param i_entry_y
  * 輪郭抽出の開始点です。
  * @param o_coord
  * 輪郭点を格納する配列を指定します。i_array_sizeよりも大きなサイズの配列が必要です。
  * @return
  * 輪郭の抽出に成功するとtrueを返します。輪郭抽出に十分なバッファが無いと、falseになります。
  * @
  */
 public bool getContour(INyARGrayscaleRaster i_raster, int i_th, int i_entry_x, int i_entry_y, NyARIntCoordinates o_coord)
 {
     NyARIntSize s = i_raster.getSize();
     //ラスタドライバの切り替え
     if (i_raster != this._ref_last_input_raster)
     {
         this._imdriver = (IRasterDriver)i_raster.createInterface(typeof(IRasterDriver));
         this._ref_last_input_raster = i_raster;
     }
     return this._imdriver.getContour(0, 0, s.w - 1, s.h - 1, i_entry_x, i_entry_y, i_th, o_coord);
 }
 public void detectMarkerCallback(NyARIntCoordinates i_coord, int[] i_vertex_index)
 {
     this._parent.updateSquareInfo(i_coord, i_vertex_index);
 }
        /**
         * 輪郭線を取得します。
         * 取得アルゴリズムは、以下の通りです。
         * 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;
        }