예제 #1
0
        private static int selectHistory(NyARSurfaceFeatures candidate, NyARFeatureCoordPtrList i_prev_log)
        {
            int j;

            for (int i = 0; i < i_prev_log.getLength(); i++)
            {
                NyARNftFsetFile.NyAR2FeatureCoord prev_item = i_prev_log.getItem(i);
                for (j = 0; j < candidate.getLength(); j++)
                {
                    NyARSurfaceFeatureItem item = candidate.getItem(j);
                    // 過去ログでも検出した形跡があったものを選択する。
                    if (prev_item == item.ref_feature)
                    {
                        return(j);
                    }
                }
            }
            //残ってない
            if (candidate.getLength() == 0)
            {
                return(-1);
            }
            //適当に返す
            int k = (int)((double)candidate.getLength() * _rand.rand() / (RepeatedRandomizer.RAND_MAX + 1.0f));

            for (int i = j = 0; i < candidate.getLength(); i++)
            {
                if (j == k)
                {
                    return(i);
                }
                j++;
            }
            return(-1);
        }
예제 #2
0
            /**
             * 射影変換行列ログから、候補点を計算して、メンバ変数posへ格納する。
             * @param i_log
             * @return
             * 候補点の数
             */
            public int makeCandidatePos(NyARSurfaceFeatureItem i_cai, NyARSurfaceTransMatrixSetFifo i_log)
            {
                NyARDoublePoint2d tmp = this._tmp;

                NyARIntPoint2d[] p = this.pos;
                double           x = i_cai.x;
                double           y = i_cai.y;

                p[0].x = (int)x;
                p[0].y = (int)y;
                int num_of_log = i_log.num_of_item;

                if (num_of_log >= 3)
                {
                    //過去の理想点を観察点に戻す
                    i_log.items[1].calculate2dPos(i_cai.ref_feature.mx, i_cai.ref_feature.my, tmp);
                    this._ref_df.ideal2Observ(tmp, tmp);
                    p[1].x = (int)(2 * x - tmp.x);
                    p[1].y = (int)(2 * y - tmp.y);
                    double x1 = tmp.x;
                    double y1 = tmp.y;
                    i_log.items[2].calculate2dPos(i_cai.ref_feature.mx, i_cai.ref_feature.my, tmp);
                    this._ref_df.ideal2Observ(tmp, tmp);
                    p[2].x = (int)(3 * x - 3 * x1 + tmp.x);
                    p[2].y = (int)(3 * y - 3 * y1 + tmp.y);

                    return(3);
                }
                else if (num_of_log >= 2)
                {
                    i_log.items[1].calculate2dPos(i_cai.ref_feature.mx, i_cai.ref_feature.my, tmp);
                    this._ref_df.ideal2Observ(tmp, tmp);
                    p[1].x = (int)(2 * x - tmp.x);
                    p[1].y = (int)(2 * y - tmp.y);
                    return(2);
                }
                return(1);
            }
예제 #3
0
        private static int select2(NyARSurfaceFeatures candidate, int xsize, int ysize, NyARSurfaceFeatureItem i_pos0, NyARSurfaceFeatureItem i_pos1)
        {
            double dmax = 0.0f;
            int    j    = -1;

            for (int i = candidate.getLength() - 1; i >= 0; i--)
            {
                NyARSurfaceFeatureItem item = candidate.getItem(i);
                if (item.x < xsize / 8 || item.x > xsize * 7 / 8 || item.y < ysize / 8 || item.y > ysize * 7 / 8)
                {
                    continue;
                }
                // なんだこれ。距離は間違いないが・・・。pos[0]とpos[1]の両方から一番離れた奴?
                double d = ((item.x - i_pos0.x) * (i_pos1.y - i_pos0.y) - (item.y - i_pos0.y) * (i_pos1.x - i_pos0.x));
                d = d * d;
                if (d > dmax)
                {
                    dmax = d;
                    j    = i;
                }
            }
            return(j);
        }
예제 #4
0
        private static int select1(NyARSurfaceFeatures candidate, int xsize, int ysize, NyARSurfaceFeatureItem i_pos0)
        {
            double dmax = 0;
            int    j    = -1;

            for (int i = candidate.getLength() - 1; i >= 0; i--)
            {
                NyARSurfaceFeatureItem item = candidate.getItem(i);
                // スクリーンの場所でフィルタ
                if (item.x < xsize / 8 || item.x > xsize * 7 / 8 || item.y < ysize / 8 || item.y > ysize * 7 / 8)
                {
                    continue;
                }
                // pos[0]との距離が市場の遠いのを選択
                double d = (item.x - i_pos0.x) * (item.x - i_pos0.x) + (item.y - i_pos0.y) * (item.y - i_pos0.y);
                if (d > dmax)
                {
                    dmax = d;
                    j    = i;
                }
            }
            return(j);
        }
예제 #5
0
        private static int select0(NyARSurfaceFeatures candidate, int xsize, int ysize)
        {
            int    j    = -1;
            double dmax = 0.0f;

            for (int i = candidate.getLength() - 1; i >= 0; i--)
            {
                NyARSurfaceFeatureItem item = candidate.getItem(i);
                // スクリーンの場所でフィルター
                if (item.x < xsize / 8 || item.x > xsize * 7 / 8 || item.y < ysize / 8 || item.y > ysize * 7 / 8)
                {
                    continue;
                }
                // 中心から一番距離のありそうなのを選択
                double d = (item.x - xsize / 2) * (item.x - xsize / 2) + (item.y - ysize / 2) * (item.y - ysize / 2);
                if (d > dmax)
                {
                    dmax = d;
                    j    = i;
                }
            }
            return(j);
        }
예제 #6
0
        private static int select3(NyARSurfaceFeatures candidate, int xsize, int ysize, NyARSurfaceFeatureItem i_pos0, NyARSurfaceFeatureItem i_pos1, NyARSurfaceFeatureItem i_pos2)
        {
            double smax, s;
            SinCos p2sincos = new SinCos();
            SinCos p3sincos = new SinCos();
            SinCos p4sincos = new SinCos();

            p2sincos.ar2GetVectorAngle(i_pos0, i_pos1);
            p3sincos.ar2GetVectorAngle(i_pos0, i_pos2);

            int j = -1;

            smax = 0.0f;
            for (int i = candidate.getLength() - 1; i >= 0; i--)
            {
                NyARSurfaceFeatureItem item = candidate.getItem(i);
                // スクリーンのry
                if (item.x < xsize / 8 || item.x > xsize * 7 / 8 || item.y < ysize / 8 || item.y > ysize * 7 / 8)
                {
                    continue;
                }
                // 謎の選択ルール・・・。
                //			pos[3].x = item.x;
                //			pos[3].y = item.y;
                p4sincos.ar2GetVectorAngle(i_pos0, item);
                if (((p3sincos.sin * p2sincos.cos - p3sincos.cos * p2sincos.sin) >= 0.0f) && ((p4sincos.sin * p2sincos.cos - p4sincos.cos * p2sincos.sin) >= 0.0f))
                {
                    if (p4sincos.sin * p3sincos.cos - p4sincos.cos * p3sincos.sin >= 0.0f)
                    {
                        s = ar2GetRegionArea(i_pos0, i_pos1, i_pos2, item);
                    }
                    else
                    {
                        s = ar2GetRegionArea(i_pos0, i_pos1, item, i_pos2);
                    }
                }
                else if (((p4sincos.sin * p3sincos.cos - p4sincos.cos * p3sincos.sin) >= 0.0f) &&
                         ((p2sincos.sin * p3sincos.cos - p2sincos.cos * p3sincos.sin) >= 0.0f))
                {
                    if (p4sincos.sin * p2sincos.cos - p4sincos.cos * p2sincos.sin >= 0.0f)
                    {
                        s = ar2GetRegionArea(i_pos0, i_pos2, i_pos1, item);
                    }
                    else
                    {
                        s = ar2GetRegionArea(i_pos0, i_pos2, item, i_pos1);
                    }
                }
                else if (((p2sincos.sin * p4sincos.cos - p2sincos.cos * p4sincos.sin) >= 0.0f) &&
                         ((p3sincos.sin * p4sincos.cos - p3sincos.cos * p4sincos.sin) >= 0.0f))
                {
                    if (p3sincos.sin * p2sincos.cos - p3sincos.cos * p2sincos.sin >= 0.0f)
                    {
                        s = ar2GetRegionArea(i_pos0, item, i_pos1, i_pos2);
                    }
                    else
                    {
                        s = ar2GetRegionArea(i_pos0, item, i_pos2, i_pos1);
                    }
                }
                else
                {
                    continue;
                }
                if (s > smax)
                {
                    smax = s;
                    j    = i;
                }
            }
            return(j);
        }
예제 #7
0
        /**
         * i_rasiterの画像から、i_surfaceにマッチするパターンを検出して、その理想座標と3次元座標セットを返す。
         * 検出した頂点セットは、o_pos2dとo_pos3dへ最大i_num個出力する。
         * @param i_raster
         * 現在の画像
         * @param i_surface
         * 検出すべきサーフェイスセット
         * @param i_trans
         * 現在の姿勢変換行列
         * @param o_pos2d
         * 出力パラメータ。画面上の理想点。
         * オブジェクトの配列を指定すること。
         * @param o_pos3d
         * 出力パラメータ。三次元サーフェイス座標。
         * オブジェクトの配列を指定すること。
         * @param i_num
         * 返却数。この数値は、コンストラクタに与えた最大数以下である必要がある。o_pos2dとo_pos3dは、この数値より大きい配列でなければならない。
         * @return
         * 検出した頂点セットの数。
         * @throws NyARException
         */
        public int tracking(INyARGrayscaleRaster i_raster, NyARSurfaceDataSet i_surface, NyARDoubleMatrix44 i_trans, NyARDoublePoint2d[] o_pos2d, NyARDoublePoint3d[] o_pos3d, int i_num)
        {
            //テンプレートドライバの更新
            INyARTemplateMatchingDriver tmd;

            if (this._last_raster != i_raster)
            {
                tmd = this._last_driver = new NyARTemplateMatchingDriver_INT1D(i_raster, 12, 12);
                this._last_raster = i_raster;
            }
            else
            {
                tmd = this._last_driver;
            }
            //射影変換行列の計算とログへの追加
            NyARSurfaceTransMatrixSet tlog = this._ctrans_log.preAdd();

            tlog.setValue(this._ref_cparam.getPerspectiveProjectionMatrix(), i_trans);


            //可視な候補を選択する。(一時リスト)
            this._feature_selector.extractVisibleFeatures(i_surface.fset, tlog, this._candidate, this._candidate2);
            PatchImagePositions pcpoints = this.__pcpoints;

            //load screen size.
            NyARIntSize s = this._ref_cparam.getScreenSize();

            //頂点選択クラス類の初期化
            NyARSurfaceFeatureIndexSelector index_selecter    = this.__index_selecter;
            NyARSurfaceFeaturesPtr          selected_features = this.__selected_features;

            selected_features.clear();
            //最大返却数の決定
            int max_feature = i_num > this.__selected_features.getArraySize() ? this.__selected_features.getArraySize() : i_num;

            int num = 0;
            NyARSurfaceFeatures current_candidate = this._candidate;

            for (int i = max_feature - 1; i >= 0; i--)
            {
                //高精度を優先して探索。なければ低精度に切り替える。切替は1度だけ。出力は座標集合。
                int k = index_selecter.ar2SelectTemplate(current_candidate, this._prev_selected_features, selected_features, s);
                if (k < 0)
                {
                    if (current_candidate == this._candidate2)
                    {
                        break;
                    }
                    current_candidate = this._candidate2;
                    //未選択なら終了
                    k = index_selecter.ar2SelectTemplate(current_candidate, this._prev_selected_features, selected_features, s);
                    if (k < 0)
                    {
                        break;
                    }
                }
                //候補kを確保
                NyARSurfaceFeatureItem cai = current_candidate.getItem(k);


                //可視な点について、トラッキングするためのパッチ画像を生成
                NyARTemplatePatchImage template_ = this.__template_patch;
                template_.makeFromReferenceImage((int)(cai.x + 0.5), (int)(cai.y + 0.5), tlog.ctrans, this._ref_cparam.getDistortionFactor(), i_surface.iset.items[cai.scale]);

                //パッチ画像の内容をチェック?
                if (template_.vlen * template_.vlen >= (template_.xsize) * (template_.ysize) * AR2_DEFALUT_TRACKING_SD_THRESH * AR2_DEFALUT_TRACKING_SD_THRESH)
                {
                    //射影変換行列ログから候補点を作る。
                    int number_of_point = pcpoints.makeCandidatePos(cai, this._ctrans_log);

                    //画像からテンプレートを検索
                    double sim = tmd.ar2GetBestMatching(template_, pcpoints.pos, number_of_point, o_pos2d[num]);
                    //類似値が一定以上なら、保存
                    if (sim > this.simThresh)
                    {
                        if (selected_features.push(cai) == null)
                        {
                            break;//最大値に達したら終わり
                        }
                        this._ref_cparam.getDistortionFactor().observ2Ideal(o_pos2d[num], o_pos2d[num]);
                        o_pos3d[num].x = cai.ref_feature.mx;
                        o_pos3d[num].y = cai.ref_feature.my;
                        o_pos3d[num].z = 0;
                        //選択した得量を記録
                        num++;
                    }
                }
                //選択された候補を取り外す。
                current_candidate.remove(k);
            }
            // 過去ログへ記録
            this._prev_selected_features.clear();
            for (int i = 0; i < selected_features.getLength(); i++)
            {
                this._prev_selected_features.push(selected_features.getItem(i).ref_feature);
            }
            return(num);
        }
예제 #8
0
        public void extractVisibleFeatures(
            NyARNftFsetFile i_fset, NyARSurfaceTransMatrixSet i_ctrans,
            NyARSurfaceFeatures candidate, NyARSurfaceFeatures candidate2)
        {
            //get work objects
            NyARDoublePoint2d ide2d    = this.__ide2d;
            NyARDoublePoint2d obs2d    = this.__obs2d;
            NyARDoublePoint2d rideal2d = this.__rideal2d;

            //		trans1.setCoefficient(i_cparam.getPerspectiveProjectionMatrix(), trans1);
            candidate.clear();
            candidate2.clear();

            int xsize = this._ref_size.w;
            int ysize = this._ref_size.h;
            INyARCameraDistortionFactor df = this._ref_dist_factor;


            for (int j = 0; j < i_fset.list.Length; j++)
            {
                NyARNftFsetFile.NyAR2FeaturePoints fpoint_ptr = i_fset.list[j];
                for (int k = 0; k < fpoint_ptr.coord.Length; k++)
                {
                    NyARNftFsetFile.NyAR2FeatureCoord coord_ptr = fpoint_ptr.coord[k];

                    //理想画面点を計算
                    i_ctrans.calculate2dPos(coord_ptr.mx, coord_ptr.my, ide2d);
                    df.ideal2Observ(ide2d.x, ide2d.y, obs2d);

                    //観察座標に変換後、画面内にあるか確認
                    if (obs2d.x < 0 || obs2d.x >= xsize)
                    {
                        continue;
                    }
                    if (obs2d.y < 0 || obs2d.y >= ysize)
                    {
                        continue;
                    }
                    //逆変換可能か確認
                    df.observ2Ideal(obs2d, rideal2d);
                    if (ide2d.sqDist(rideal2d) > 1.0)
                    {
                        continue;
                    }


                    //原点からのベクトルを計算
                    //Z軸が+だとつかえないので判定?
                    if (i_ctrans.calculateVd(coord_ptr.mx, coord_ptr.my) > -0.1)
                    {
                        continue;
                    }
                    //				double vd0 = trans1.m00 * coord_ptr.mx+ trans1.m01 * coord_ptr.my+ trans1.m03;
                    //				double vd1 = trans1.m10 * coord_ptr.mx+ trans1.m11 * coord_ptr.my+ trans1.m13;
                    //				double vd2 = trans1.m20 * coord_ptr.mx+ trans1.m21 * coord_ptr.my+ trans1.m23;
                    //				if( (vd0*trans1.m02 + vd1*trans1.m12 + vd2*trans1.m22)/Math.sqrt( vd0*vd0 + vd1*vd1 + vd2*vd2 ) > -0.1 ){
                    //					continue;
                    //				}


                    //撮影箇所のdpiを計算(x,y方向で計算して、大・小の順番で格納?)
                    double dpi = i_ctrans.ar2GetMinResolution(coord_ptr);

                    //dpiによってコレクトする候補を分離
                    if (dpi <= fpoint_ptr.maxdpi && dpi >= fpoint_ptr.mindpi)
                    {
                        NyARSurfaceFeatureItem item = candidate.prePush();
                        if (item == null)
                        {
                            return;
                        }
                        item.ref_feature = coord_ptr;
                        item.scale       = fpoint_ptr.scale;
                        item.x           = obs2d.x;
                        item.y           = obs2d.y;
                    }
                    else if (dpi <= fpoint_ptr.maxdpi * 2 && dpi >= fpoint_ptr.mindpi / 2)
                    {
                        NyARSurfaceFeatureItem item = candidate2.prePush();
                        if (item == null)
                        {
                            return;
                        }
                        item.ref_feature = coord_ptr;
                        item.scale       = fpoint_ptr.scale;
                        item.x           = obs2d.x;
                        item.y           = obs2d.y;
                    }
                }
            }
            return;
        }