/**
  * この関数は、オブジェクトからインスタンスに値をセットします。
  * @param i_in
  * コピー元のオブジェクト。
  */
 public void setValue(NyARDoublePoint3d i_in)
 {
     this.x = i_in.x;
     this.y = i_in.y;
     this.z = i_in.z;
     return;
 }
 /**
  * この関数は、オブジェクトからインスタンスに値をセットします。
  * @param i_in
  * コピー元のオブジェクト。
  */
 public void setValue(NyARDoublePoint3d i_in)
 {
     this.x = i_in.x;
     this.y = i_in.y;
     this.z = i_in.z;
     return;
 }
        private double optimize(NyARRotMatrix_ARToolKit io_rotmat, NyARDoublePoint3d io_transvec, INyARTransportVectorSolver i_solver, NyARDoublePoint3d[] i_offset_3d, NyARDoublePoint2d[] i_2d_vertex)
        {
            NyARDoublePoint3d[] vertex_3d = this.__transMat_vertex_3d;
            double err = -1;

            //System.out.println("START");
            // ループを抜けるタイミングをARToolKitと合わせるために変なことしてます。
            for (int i = 0; ; i++)
            {
                // <arGetTransMat3>
                err = this._mat_optimize.modifyMatrix(io_rotmat, io_transvec, i_offset_3d, i_2d_vertex);
                io_rotmat.getPoint3dBatch(i_offset_3d, vertex_3d, 4);
                i_solver.solveTransportVector(vertex_3d, io_transvec);

                err = this._mat_optimize.modifyMatrix(io_rotmat, io_transvec, i_offset_3d, i_2d_vertex);
                //System.out.println("E:"+err*4);
                // //</arGetTransMat3>
                if (err < AR_GET_TRANS_MAT_MAX_FIT_ERROR || i == AR_GET_TRANS_MAT_MAX_LOOP_COUNT - 1)
                {
                    break;
                }
                io_rotmat.getPoint3dBatch(i_offset_3d, vertex_3d, 4);
                i_solver.solveTransportVector(vertex_3d, io_transvec);
            }
            //System.out.println("END");
            return(err);
        }
Пример #4
0
        /**
         * ターゲット座標系の4頂点でかこまれる領域を射影した平面から、RGB画像をo_rasterに取得します。
         * @param i_vertex
         * ターゲットのオフセットを基準値とした、頂点座標。要素数は4であること。(mm単位)
         * @param i_matrix
         * i_vertexに適応する変換行列。
         * ターゲットの姿勢行列を指定すると、ターゲット座標系になります。不要ならばnullを設定してください。
         * @param i_resolution
         * 1ピクセルあたりのサンプリング値(n^2表現)
         * @param o_raster
         * 出力ラスタ
         * @return
         * @throws NyARException
         * <p>メモ:この関数にはnewが残ってるので注意</p>
         */
        public bool getRgbPatt3d(NyARRealitySource i_src, NyARDoublePoint3d[] i_vertex, NyARDoubleMatrix44 i_matrix, int i_resolution, INyARRgbRaster o_raster)
        {
            Debug.Assert(this._target_type == RT_KNOWN);
            NyARDoublePoint2d[] da4 = this._ref_pool._wk_da2_4;
            NyARDoublePoint3d   v3d = new NyARDoublePoint3d();

            if (i_matrix != null)
            {
                //姿勢変換してから射影変換
                for (int i = 3; i >= 0; i--)
                {
                    //姿勢を変更して射影変換
                    i_matrix.transform3d(i_vertex[i], v3d);
                    this._transform_matrix.transform3d(v3d, v3d);
                    this._ref_pool._ref_prj_mat.project(v3d, da4[i]);
                }
            }
            else
            {
                //射影変換のみ
                for (int i = 3; i >= 0; i--)
                {
                    //姿勢を変更して射影変換
                    this._transform_matrix.transform3d(i_vertex[i], v3d);
                    this._ref_pool._ref_prj_mat.project(v3d, da4[i]);
                }
            }
            //パターンの取得
            return(i_src.refPerspectiveRasterReader().copyPatt(da4, 0, 0, i_resolution, o_raster));
        }
        /**
         * double arGetTransMat( ARMarkerInfo *marker_info,double center[2], double width, double conv[3][4] )
         *
         * @param i_square
         * 計算対象のNyARSquareオブジェクト
         * @param i_width
         * @return
         * @throws NyARException
         */
        public void transMat(NyARSquare i_square, NyARRectOffset i_offset, NyARTransMatResult o_result_conv)
        {
            NyARDoublePoint3d trans = this.__transMat_trans;

            //平行移動量計算機に、2D座標系をセット
            NyARDoublePoint2d[] vertex_2d;
            if (this._ref_dist_factor != null)
            {
                //歪み復元必要
                vertex_2d = this.__transMat_vertex_2d;
                this._ref_dist_factor.ideal2ObservBatch(i_square.sqvertex, vertex_2d, 4);
            }
            else
            {
                //歪み復元は不要
                vertex_2d = i_square.sqvertex;
            }
            this._transsolver.set2dVertex(vertex_2d, 4);
            //回転行列を計算
            this._rotmatrix.initRotBySquare(i_square.line, i_square.sqvertex);

            //回転後の3D座標系から、平行移動量を計算
            NyARDoublePoint3d[] vertex_3d = this.__transMat_vertex_3d;
            this._rotmatrix.getPoint3dBatch(i_offset.vertex, vertex_3d, 4);
            this._transsolver.solveTransportVector(vertex_3d, trans);

            //計算結果の最適化(平行移動量と回転行列の最適化)
            double err = this.optimize(this._rotmatrix, trans, this._transsolver, i_offset.vertex, vertex_2d);

            // マトリクスの保存
            o_result_conv.setValue(this._rotmatrix, trans, err);
            return;
        }
 /**
  * この関数は、インスタンスの座標と、指定点との距離の2乗値を返します。
  * @param i_p1
  * 点の座標
  * @return
  * i_p1との距離の二乗値
  */
 public double sqDist(NyARDoublePoint3d i_p1)
 {
     double x, y, z;
     x = this.x - i_p1.x;
     y = this.y - i_p1.y;
     z = this.z - i_p1.z;
     return x * x + y * y + z * z;
 }
Пример #7
0
        public NyARDoublePoint2d getScreenPos(int i_id, double i_x, double i_y, double i_z, NyARDoublePoint2d i_out)
        {
            NyARDoublePoint3d _wk_3dpos = this._wk_3dpos;

            this.getTransformMatrix(i_id).transform3d(i_x, i_y, i_z, _wk_3dpos);
            this._view.getFrustum().project(_wk_3dpos, i_out);
            return(i_out);
        }
        public void getMarkerPlanePos(int id, int i_x, int i_y, ref Vector3 i_out)
        {
            NyARDoublePoint3d p = new NyARDoublePoint3d();

            this.getMarkerPlanePos(id, i_x, i_y, p);
            i_out.x = -(float)p.x;
            i_out.y = (float)p.y;
            i_out.z = (float)p.z;
        }
 /**
  * この関数は、オブジェクトの一次配列を作ります。
  * @param i_number
  * 作成する配列の長さ
  * @return
  * 新しい配列。
  */
 public static NyARDoublePoint3d[] createArray(int i_number)
 {
     NyARDoublePoint3d[] ret = new NyARDoublePoint3d[i_number];
     for (int i = 0; i < i_number; i++)
     {
         ret[i] = new NyARDoublePoint3d();
     }
     return ret;
 }
        /**
         * この関数は、インスタンスの座標と、指定点との距離の2乗値を返します。
         * @param i_p1
         * 点の座標
         * @return
         * i_p1との距離の二乗値
         */
        public double sqDist(NyARDoublePoint3d i_p1)
        {
            double x, y, z;

            x = this.x - i_p1.x;
            y = this.y - i_p1.y;
            z = this.z - i_p1.z;
            return(x * x + y * y + z * z);
        }
 /**
  * この関数は、オブジェクトの一次配列を作ります。
  * @param i_number
  * 作成する配列の長さ
  * @return
  * 新しい配列。
  */
 public static NyARDoublePoint3d[] createArray(int i_number)
 {
     NyARDoublePoint3d[] ret = new NyARDoublePoint3d[i_number];
     for (int i = 0; i < i_number; i++)
     {
         ret[i] = new NyARDoublePoint3d();
     }
     return(ret);
 }
Пример #12
0
        public void getMarkerPlanePos(int i_id, int i_x, int i_y, ref Vector3 i_buf)
        {
            NyARDoublePoint3d p = this.__wk_3dpos;

            base.getMarkerPlanePos(i_id, i_x, i_y, p);
            i_buf.X = (float)p.x;
            i_buf.Y = (float)p.y;
            i_buf.Z = (float)p.z;
            return;
        }
Пример #13
0
        public void getScreenPos(int i_id, double i_x, double i_y, double i_z, ref Vector2 i_out)
        {
            NyARDoublePoint2d wk_2dpos = this.__wk_2dpos;
            NyARDoublePoint3d wk_3dpos = this.__wk_3dpos;

            this.getMarkerMatrix(i_id).transform3d(i_x, i_y, i_z, wk_3dpos);
            this._frustum.project(wk_3dpos, wk_2dpos);
            i_out.X = (float)wk_2dpos.x;
            i_out.Y = (float)wk_2dpos.y;
            return;
        }
Пример #14
0
        public static void restoreOutputOffset(NyARDoubleMatrix44 conv, NyARDoublePoint3d i_offset)
        {
            double dx = i_offset.x;
            double dy = i_offset.y;
            double dz = i_offset.z;

            conv.m03 = (conv.m03 - conv.m00 * dx - conv.m01 * dy - conv.m02 * dz);
            conv.m13 = (conv.m13 - conv.m10 * dx - conv.m11 * dy - conv.m12 * dz);
            conv.m23 = (conv.m23 - conv.m20 * dx - conv.m21 * dy - conv.m22 * dz);
            return;
        }
Пример #15
0
        /**
         * 画面座標群と3次元座標群から、平行移動量を計算します。
         * 2d座標系は、直前に実行した{@link #set2dVertex}のものを使用します。
         */
        public void solveTransportVector(NyARDoublePoint3d[] i_vertex3d, NyARDoublePoint3d o_transfer)
        {
            int    number_of_vertex = this._nmber_of_vertex;
            double p00 = this._projection_mat.m00;
            double p01 = this._projection_mat.m01;
            double p02 = this._projection_mat.m02;
            double p11 = this._projection_mat.m11;
            double p12 = this._projection_mat.m12;

            //行列[A]の3列目のキャッシュ
            double[] cx = this._cx;
            double[] cy = this._cy;

            //回転行列を元座標の頂点群に適応
            //[A]T*[b]を計算
            double b1 = 0, b2 = 0, b3 = 0;

            for (int i = 0; i < number_of_vertex; i++)
            {
                double w1 = i_vertex3d[i].z * cx[i] - p00 * i_vertex3d[i].x - p01 * i_vertex3d[i].y - p02 * i_vertex3d[i].z;
                double w2 = i_vertex3d[i].z * cy[i] - p11 * i_vertex3d[i].y - p12 * i_vertex3d[i].z;
                b1 += w1;
                b2 += w2;
                b3 += cx[i] * w1 + cy[i] * w2;
            }
            //[A]T*[b]を計算
            b3 = p02 * b1 + p12 * b2 - b3;//順番変えたらダメよ
            b2 = p01 * b1 + p11 * b2;
            b1 = p00 * b1;
            //([A]T*[A])*[T]=[A]T*[b]を方程式で解く。
            //a01とa10を0と仮定しても良いんじゃないかな?
            double a00 = this._a00;
            double a01 = this._a01_10;
            double a02 = this._a02_20;
            double a11 = this._a11;
            double a12 = this._a12_21;
            double a22 = this._a22;

            double t1  = a22 * b2 - a12 * b3;
            double t2  = a12 * b2 - a11 * b3;
            double t3  = a01 * b3 - a02 * b2;
            double t4  = a12 * a12 - a11 * a22;
            double t5  = a02 * a12 - a01 * a22;
            double t6  = a02 * a11 - a01 * a12;
            double det = a00 * t4 - a01 * t5 + a02 * t6;

            o_transfer.x = (a01 * t1 - a02 * t2 + b1 * t4) / det;
            o_transfer.y = -(a00 * t1 + a02 * t3 + b1 * t5) / det;
            o_transfer.z = (a00 * t2 + a01 * t3 + b1 * t6) / det;


            return;
        }
        /*
         * (non-Javadoc)
         * @see jp.nyatla.nyartoolkit.core.transmat.INyARTransMat#transMatContinue(jp.nyatla.nyartoolkit.core.NyARSquare, int, double, jp.nyatla.nyartoolkit.core.transmat.NyARTransMatResult)
         */
        public void transMatContinue(NyARSquare i_square, NyARRectOffset i_offset, NyARTransMatResult o_result_conv)
        {
            NyARDoublePoint3d trans = this.__transMat_trans;

            // io_result_convが初期値なら、transMatで計算する。
            if (!o_result_conv.has_value)
            {
                this.transMat(i_square, i_offset, o_result_conv);
                return;
            }

            //平行移動量計算機に、2D座標系をセット
            NyARDoublePoint2d[] vertex_2d = this.__transMat_vertex_2d;
            NyARDoublePoint3d[] vertex_3d = this.__transMat_vertex_3d;
            this._ref_dist_factor.ideal2ObservBatch(i_square.sqvertex, vertex_2d, 4);
            this._transsolver.set2dVertex(vertex_2d, 4);

            //回転行列を計算
            this._rotmatrix.initRotByPrevResult(o_result_conv);

            //回転後の3D座標系から、平行移動量を計算
            this._rotmatrix.getPoint3dBatch(i_offset.vertex, vertex_3d, 4);
            this._transsolver.solveTransportVector(vertex_3d, trans);

            //計算結果の最適化(平行移動量と回転行列の最適化)
            double err = this.optimize(this._rotmatrix, trans, this._transsolver, i_offset.vertex, vertex_2d);

            // マトリクスの保存
            this.updateMatrixValue(this._rotmatrix, trans, o_result_conv);

            // エラー値が許容範囲でなければTransMatをやり直し
            if (err > AR_GET_TRANS_CONT_MAT_MAX_FIT_ERROR)
            {
                // rotationを矩形情報で初期化
                this._rotmatrix.initRotBySquare(i_square.line, i_square.sqvertex);
                //回転行列の平行移動量の計算
                this._rotmatrix.getPoint3dBatch(i_offset.vertex, vertex_3d, 4);
                this._transsolver.solveTransportVector(vertex_3d, trans);
                //計算結果の最適化(this._rotmatrix,trans)
                double err2 = this.optimize(this._rotmatrix, trans, this._transsolver, i_offset.vertex, vertex_2d);
                //エラー値が低かったら値を差換え
                if (err2 < err)
                {
                    // 良い値が取れたら、差換え
                    this.updateMatrixValue(this._rotmatrix, trans, o_result_conv);
                }
                err = err2;
            }
            //エラー値保存
            o_result_conv.error = err;
            return;
        }
Пример #17
0
        /**
         * この関数は、理想座標系の四角系を元に、位置姿勢変換行列を求めます。
         * 計算に過去の履歴を使う点が、{@link #transMat}と異なります。
         * @see INyARTransMat#transMatContinue
         */
        public bool transMatContinue(NyARSquare i_square, NyARRectOffset i_offset, NyARDoubleMatrix44 i_prev_result, double i_prev_err, NyARDoubleMatrix44 o_result, NyARTransMatResultParam o_param)
        {
            NyARDoublePoint3d trans = this.__transMat_trans;

            //平行移動量計算機に、2D座標系をセット
            NyARDoublePoint2d[] vertex_2d;
            if (this._ref_dist_factor != null)
            {
                //歪み復元必要
                vertex_2d = this.__transMat_vertex_2d;
                this._ref_dist_factor.ideal2ObservBatch(i_square.sqvertex, vertex_2d, 4);
            }
            else
            {
                //歪み復元は不要
                vertex_2d = i_square.sqvertex;
            }
            this._transsolver.set2dVertex(vertex_2d, 4);

            NyARDoublePoint3d[] vertex_3d = this.__transMat_vertex_3d;
            //回転行列を計算
            this._rotmatrix.initRotByPrevResult(i_prev_result);

            //回転後の3D座標系から、平行移動量を計算
            this._rotmatrix.getPoint3dBatch(i_offset.vertex, vertex_3d, 4);
            this._transsolver.solveTransportVector(vertex_3d, trans);

            //計算結果の最適化(平行移動量と回転行列の最適化)
            double err = this.optimize(this._rotmatrix, trans, this._transsolver, i_offset.vertex, vertex_2d);

            // マトリクスの保存
            o_result.setValue(this._rotmatrix, trans);

            // エラー値が許容範囲でなければTransMatをやり直し
            if (err > AR_GET_TRANS_CONT_MAT_MAX_FIT_ERROR)
            {
                return(false);
            }
            // マトリクスの保存
            o_result.setValue(this._rotmatrix, trans);
            //エラー値保存
            if (o_param != null)
            {
                o_param.last_error = err;
            }
            return(true);
        }
        /**
         * パラメータで変換行列を更新します。
         *
         * @param i_rot
         * @param i_off
         * @param i_trans
         */
        public void updateMatrixValue(NyARRotMatrix i_rot, NyARDoublePoint3d i_trans, NyARTransMatResult o_result)
        {
            o_result.m00 = i_rot.m00;
            o_result.m01 = i_rot.m01;
            o_result.m02 = i_rot.m02;
            o_result.m03 = i_trans.x;

            o_result.m10 = i_rot.m10;
            o_result.m11 = i_rot.m11;
            o_result.m12 = i_rot.m12;
            o_result.m13 = i_trans.y;

            o_result.m20 = i_rot.m20;
            o_result.m21 = i_rot.m21;
            o_result.m22 = i_rot.m22;
            o_result.m23 = i_trans.z;

            o_result.has_value = true;
            return;
        }
Пример #19
0
        /**
         * この関数は、理想座標系の四角系を元に、位置姿勢変換行列を求めます。
         * ARToolKitのarGetTransMatに該当します。
         * @see INyARTransMat#transMatContinue
         */
        public bool transMat(NyARSquare i_square, NyARRectOffset i_offset, NyARDoubleMatrix44 o_result, NyARTransMatResultParam o_param)
        {
            NyARDoublePoint3d trans = this.__transMat_trans;

            //平行移動量計算機に、2D座標系をセット
            NyARDoublePoint2d[] vertex_2d;
            if (this._ref_dist_factor != null)
            {
                //歪み復元必要
                vertex_2d = this.__transMat_vertex_2d;
                this._ref_dist_factor.ideal2ObservBatch(i_square.sqvertex, vertex_2d, 4);
            }
            else
            {
                //歪み復元は不要
                vertex_2d = i_square.sqvertex;
            }
            this._transsolver.set2dVertex(vertex_2d, 4);
            //回転行列を計算
            if (!this._rotmatrix.initRotBySquare(i_square.line, i_square.sqvertex))
            {
                return(false);
            }

            //回転後の3D座標系から、平行移動量を計算
            NyARDoublePoint3d[] vertex_3d = this.__transMat_vertex_3d;
            this._rotmatrix.getPoint3dBatch(i_offset.vertex, vertex_3d, 4);
            this._transsolver.solveTransportVector(vertex_3d, trans);

            //計算結果の最適化(平行移動量と回転行列の最適化)
            double err = this.optimize(this._rotmatrix, trans, this._transsolver, i_offset.vertex, vertex_2d);

            // マトリクスの保存
            o_result.setValue(this._rotmatrix, trans);
            if (o_param != null)
            {
                o_param.last_error = err;
            }
            return(true);
        }
        /**
         * この関数は、平行移動量と回転行列をセットして、インスタンスのパラメータを更新します。
         * 通常、ユーザが使うことはありません。
         * {@link INyARTransMat#transMatContinue}関数が使います。
         * @param i_rot
         * 設定する回転行列
         * @param i_trans
         * 設定する平行移動量
         */
        public void setValue(NyARDoubleMatrix33 i_rot, NyARDoublePoint3d i_trans, double i_error)
        {
            this.m00 = i_rot.m00;
            this.m01 = i_rot.m01;
            this.m02 = i_rot.m02;
            this.m03 = i_trans.x;

            this.m10 = i_rot.m10;
            this.m11 = i_rot.m11;
            this.m12 = i_rot.m12;
            this.m13 = i_trans.y;

            this.m20 = i_rot.m20;
            this.m21 = i_rot.m21;
            this.m22 = i_rot.m22;
            this.m23 = i_trans.z;

            this.m30 = this.m31 = this.m32 = 0;
            this.m33 = 1.0;
            this.has_value = true;
            this.last_error = i_error;
            return;
        }
Пример #21
0
        /**
         * この関数は、平行移動量と回転行列をセットして、インスタンスのパラメータを更新します。
         * 通常、ユーザが使うことはありません。
         * {@link INyARTransMat#transMatContinue}関数が使います。
         * @param i_rot
         * 設定する回転行列
         * @param i_trans
         * 設定する平行移動量
         */
        public void setValue(NyARDoubleMatrix33 i_rot, NyARDoublePoint3d i_trans, double i_error)
        {
            this.m00 = i_rot.m00;
            this.m01 = i_rot.m01;
            this.m02 = i_rot.m02;
            this.m03 = i_trans.x;

            this.m10 = i_rot.m10;
            this.m11 = i_rot.m11;
            this.m12 = i_rot.m12;
            this.m13 = i_trans.y;

            this.m20 = i_rot.m20;
            this.m21 = i_rot.m21;
            this.m22 = i_rot.m22;
            this.m23 = i_trans.z;

            this.m30        = this.m31 = this.m32 = 0;
            this.m33        = 1.0;
            this.has_value  = true;
            this.last_error = i_error;
            return;
        }
Пример #22
0
 /**
  * カメラ座標系の4頂点でかこまれる領域から、RGB画像をo_rasterに取得します。
  * @param i_vertex
  * @param i_matrix
  * i_vertexに適応する変換行列。
  * ターゲットの姿勢行列を指定すると、ターゲット座標系になります。不要ならばnullを設定してください。
  * @param i_resolution
  * @param o_raster
  * @return
  * @throws NyARException
  */
 public bool GetRgbPatt3d(NyARRealitySource i_src, NyARDoublePoint3d[] i_vertex, NyARDoubleMatrix44 i_matrix, int i_resolution, INyARRgbRaster o_raster)
 {
     NyARDoublePoint2d[] vx = NyARDoublePoint2d.createArray(4);
     if (i_matrix != null)
     {
         //姿勢変換してから射影変換
         NyARDoublePoint3d v3d = new NyARDoublePoint3d();
         for (int i = 3; i >= 0; i--)
         {
             i_matrix.transform3d(i_vertex[i], v3d);
             this._ref_prjmat.project(v3d, vx[i]);
         }
     }
     else
     {
         //射影変換のみ
         for (int i = 3; i >= 0; i--)
         {
             this._ref_prjmat.project(i_vertex[i], vx[i]);
         }
     }
     //パターンの取得
     return(i_src.refPerspectiveRasterReader().copyPatt(vx, 0, 0, i_resolution, o_raster));
 }
Пример #23
0
 public NyARDoublePoint3d getPlanePos(int i_id, int i_x, int i_y, NyARDoublePoint3d i_out)
 {
     this._view.getFrustum().unProjectOnMatrix(i_x, i_y, this.getTransformMatrix(i_id), i_out);
     return(i_out);
 }
Пример #24
0
        static void Main(string[] args)
        {
            NyARDoubleMatrix44 DEST_MAT = new NyARDoubleMatrix44(
                new double[] {
                0.9832165682361184, 0.004789697223621061, -0.18237945710280384, -190.59060790299358,
                0.012860184615056927, -0.9989882709616935, 0.04309419210331572, 64.04490277502563,
                -0.18198852802987958, -0.044716355753573425, -0.9822833548209547, 616.6427596804766,
                0, 0, 0, 1
            });
            NyARDoubleMatrix44 SRC_MAT = new NyARDoubleMatrix44(new double[] {
                0.984363556, 0.00667689135, -0.176022261, -191.179672,
                0.0115975942, -0.999569774, 0.0269410834, 63.0028076,
                -0.175766647, -0.0285612550, -0.984017432, 611.758728,
                0, 0, 0, 1
            });

            String img_file = "../../../../../data/testcase/test.raw";
            String cparam   = "../../../../../data/testcase/camera_para5.dat";
            String fsetfile = "../../../../../data/testcase/pinball.fset";
            String isetfile = "../../../../../data/testcase/pinball.iset5";
            //カメラパラメータ
            NyARParam param = NyARParam.loadFromARParamFile(File.OpenRead(cparam), 640, 480, NyARParam.DISTFACTOR_LT_ARTK5);


            INyARGrayscaleRaster gs = NyARGrayscaleRaster.createInstance(640, 480);
            //試験画像の準備
            {
                INyARRgbRaster rgb = NyARRgbRaster.createInstance(640, 480, NyARBufferType.BYTE1D_B8G8R8X8_32);
                Stream         fs  = File.OpenRead(img_file);
                byte[]         b   = (byte[])rgb.getBuffer();
                fs.Read(b, 0, b.Length);
                INyARRgb2GsFilterRgbAve filter = (INyARRgb2GsFilterRgbAve)rgb.createInterface(typeof(INyARRgb2GsFilterRgbAve));
                filter.convert(gs);
            }

            NyARNftFsetFile    fset = NyARNftFsetFile.loadFromFsetFile(File.OpenRead(fsetfile));
            NyARNftIsetFile    iset = NyARNftIsetFile.loadFromIsetFile(File.OpenRead(isetfile));
            NyARSurfaceTracker st   = new NyARSurfaceTracker(param, 16, 0.5);
            NyARSurfaceDataSet sd   = new NyARSurfaceDataSet(iset, fset);
            NyARDoubleMatrix44 sret = new NyARDoubleMatrix44();

            NyARDoublePoint2d[] o_pos2d           = NyARDoublePoint2d.createArray(16);
            NyARDoublePoint3d[] o_pos3d           = NyARDoublePoint3d.createArray(16);
            NyARSurfaceTrackingTransmatUtils tmat = new NyARSurfaceTrackingTransmatUtils(param, 5.0);
            NyARDoubleMatrix44 tret = new NyARDoubleMatrix44();

            for (int j = 0; j < 10; j++)
            {
                Stopwatch s = new Stopwatch();
                s.Reset();
                s.Start();
                for (int i = 0; i < 3000; i++)
                {
                    sret.setValue(SRC_MAT);
                    int nop = st.tracking(gs, sd, sret, o_pos2d, o_pos3d, 16);
                    //Transmatの試験
                    NyARDoublePoint3d off = NyARSurfaceTrackingTransmatUtils.centerOffset(o_pos3d, nop, new NyARDoublePoint3d());
                    NyARSurfaceTrackingTransmatUtils.modifyInputOffset(sret, o_pos3d, nop, off);
                    tmat.surfaceTrackingTransmat(sret, o_pos2d, o_pos3d, nop, tret, new NyARTransMatResultParam());
                    NyARSurfaceTrackingTransmatUtils.restoreOutputOffset(tret, off);
                    System.Console.WriteLine(tret.Equals(DEST_MAT));
                }
                s.Stop();
                System.Console.WriteLine(s.ElapsedMilliseconds);
            }
            return;
        }
        private double optimize(NyARRotMatrix_ARToolKit io_rotmat, NyARDoublePoint3d io_transvec, INyARTransportVectorSolver i_solver, NyARDoublePoint3d[] i_offset_3d, NyARDoublePoint2d[] i_2d_vertex)
        {
            NyARDoublePoint3d[] vertex_3d = this.__transMat_vertex_3d;
            double err = -1;
            //System.out.println("START");
            // ループを抜けるタイミングをARToolKitと合わせるために変なことしてます。 
            for (int i = 0; ; i++)
            {
                // <arGetTransMat3>
                err = this._mat_optimize.modifyMatrix(io_rotmat, io_transvec, i_offset_3d, i_2d_vertex);
                io_rotmat.getPoint3dBatch(i_offset_3d, vertex_3d, 4);
                i_solver.solveTransportVector(vertex_3d, io_transvec);

                err = this._mat_optimize.modifyMatrix(io_rotmat, io_transvec, i_offset_3d, i_2d_vertex);
                //System.out.println("E:"+err*4);
                // //</arGetTransMat3>
                if (err < AR_GET_TRANS_MAT_MAX_FIT_ERROR || i == AR_GET_TRANS_MAT_MAX_LOOP_COUNT - 1)
                {
                    break;
                }
                io_rotmat.getPoint3dBatch(i_offset_3d, vertex_3d, 4);
                i_solver.solveTransportVector(vertex_3d, io_transvec);
            }
            //System.out.println("END");
            return err;
        }
        /**
         * この関数は、入力した画像でインスタンスの状態を更新します。
         * 関数は、入力画像を処理して検出、一致判定、トラッキング処理を実行します。
         * @param i_sensor
         * 画像を含むセンサオブジェクト
         */
        public void update(NyARSensor i_sensor)
        {
            long time_stamp = i_sensor.getTimeStamp();

            //センサのタイムスタンプが変化していなければ何もしない。
            if (this._last_time_stamp == time_stamp)
            {
                return;
            }
            //タイムスタンプの更新
            this._last_time_stamp = time_stamp;

            //ステータス遷移


            NyARDoublePoint2d[]  pos2d = this._pos2d;
            NyARDoublePoint3d[]  pos3d = this._pos3d;
            INyARGrayscaleRaster gs    = i_sensor.getGsImage();

            //KPMスレッドによる更新()
            this._kpm_worker.updateInputImage(gs);

            //SurfaceTrackingによるfrontデータの更新

            foreach (NftTarget target in this._nftdatalist)
            {
                if (target.stage < NftTarget.ST_KPM_FOUND)
                {
                    //System.out.println("NOTHING");
                    //KPM検出前なら何もしない。
                    continue;
                }
                switch (target.stage)
                {
                case NftTarget.ST_AR2_TRACKING:
                    //NftTarget.ST_AR2_TRACKING以降
                    //front_transmatに作る。
                    NyARSurfaceTracker st = this._surface_tracker;
                    int nop = st.tracking(gs, target.dataset.surface_dataset, target.front_transmat, this._pos2d, pos3d, 16);
                    if (nop == 0)
                    {
                        //失敗
                        target.stage = NftTarget.ST_KPM_SEARCH;
                        //System.out.println("ST_KPM_SEARCH");
                        continue;
                    }
                    //Transmatの試験
                    NyARDoublePoint3d off = NyARSurfaceTrackingTransmatUtils.centerOffset(pos3d, nop, new NyARDoublePoint3d());
                    NyARSurfaceTrackingTransmatUtils.modifyInputOffset(target.front_transmat, pos3d, nop, off);    //ARTK5の補正
                    if (!this._sftrackingutils.surfaceTrackingTransmat(target.front_transmat, pos2d, pos3d, nop, target.front_transmat, this.result_param))
                    {
                        //失敗
                        target.stage = NftTarget.ST_KPM_SEARCH;
                        //System.out.println("ST_KPM_SEARCH");
                        continue;
                    }
                    NyARSurfaceTrackingTransmatUtils.restoreOutputOffset(target.front_transmat, off);    //ARTK5の補正
                    break;

                case NftTarget.ST_KPM_FOUND:
                    target.stage = NftTarget.ST_AR2_TRACKING;
                    //System.out.println("ST_AR2_TRACKING");
                    break;
                }
            }
        }
Пример #27
0
        public override bool icpPoint(NyARDoublePoint2d[] screenCoord,
            NyARDoublePoint3d[] worldCoord, int num,
            NyARDoubleMatrix44 initMatXw2Xc, NyARDoubleMatrix44 o_matxw2xc, NyARTransMatResultParam o_result_param)
        {
            double err0 = 0, err1;
            System.Diagnostics.Debug.Assert(num >= 4);

            NyARIcpUtils.DeltaS dS = this.__dS;
            NyARIcpUtils.U u = this.__u;

            //ワークオブジェクトのリセット
            if (this.__jus.getArraySize() < num)
            {
                this.__jus = new NyARIcpUtils.JusStack(num);
                this.__du = NyARDoublePoint2d.createArray(num);
            }
            NyARIcpUtils.JusStack jus = this.__jus;
            NyARDoublePoint2d[] du = this.__du;

            o_matxw2xc.setValue(initMatXw2Xc);

            double breakLoopErrorThresh = this.getBreakLoopErrorThresh();
            double breakLoopErrorThresh2 = this.getBreakLoopErrorThresh2();
            double breakLoopErrorRatioThresh = this.getBreakLoopErrorRatioThresh();
            double maxLoop = this.getMaxLoop();

            NyARDoubleMatrix44 matXw2U = this.__matXw2U;
            for (int i = 0; ; i++)
            {
                matXw2U.mul(this._ref_matXc2U, o_matxw2xc);
                err1 = 0.0;
                for (int j = 0; j < num; j++)
                {
                    if (!u.setXbyMatX2U(matXw2U, worldCoord[j]))
                    {
                        return false;
                    }
                    double dx = screenCoord[j].x - u.x;
                    double dy = screenCoord[j].y - u.y;
                    err1 += dx * dx + dy * dy;
                    du[j].x = dx;
                    du[j].y = dy;
                }
                err1 /= num;
                if (err1 < breakLoopErrorThresh)
                {
                    break;
                }
                if ((i > 0) && (err1 < breakLoopErrorThresh2) && (err1 / err0 > breakLoopErrorRatioThresh))
                {
                    break;
                }
                if (i == maxLoop)
                {
                    break;
                }
                err0 = err1;
                jus.clear();
                for (int j = 0; j < num; j++)
                {
                    if(!jus.push(this._ref_matXc2U,o_matxw2xc, worldCoord[j],du[j],1.0))
                    {
                        return false;
                    }
                }
                if (!dS.setJusArray(jus))
                {
                    return false;
                }
                dS.makeMat(o_matxw2xc);
                }
            if (o_result_param != null)
            {
                o_result_param.last_error = err1;
            }
            // *err = err1;
            return true;
        }
Пример #28
0
 public NyARDoublePoint3d getMarkerPlanePos(int i_id, int i_x, int i_y, NyARDoublePoint3d i_out)
 {
     return(this.getPlanePos(i_id, i_x, i_y, i_out));
 }
        /**
         * 画面座標群と3次元座標群から、平行移動量を計算します。
         * 2d座標系は、直前に実行した{@link #set2dVertex}のものを使用します。
         */
        public void solveTransportVector(NyARDoublePoint3d[] i_vertex3d, NyARDoublePoint3d o_transfer)
        {
            int number_of_vertex = this._nmber_of_vertex;
            double p00 = this._projection_mat.m00;
            double p01 = this._projection_mat.m01;
            double p02 = this._projection_mat.m02;
            double p11 = this._projection_mat.m11;
            double p12 = this._projection_mat.m12;
            //行列[A]の3列目のキャッシュ
            double[] cx = this._cx;
            double[] cy = this._cy;

            //回転行列を元座標の頂点群に適応
            //[A]T*[b]を計算
            double b1 = 0, b2 = 0, b3 = 0;
            for (int i = 0; i < number_of_vertex; i++)
            {
                double w1 = i_vertex3d[i].z * cx[i] - p00 * i_vertex3d[i].x - p01 * i_vertex3d[i].y - p02 * i_vertex3d[i].z;
                double w2 = i_vertex3d[i].z * cy[i] - p11 * i_vertex3d[i].y - p12 * i_vertex3d[i].z;
                b1 += w1;
                b2 += w2;
                b3 += cx[i] * w1 + cy[i] * w2;
            }
            //[A]T*[b]を計算
            b3 = p02 * b1 + p12 * b2 - b3;//順番変えたらダメよ
            b2 = p01 * b1 + p11 * b2;
            b1 = p00 * b1;
            //([A]T*[A])*[T]=[A]T*[b]を方程式で解く。
            //a01とa10を0と仮定しても良いんじゃないかな?
            double a00 = this._a00;
            double a01 = this._a01_10;
            double a02 = this._a02_20;
            double a11 = this._a11;
            double a12 = this._a12_21;
            double a22 = this._a22;

            double t1 = a22 * b2 - a12 * b3;
            double t2 = a12 * b2 - a11 * b3;
            double t3 = a01 * b3 - a02 * b2;
            double t4 = a12 * a12 - a11 * a22;
            double t5 = a02 * a12 - a01 * a22;
            double t6 = a02 * a11 - a01 * a12;
            double det = a00 * t4 - a01 * t5 + a02 * t6;
            o_transfer.x = (a01 * t1 - a02 * t2 + b1 * t4) / det;
            o_transfer.y = -(a00 * t1 + a02 * t3 + b1 * t5) / det;
            o_transfer.z = (a00 * t2 + a01 * t3 + b1 * t6) / det;


            return;
        }
Пример #30
0
	    /**
	     * ICPアルゴリズムによる姿勢推定を行います。
	     * 
	     * @param screenCoord
	     * @param worldCoord
	     * @param num
	     * @param initMatXw2Xc
	     * @param o_matxw2xc
	     * @param o_result_param
	     * 結果パラメータを受け取るオブジェクト。不要な場合はnullを指定可能。
	     * @return
	     * @throws NyARException
	     */
	    public abstract bool icpPoint(NyARDoublePoint2d[] screenCoord,
			    NyARDoublePoint3d[] worldCoord, int num,
			    NyARDoubleMatrix44 initMatXw2Xc, NyARDoubleMatrix44 o_matxw2xc,NyARTransMatResultParam o_result_param);
 /**
  * この関数は、スクリーン座標点をマーカ平面の点に変換します。
  * {@link #isExistMarker(int)}がtrueの時にだけ使用できます。
  * @param i_id
  * マーカID(ハンドル)値。
  * @param i_x
  * 変換元のスクリーン座標
  * @param i_y
  * 変換元のスクリーン座標
  * @param i_out
  * 結果を格納するオブジェクト
  * @return
  * 結果を格納したi_outに設定したオブジェクト
  */
 public NyARDoublePoint3d getMarkerPlanePos(int i_id, int i_x, int i_y, NyARDoublePoint3d i_out)
 {
     this._frustum.unProjectOnMatrix(i_x, i_y, this.getMarkerMatrix(i_id), i_out);
     return(i_out);
 }
Пример #32
0
        //Método executado a cada frame de vídeo
        public void OnBuffer(CaptureDevice i_sender, double i_sample_time, IntPtr i_buffer, int i_buffer_len)
        {
            try
            {
                i++;
                int                w             = i_sender.video_width;
                int                h             = i_sender.video_height;
                int                s             = w * (i_sender.video_bit_count / 8);
                Matrix             trans_matrix  = new Matrix();
                NyARTransMatResult nyar_transmat = this.__OnBuffer_nyar_transmat;

                Bitmap b = new Bitmap(w, h, s, PixelFormat.Format32bppRgb, i_buffer);

                // If the image is upsidedown
                b.RotateFlip(RotateFlipType.RotateNoneFlipY);
                this.pbxNyAR.Image = b;

                //Calculation of the AR - Seta o frame do vídeo no objeto Raster
                Core.raster.setBuffer(i_buffer, i_sender.video_vertical_flip);

                //Instância dos objetos de detecção
                detectedMarkersList = new ArrayList();
                NyARTransMatResult transMatrix;
                NyARDoublePoint3d  point3D;


                if (this.blnKanji == false)   //Controle Kanji. FALSE: Palavra não formada // TRUE: Palavra formada, pronto para plotar
                {
                    //Detecção
                    int    totalMarkers   = this.markerDetector.detectMarkerLite(Core.raster, 100);
                    int    markerId       = 0;
                    string palavraFormada = null;

                    NyARTransMatResult transMatKanji = new NyARTransMatResult();

                    //Caso encontrar marcadores
                    if (totalMarkers > 0)
                    {
                        for (int counter = 0; counter < totalMarkers; counter++)
                        {
                            markerId = this.markerDetector.getARCodeIndex(counter);

                            if (this.markerDetector.getConfidence(counter) > 0.60)
                            {
                                if (markerId == 0)
                                {
                                    this.markerDetector.getTransmationMatrix(markerId, transMatKanji);
                                }
                                else
                                {
                                    //Recupera o ângulo XYZ do marcador e salva na lista.
                                    transMatrix = new NyARTransMatResult();
                                    point3D     = new NyARDoublePoint3d();
                                    this.markerDetector.getTransmationMatrix(counter, transMatrix);
                                    transMatrix.getZXYAngle(point3D);


                                    detectedMarker          = new DetectedMarker();
                                    detectedMarker.markerID = markerId;
                                    detectedMarker.point3D  = point3D;
                                    detectedMarkersList.Add(detectedMarker);
                                }
                            }
                        }
                    }


                    //Realiza os cálculos da RA caso encontrar algum marcador válido
                    if (detectedMarkersList.Count > 0)
                    {
                        //Ordena a lista de acordo com a posição
                        detectedMarkersList.Sort(new OrdenacaoPorX());

                        //Monta a palavra de acordo com os marcadores detectados
                        foreach (DetectedMarker item in detectedMarkersList)
                        {
                            palavraFormada += this.arrayLetters[item.markerID - 1];
                        }

                        if (detectedMarkersList.Count == 3)
                        {
                            totalMarkers = totalMarkers + 0;
                        }



                        //Teste - Verifica o número de letras correspondentes
                        string originalWord = gmNyAR.SelectedObject;
                        int    total        = verificaTotalPalavraFormada(detectedMarkersList, originalWord);
                        if (total == originalWord.Length)
                        {
                            this.blnKanji     = true;
                            this.kanjiCounter = 0; //Refresh do contador
                            lbNyAR.Text       = "Palavra correta!";
                        }
                        else
                        {
                            if (intRefresh == 0)
                            {
                                if (total == 1)
                                {
                                    lbNyAR.Text = "Você acertou " + total + " letra! ";
                                }
                                else
                                {
                                    lbNyAR.Text = "Você acertou " + total + " letras! ";
                                }
                            }
                        }

                        // Realiza a gravação da pontuação
                        int points = (total / originalWord.Length) * 100;

                        if (points > int.Parse(gmNyAR.Points))
                        {
                            gmNyAR.Points = points.ToString();
                        }

                        //Refresh da label que indica a quantidade de letras corretas.
                        intRefresh++;
                        if (intRefresh > 20)
                        {
                            intRefresh = 0;
                        }
                    }
                }
                else
                {
                    //Desenho do objeto 3D no marcador Kanji.
                    bool kanji = this.kanjiDetector.detectMarkerLite(Core.raster);
                    if (kanji)
                    {
                        NyARTransMatResult result = new NyARTransMatResult();
                        if (this.kanjiDetector.getConfidence() > 0.50)
                        {
                            this.kanjiDetector.getTransmationMatrix(result);
                            DrawWord(gmNyAR.SelectedObject, result);
                        }
                    }
                    this.kanjiCounter++;
                    if (this.kanjiCounter > 50)
                    {
                        this.blnKanji = false;
                    }
                }
            }
            catch (Exception e)
            {
                MessageBox.Show("Ocorreu um erro na verficação dos marcadores. Favor, reinicie a aplicação. Se o erro persistir, contate os desenvolvedores.", "Erro!");
                Environment.Exit(0);
            }
        }
Пример #33
0
        public bool icpStereoPoint(NyARDoublePoint2d[] screenCoord_l,
                NyARDoublePoint3d[] worldCoord_l, int num_l,
                NyARDoublePoint2d[] screenCoord_r,
                NyARDoublePoint3d[] worldCoord_r, int num_r,
                NyARDoubleMatrix44 initMatXw2Xc, NyARDoubleMatrix44 matXw2Xc)
        {
            System.Diagnostics.Debug.Assert(num_l + num_r >= 3);
            double err0 = 0, err1;
            // 6*2*num?
            NyARIcpUtils.DeltaS dS = this.__dS;
            //ワークオブジェクトのリセット		
            if (this.__jus.getArraySize() < num_l + num_r)
            {
                this.__jus = new NyARIcpUtils.JusStack(num_l + num_r);
                this.__du = NyARDoublePoint2d.createArray(num_l + num_r);
            }
            NyARIcpUtils.JusStack jus = this.__jus;
            NyARDoublePoint2d[] du = this.__du;
            NyARIcpUtils.U u = this.__u;
            NyARDoubleMatrix44 matXc2Ul = new NyARDoubleMatrix44();
            NyARDoubleMatrix44 matXc2Ur = new NyARDoubleMatrix44();
            NyARDoubleMatrix44 matXw2Ul = new NyARDoubleMatrix44();
            NyARDoubleMatrix44 matXw2Ur = new NyARDoubleMatrix44();



            matXw2Xc.setValue(initMatXw2Xc);

            matXc2Ul.mul(this._ref_matXcl2Ul, this._matC2L);
            matXc2Ur.mul(this._ref_matXcr2Ur, this._matC2R);

            for (int i = 0; ; i++)
            {
                matXw2Ul.mul(matXc2Ul, matXw2Xc);
                matXw2Ur.mul(matXc2Ur, matXw2Xc);

                err1 = 0.0;
                for (int j = 0; j < num_l; j++)
                {
                    if (!u.setXbyMatX2U(matXw2Ul, worldCoord_l[j]))
                    {
                        return false;
                    }
                    double dx = screenCoord_l[j].x - u.x;
                    double dy = screenCoord_l[j].y - u.y;
                    err1 += dx * dx + dy * dy;
                    du[j].x = dx;
                    du[j].y = dy;
                }
                for (int j = 0; j < num_r; j++)
                {
                    if (!u.setXbyMatX2U(matXw2Ur, worldCoord_r[j]))
                    {
                        return false;
                    }
                    double dx = screenCoord_r[j].x - u.x;
                    double dy = screenCoord_r[j].y - u.y;
                    err1 += dx * dx + dy * dy;
                    du[j + num_l].x = dx;
                    du[j + num_l].y = dy;
                }
                err1 /= (num_l + num_r);

                if (err1 < this.breakLoopErrorThresh)
                {
                    break;
                }
                if (i > 0 && err1 < ICP_BREAK_LOOP_ERROR_THRESH2
                        && err1 / err0 > this.breakLoopErrorRatioThresh)
                {
                    break;
                }
                if (i == this.maxLoop)
                {
                    break;
                }
                err0 = err1;

                for (int j = 0; j < num_l; j++)
                {
                    if (!jus.push(this._ref_matXc2U, matXw2Xc, worldCoord_l[j], du[j], 1.0))
                    {
                        return false;
                    }
                }
                for (int j = 0; j < num_r; j++)
                {
                    if (!jus.push(this._ref_matXc2U, matXw2Xc, worldCoord_r[j], du[j], 1.0))
                    {
                        return false;
                    }
                }
                if (!dS.setJusArray(jus))
                {
                    return false;
                }
                dS.makeMat(matXw2Xc);
            }

            return false;
        }
Пример #34
0
        public static NyARDoublePoint3d centerOffset(NyARDoublePoint3d[] i_pos3d, int i_num, NyARDoublePoint3d i_result)
        {
            double dx, dy, dz;

            dx = dy = dz = 0.0f;
            for (int i = 0; i < i_num; i++)
            {
                dx += i_pos3d[i].x;
                dy += i_pos3d[i].y;
                dz += i_pos3d[i].z;
            }
            i_result.x = dx / i_num;
            i_result.y = dy / i_num;
            i_result.z = dz / i_num;
            return(i_result);
        }
Пример #35
0
        /**
         * ARToolKitV5で追加されていた補正
         * @param initConv
         * @param i_pos3d
         * @param i_offset
         * @param i_num
         */
        public static void modifyInputOffset(NyARDoubleMatrix44 initConv, NyARDoublePoint3d[] i_pos3d, int i_num, NyARDoublePoint3d i_offset)
        {
            double dx = i_offset.x;
            double dy = i_offset.y;
            double dz = i_offset.z;

            for (int i = 0; i < i_num; i++)
            {
                i_pos3d[i].x = i_pos3d[i].x - dx;
                i_pos3d[i].y = i_pos3d[i].y - dy;
                i_pos3d[i].z = i_pos3d[i].z - dz;
            }
            initConv.m03 = (initConv.m00 * dx + initConv.m01 * dy + initConv.m02 * dz + initConv.m03);
            initConv.m13 = (initConv.m10 * dx + initConv.m11 * dy + initConv.m12 * dz + initConv.m13);
            initConv.m23 = (initConv.m20 * dx + initConv.m21 * dy + initConv.m22 * dz + initConv.m23);
            return;
        }
Пример #36
0
        //Método executado a cada frame de vídeo
        public void OnBuffer(CaptureDevice i_sender, double i_sample_time, IntPtr i_buffer, int i_buffer_len)
        {
            try
            {
                i++;
                int                w             = i_sender.video_width;
                int                h             = i_sender.video_height;
                int                s             = w * (i_sender.video_bit_count / 8);
                Matrix             trans_matrix  = new Matrix();
                NyARTransMatResult nyar_transmat = this.__OnBuffer_nyar_transmat;

                Bitmap b = new Bitmap(w, h, s, PixelFormat.Format32bppRgb, i_buffer);

                // If the image is upsidedown
                b.RotateFlip(RotateFlipType.RotateNoneFlipY);
                this.pbxNyAR.Image = b;

                //Calculation of the AR - Seta o frame do vídeo no objeto Raster
                Core.raster.setBuffer(i_buffer, i_sender.video_vertical_flip);

                //Instância dos objetos de detecção
                detectedMarkersListLetters = new ArrayList();
                detectedMarkersListImages  = new ArrayList();
                NyARTransMatResult transMatrix;
                NyARDoublePoint3d  point3D;



                //Aqui vem a lógica do Bingo
                //1 - Detectar o marcador da cartela
                //2 - Verificar a relação de letras sorteadas e a palavra da cartela
                //3 - Se a palavra tiver todas as letras sorteadas, plotar o desenho específico
                //  - Senão, informa de algum jeito o total das letras, e qual falta, sei lá.

                //Verficar a palavra relacionada à cartela
                string originalWord = string.Empty;

                //Adiciona as letras sorteadas no ArrayList para comparação
                raffledLetters = new ArrayList();
                foreach (char item in gmNyAR.RaffleLetters)
                {
                    raffledLetters.Add(item);
                }



                if (intRefresh == 0)
                {
                    //Detecção das LETRAS
                    int totalMarkersLetter           = this.markerDetectorLetters.detectMarkerLite(Core.raster, 100);
                    int markerLetterId               = 0;
                    NyARTransMatResult transMatKanji = new NyARTransMatResult();

                    //Caso encontrar marcadores
                    if (totalMarkersLetter > 0)
                    {
                        for (int counter = 0; counter < totalMarkersLetter; counter++)
                        {
                            markerLetterId = this.markerDetectorLetters.getARCodeIndex(counter);

                            if (this.markerDetectorLetters.getConfidence(counter) > 0.60)
                            {
                                if (markerLetterId == 0)
                                {
                                    this.markerDetectorLetters.getTransmationMatrix(markerLetterId, transMatKanji);
                                }
                                else
                                {
                                    //Recupera o ângulo XYZ do marcador e salva na lista.
                                    transMatrix = new NyARTransMatResult();
                                    point3D     = new NyARDoublePoint3d();
                                    this.markerDetectorLetters.getTransmationMatrix(counter, transMatrix);
                                    transMatrix.getZXYAngle(point3D);

                                    detectedMarker          = new DetectedMarker();
                                    detectedMarker.markerID = markerLetterId;
                                    detectedMarker.point3D  = point3D;
                                    detectedMarkersListLetters.Add(detectedMarker);
                                }
                            }
                        }
                    }

                    //Detecção dos marcadores específicos
                    int totalMarkerImages = this.markerDetectorImages.detectMarkerLite(Core.raster, 100);
                    int markerImageId     = 0;

                    if (totalMarkerImages > 0)
                    {
                        for (int counter = 0; counter < totalMarkerImages; counter++)
                        {
                            markerImageId = this.markerDetectorImages.getARCodeIndex(counter);

                            if (this.markerDetectorImages.getConfidence(counter) > 0.50)
                            {
                                //Recupera o ângulo XYZ do marcador e salva na lista.
                                transMatrix = new NyARTransMatResult();
                                point3D     = new NyARDoublePoint3d();
                                this.markerDetectorImages.getTransmationMatrix(counter, transMatrix);
                                transMatrix.getZXYAngle(point3D);

                                detectedMarker          = new DetectedMarker();
                                detectedMarker.markerID = markerImageId;
                                detectedMarker.point3D  = point3D;
                                detectedMarkersListImages.Add(detectedMarker);
                            }
                        }
                    }



                    if ((detectedMarkersListLetters.Count + detectedMarkersListImages.Count) > 0)
                    {
                        if ((detectedMarkersListLetters.Count + detectedMarkersListImages.Count) > 1)
                        {
                            lbNyAR.Text = "Há letras que não foram preenchidas na cartela";
                            //Fazer algo para avisar que nem todas as letras foram preenchidas.
                        }
                        else
                        {
                            if (detectedMarkersListImages.Count > 0)
                            {
                                //switch das palavras correspondentes ao marcador encontrado.
                                switch (markerImageId)
                                {
                                case 0: originalWord = "BOLA";
                                    break;

                                case 1: originalWord = "ESPADA";
                                    break;

                                case 2: originalWord = "CARRO";
                                    break;

                                case 3: originalWord = "BRIGADEIRO";
                                    break;

                                case 4: originalWord = "GARFO";
                                    break;

                                case 5: originalWord = "CANETA";
                                    break;

                                case 6: originalWord = "PEIXE";
                                    break;
                                }

                                int total = checkTotalLetters(raffledLetters, originalWord);

                                //Se todas as letras da palavra tiverem sido sorteadas, plota a imagem
                                if (total == originalWord.Length)
                                {
                                    lbNyAR.Text = "BINGO! Palavra: " + originalWord;
                                    intRefresh++;
                                    intDetected = markerImageId;
                                }
                                else
                                {
                                    lbNyAR.Text = "Algumas letras ainda não foram sorteadas";
                                    //Verificar o que vai fazer... pode ser uma mensagem na tela.
                                }
                            }
                        }
                    }
                }
                else
                {
                    bool detected;
                    switch (intDetected)
                    {
                    case 0: detected = this.ballMarkerDetector.detectMarkerLite(Core.raster);
                        if (detected)
                        {
                            NyARTransMatResult result = new NyARTransMatResult();
                            if (this.ballMarkerDetector.getConfidence() > 0.50)
                            {
                                this.ballMarkerDetector.getTransmationMatrix(result);
                                //DrawWord("bola", result);
                            }
                        }
                        break;

                    case 1: detected = this.swordMarkerDetector.detectMarkerLite(Core.raster);
                        if (detected)
                        {
                            NyARTransMatResult result = new NyARTransMatResult();
                            if (this.swordMarkerDetector.getConfidence() > 0.50)
                            {
                                this.swordMarkerDetector.getTransmationMatrix(result);
                                //DrawWord("espada", result);
                            }
                        }
                        break;

                    case 3: detected = this.carMarkerDetector.detectMarkerLite(Core.raster);
                        if (detected)
                        {
                            NyARTransMatResult result = new NyARTransMatResult();
                            if (this.carMarkerDetector.getConfidence() > 0.50)
                            {
                                this.carMarkerDetector.getTransmationMatrix(result);
                                //DrawWord("carro", result);
                            }
                        }
                        break;

                    case 4: detected = this.forkMarkerDetector.detectMarkerLite(Core.raster);
                        if (detected)
                        {
                            NyARTransMatResult result = new NyARTransMatResult();
                            if (this.forkMarkerDetector.getConfidence() > 0.50)
                            {
                                this.forkMarkerDetector.getTransmationMatrix(result);
                                DrawWord("garfo", result);
                            }
                        }
                        break;

                    case 5: detected = this.penMarkerDetector.detectMarkerLite(Core.raster);
                        if (detected)
                        {
                            NyARTransMatResult result = new NyARTransMatResult();
                            if (this.penMarkerDetector.getConfidence() > 0.50)
                            {
                                this.penMarkerDetector.getTransmationMatrix(result);
                                //DrawWord("caneta", result);
                            }
                        }
                        break;

                    case 6: detected = this.fishMarkerDetector.detectMarkerLite(Core.raster);
                        if (detected)
                        {
                            NyARTransMatResult result = new NyARTransMatResult();
                            if (this.fishMarkerDetector.getConfidence() > 0.50)
                            {
                                this.fishMarkerDetector.getTransmationMatrix(result);
                                DrawWord("peixe", result);
                            }
                        }
                        break;
                    }


                    //Refresh do detector
                    intRefresh++;
                    if (intRefresh > 20)
                    {
                        intRefresh  = 0;
                        intDetected = -1;
                    }
                }
            }
            catch (Exception e)
            {
                MessageBox.Show("Ocorreu um erro na verficação dos marcadores. Favor, reinicie a aplicação. Se o erro persistir, contate os desenvolvedores.", "Erro!");
                Environment.Exit(0);
            }
        }
        /**
         * パラメータで変換行列を更新します。
         * 
         * @param i_rot
         * @param i_off
         * @param i_trans
         */
        public void updateMatrixValue(NyARRotMatrix i_rot, NyARDoublePoint3d i_trans, NyARTransMatResult o_result)
        {
            o_result.m00 = i_rot.m00;
            o_result.m01 = i_rot.m01;
            o_result.m02 = i_rot.m02;
            o_result.m03 = i_trans.x;

            o_result.m10 = i_rot.m10;
            o_result.m11 = i_rot.m11;
            o_result.m12 = i_rot.m12;
            o_result.m13 = i_trans.y;

            o_result.m20 = i_rot.m20;
            o_result.m21 = i_rot.m21;
            o_result.m22 = i_rot.m22;
            o_result.m23 = i_trans.z;

            o_result.has_value = true;
            return;
        }