Exemple #1
0
        protected void initInstance(
            NyARParam i_ref_param,
            NyARCode[] i_ref_code,
            double[] i_marker_width,
            int i_number_of_code,
            int i_input_raster_type)
        {
            NyARIntSize scr_size = i_ref_param.getScreenSize();
            // 解析オブジェクトを作る
            int cw = i_ref_code[0].getWidth();
            int ch = i_ref_code[0].getHeight();

            //detectMarkerのコールバック関数
            this._detect_cb = new DetectSquareCB(
                new NyARColorPatt_Perspective_O2(cw, ch, 4, 25),
                i_ref_code, i_number_of_code, i_ref_param);
            this._transmat = new NyARTransMat(i_ref_param);
            //NyARToolkitプロファイル
            this._square_detect = new NyARSquareContourDetector_Rle(i_ref_param.getScreenSize());
            this._tobin_filter  = new NyARRasterFilter_ARToolkitThreshold(100, i_input_raster_type);

            //実サイズ保存
            this._offset = NyARRectOffset.createArray(i_number_of_code);
            for (int i = 0; i < i_number_of_code; i++)
            {
                this._offset[i].setSquare(i_marker_width[i]);
            }
            //2値画像バッファを作る
            this._bin_raster = new NyARBinRaster(scr_size.w, scr_size.h);
            return;
        }
Exemple #2
0
        /// <summary>
        /// Initializes the detector for single marker detection.
        /// </summary>
        /// <param name="width">The width of the buffer that will be used for detection.</param>
        /// <param name="height">The height of the buffer that will be used for detection.</param>
        /// <param name="nearPlane">The near view plane of the frustum.</param>
        /// <param name="farPlane">The far view plane of the frustum.</param>
        /// <param name="markers">A list of markers that should be detected.</param>
        /// <param name="bufferType">The type of the buffer.</param>
        /// <param name="adaptive">Performs an adaptive bitmap thresholding if set to true. Default = false.</param>
        protected void Initialize(int width, int height, double nearPlane, double farPlane, IList <Marker> markers, int bufferType, bool adaptive = false)
        {
            // Check arguments
            if (markers == null || !markers.Any())
            {
                throw new ArgumentNullException("markers");
            }

            // Member init
            this.bufferWidth  = width;
            this.bufferHeight = height;
            this.isAdaptive   = adaptive;

            // Init pattern matchers with markers and check segment size, whcih has to be equal for all markers
            int segmentX        = markers[0].SegmentsX;
            int segmentY        = markers[0].SegmentsY;
            var patternMatchers = new List <PatternMatcher>(markers.Count);

            foreach (var marker in markers)
            {
                if (marker.SegmentsX != segmentX || marker.SegmentsY != segmentY)
                {
                    throw new ArgumentException("The Segment size has to be equal for all markers. Don't mix 16x16 and 32x32 markers for example.", "markers");
                }
                patternMatchers.Add(new PatternMatcher(marker));
            }

            // Load deafult camera calibration data
            var asmName = new System.Reflection.AssemblyName(System.Reflection.Assembly.GetExecutingAssembly().FullName).Name;

            var streamResInfoCam = Application.GetResourceStream(new Uri(asmName + ";component/data/Camera_Calibration_Default.dat", UriKind.Relative));
            var cameraParameters = new NyARParam();

            using (var cameraCalibrationDataStream = streamResInfoCam.Stream)
            {
                cameraParameters.loadARParam(cameraCalibrationDataStream);
                cameraParameters.changeScreenSize(width, height);
            }

            // Get projection matrix from camera calibration data
            this.Projection = cameraParameters.GetCameraFrustumRH(nearPlane, farPlane);

            // Init detector and necessary data
            var colorPattern = new NyARColorPatt_Perspective_O2(segmentX, segmentY, 4, 25);
            var patternMatchDeviationData = new NyARMatchPattDeviationColorData(segmentX, segmentY);

            this.squareDetector          = new NyARSquareContourDetector_Rle(cameraParameters.getScreenSize());
            this.squareDetectionListener = new SquareDetectionListener(patternMatchers, cameraParameters, colorPattern, patternMatchDeviationData);

            // Init buffer members
            this.filteredBuffer = new NyARBinRaster(width, height);
            if (adaptive)
            {
                this.bufferFilter = new NyARRasterFilter_AdaptiveThreshold(bufferType);
            }
            else
            {
                this.bufferFilter = new NyARRasterFilter_ARToolkitThreshold(this.Threshold, bufferType);
            }
        }
        protected void initInstance(
            INyARColorPatt i_patt_inst,
            NyARSquareContourDetector i_sqdetect_inst,
            INyARTransMat i_transmat_inst,
            INyARRasterFilter_Rgb2Bin i_filter,
            NyARParam i_ref_param,
            NyARCode i_ref_code,
            double i_marker_width)
        {
            NyARIntSize scr_size = i_ref_param.getScreenSize();

            // 解析オブジェクトを作る
            this._square_detect = i_sqdetect_inst;
            this._transmat      = i_transmat_inst;
            this._tobin_filter  = i_filter;
            //2値画像バッファを作る
            this._bin_raster = new NyARBinRaster(scr_size.w, scr_size.h);
            //パターンの一致検索処理用
            this._inst_patt      = i_patt_inst;
            this._deviation_data = new NyARMatchPattDeviationColorData(i_ref_code.getWidth(), i_ref_code.getHeight());
            this._coordline      = new NyARCoord2Linear(i_ref_param.getScreenSize(), i_ref_param.getDistortionFactor());
            this._match_patt     = new NyARMatchPatt_Color_WITHOUT_PCA(i_ref_code);
            //オフセットを作成
            this._offset = new NyARRectOffset();
            this._offset.setSquare(i_marker_width);
            return;
        }
            /**
             * 矩形が見付かるたびに呼び出されます。
             * 発見した矩形のパターンを検査して、方位を考慮した頂点データを確保します。
             */
            public void onSquareDetect(NyARSquareContourDetector i_sender, int[] i_coordx, int[] i_coordy, int i_coor_num, int[] i_vertex_index)
            {
                NyARMatchPattResult mr = this.__detectMarkerLite_mr;

                //輪郭座標から頂点リストに変換
                NyARIntPoint2d[] vertex = this.__tmp_vertex;
                vertex[0].x = i_coordx[i_vertex_index[0]];
                vertex[0].y = i_coordy[i_vertex_index[0]];
                vertex[1].x = i_coordx[i_vertex_index[1]];
                vertex[1].y = i_coordy[i_vertex_index[1]];
                vertex[2].x = i_coordx[i_vertex_index[2]];
                vertex[2].y = i_coordy[i_vertex_index[2]];
                vertex[3].x = i_coordx[i_vertex_index[3]];
                vertex[3].y = i_coordy[i_vertex_index[3]];

                //画像を取得
                if (!this._inst_patt.pickFromRaster(this._ref_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_coordx, i_coordy, i_coor_num, sq.line[i]);
                }
                for (int i = 0; i < 4; i++)
                {
                    //直線同士の交点計算
                    if (!NyARLinear.crossPos(sq.line[i], sq.line[(i + 3) % 4], sq.sqvertex[i]))
                    {
                        throw new NyARException();//ここのエラー復帰するならダブルバッファにすればOK
                    }
                }
            }
Exemple #5
0
        protected void initInstance(NyARParam i_param, int i_raster_type)
        {
            //初期化済?
            Debug.Assert(this._initialized == false);

            NyARIntSize scr_size = i_param.getScreenSize();

            // 解析オブジェクトを作る
            this._square_detect = new NyARSquareContourDetector_Rle(scr_size);
            this._transmat      = new NyARTransMat(i_param);
            this._tobin_filter  = new NyARRasterFilter_ARToolkitThreshold(110, i_raster_type);

            // 2値画像バッファを作る
            this._bin_raster       = new NyARBinRaster(scr_size.w, scr_size.h);
            this._threshold_detect = new NyARRasterThresholdAnalyzer_SlidePTile(15, i_raster_type, 4);
            this._initialized      = true;
            //コールバックハンドラ
            this._detectmarker_cb = new DetectSquareCB(i_param);
            this._offset          = new NyARRectOffset();
            return;
        }
        protected void initInstance(
            INyARColorPatt i_patt_inst,
            NyARSquareContourDetector i_sqdetect_inst,
            INyARTransMat i_transmat_inst,
            INyARRasterFilter_Rgb2Bin i_filter,
            NyARParam i_ref_param,
            NyARCode i_ref_code,
            double i_marker_width)
        {
            NyARIntSize scr_size = i_ref_param.getScreenSize();

            // 解析オブジェクトを作る
            this._square_detect = i_sqdetect_inst;
            this._transmat      = i_transmat_inst;
            this._tobin_filter  = i_filter;
            //2値画像バッファを作る
            this._bin_raster = new NyARBinRaster(scr_size.w, scr_size.h);
            //_detect_cb
            this._detect_cb = new DetectSquareCB(i_patt_inst, i_ref_code, i_ref_param);
            //オフセットを作成
            this._offset = new NyARRectOffset();
            this._offset.setSquare(i_marker_width);
            return;
        }
            /**
             * 矩形が見付かるたびに呼び出されます。
             * 発見した矩形のパターンを検査して、方位を考慮した頂点データを確保します。
             */
            public void onSquareDetect(NyARSquareContourDetector i_sender, int[] i_coordx, int[] i_coordy, int i_coor_num, int[] i_vertex_index)
            {
                //既に発見済なら終了
                if (this.marker_data != null)
                {
                    return;
                }
                //輪郭座標から頂点リストに変換
                NyARIntPoint2d[] vertex = this.__tmp_vertex;
                vertex[0].x = i_coordx[i_vertex_index[0]];
                vertex[0].y = i_coordy[i_vertex_index[0]];
                vertex[1].x = i_coordx[i_vertex_index[1]];
                vertex[1].y = i_coordy[i_vertex_index[1]];
                vertex[2].x = i_coordx[i_vertex_index[2]];
                vertex[2].y = i_coordy[i_vertex_index[2]];
                vertex[3].x = i_coordx[i_vertex_index[3]];
                vertex[3].y = i_coordy[i_vertex_index[3]];

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

                // 評価基準になるパターンをイメージから切り出す
                if (!this._id_pickup.pickFromRaster(this._ref_raster, 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_coordx, i_coordy, i_coor_num, sq.line[i]);
                }
                for (int i = 0; i < 4; i++)
                {
                    //直線同士の交点計算
                    if (!NyARLinear.crossPos(sq.line[i], sq.line[(i + 3) % 4], sq.sqvertex[i]))
                    {
                        throw new NyARException();//ここのエラー復帰するならダブルバッファにすればOK
                    }
                }
                this.threshold   = param.threshold;
                this.marker_data = this._current_data;//みつかった。
            }
Exemple #8
0
            /**
             * 矩形が見付かるたびに呼び出されます。
             * 発見した矩形のパターンを検査して、方位を考慮した頂点データを確保します。
             */
            public void onSquareDetect(NyARSquareContourDetector i_sender, int[] i_coordx, int[] i_coordy, int i_coor_num, int[] i_vertex_index)
            {
                if (this._match_patt == null)
                {
                    return;
                }
                //輪郭座標から頂点リストに変換
                NyARIntPoint2d[] vertex = this.__tmp_vertex;
                vertex[0].x = i_coordx[i_vertex_index[0]];
                vertex[0].y = i_coordy[i_vertex_index[0]];
                vertex[1].x = i_coordx[i_vertex_index[1]];
                vertex[1].y = i_coordy[i_vertex_index[1]];
                vertex[2].x = i_coordx[i_vertex_index[2]];
                vertex[2].y = i_coordy[i_vertex_index[2]];
                vertex[3].x = i_coordx[i_vertex_index[3]];
                vertex[3].y = i_coordy[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_coordx, i_coordy, i_coor_num, sq.line[i]);
                }
                for (int i = 0; i < 4; i++)
                {
                    //直線同士の交点計算
                    if (!NyARLinear.crossPos(sq.line[i], sq.line[(i + 3) % 4], sq.sqvertex[i]))
                    {
                        throw new NyARException();//ここのエラー復帰するならダブルバッファにすればOK
                    }
                }
            }
        /// <summary>
        /// Listener method called when something was detected.
        /// </summary>
        /// <param name="callingDetector">The detector that called the method.</param>
        /// <param name="coordsX">The four x coordinates of the detected marker square.</param>
        /// <param name="coordsY">The four y coordinates of the detected marker square.</param>
        /// <param name="coordCount">The number of coordinates.</param>
        /// <param name="coordIndices">The indices of the coordiantes in the coords array.</param>
        public void onSquareDetect(NyARSquareContourDetector callingDetector, int[] coordsX, int[] coordsY, int coordCount, int[] coordIndices)
        {
            // Init variables
            points[0].x = coordsX[coordIndices[0]];
            points[0].y = coordsY[coordIndices[0]];
            points[1].x = coordsX[coordIndices[1]];
            points[1].y = coordsY[coordIndices[1]];
            points[2].x = coordsX[coordIndices[2]];
            points[2].y = coordsY[coordIndices[2]];
            points[3].x = coordsX[coordIndices[3]];
            points[3].y = coordsY[coordIndices[3]];

            // Evaluate and find best match
            if (this.colorPattern.pickFromRaster(this.Buffer, points))
            {
                // Find best matching marker
                this.patternMatchDeviationData.setRaster(this.colorPattern);
                Marker foundMarker    = null;
                int    foundDirection = NyARMatchPattResult.DIRECTION_UNKNOWN;
                double bestConfidence = 0;

                foreach (var patMat in patternMatchers)
                {
                    // Evaluate
                    patMat.evaluate(this.patternMatchDeviationData, evaluationResult);

                    // Best match?
                    if (evaluationResult.confidence > bestConfidence)
                    {
                        foundMarker    = patMat.Marker;
                        foundDirection = evaluationResult.direction;
                        bestConfidence = evaluationResult.confidence;
                    }
                }

                // Calculate found marker square
                var square = new NyARSquare();
                var len    = coordIndices.Length;
                for (int i = 0; i < len; i++)
                {
                    int idx = (i + len - foundDirection) % len;
                    this.coordinationMapper.coord2Line(coordIndices[idx], coordIndices[(idx + 1) % len], coordsX, coordsY, coordCount, square.line[i]);
                }
                // Calculate normal
                for (int i = 0; i < len; i++)
                {
                    NyARLinear.crossPos(square.line[i], square.line[(i + 3) % len], square.sqvertex[i]);
                }

                // Calculate matrix using continued mode
                if (foundMarker != null)
                {
                    var nymat = new NyARTransMatResult();
                    matrixCalculator.transMatContinue(square, foundMarker.RectOffset, nymat);

                    // Create and add result to collection
                    var v            = square.sqvertex;
                    var resultSquare = new Square(v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, v[3].x, v[3].y);
                    Results.Add(new DetectionResult(foundMarker, bestConfidence, nymat.ToMatrix3D(), resultSquare));
                }
            }
        }
Exemple #10
0
            /**
             * 矩形が見付かるたびに呼び出されます。
             * 発見した矩形のパターンを検査して、方位を考慮した頂点データを確保します。
             */
            public void onSquareDetect(NyARSquareContourDetector i_sender, int[] i_coordx, int[] i_coordy, int i_coor_num, int[] i_vertex_index)
            {
                NyARMatchPattResult mr = this.__detectMarkerLite_mr;

                //輪郭座標から頂点リストに変換
                NyARIntPoint2d[] vertex = this.__tmp_vertex;
                vertex[0].x = i_coordx[i_vertex_index[0]];
                vertex[0].y = i_coordy[i_vertex_index[0]];
                vertex[1].x = i_coordx[i_vertex_index[1]];
                vertex[1].y = i_coordy[i_vertex_index[1]];
                vertex[2].x = i_coordx[i_vertex_index[2]];
                vertex[2].y = i_coordy[i_vertex_index[2]];
                vertex[3].x = i_coordx[i_vertex_index[3]];
                vertex[3].y = i_coordy[i_vertex_index[3]];

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

                //最も一致するパターンを割り当てる。
                int    square_index, direction;
                double confidence;

                this._match_patt[0].evaluate(this._deviation_data, mr);
                square_index = 0;
                direction    = mr.direction;
                confidence   = mr.confidence;
                //2番目以降
                for (int i = 1; i < this._match_patt.Length; i++)
                {
                    this._match_patt[i].evaluate(this._deviation_data, mr);
                    if (confidence > mr.confidence)
                    {
                        continue;
                    }
                    // もっと一致するマーカーがあったぽい
                    square_index = i;
                    direction    = mr.direction;
                    confidence   = mr.confidence;
                }
                //最も一致したマーカ情報を、この矩形の情報として記録する。
                NyARDetectMarkerResult result = this.result_stack.prePush();

                result.arcode_id  = square_index;
                result.confidence = confidence;

                NyARSquare sq = result.square;

                //directionを考慮して、squareを更新する。
                for (int i = 0; i < 4; i++)
                {
                    int idx = (i + 4 - direction) % 4;
                    this._coordline.coord2Line(i_vertex_index[idx], i_vertex_index[(idx + 1) % 4], i_coordx, i_coordy, i_coor_num, sq.line[i]);
                }
                for (int i = 0; i < 4; i++)
                {
                    //直線同士の交点計算
                    if (!NyARLinear.crossPos(sq.line[i], sq.line[(i + 3) % 4], sq.sqvertex[i]))
                    {
                        throw new NyARException();//ここのエラー復帰するならダブルバッファにすればOK
                    }
                }
            }
        /**
         * この関数は、ラスタから矩形を検出して、自己コールバック関数{@link #onSquareDetect}で通知します。
         * 実装クラスでは、矩形検出処理をして、結果を通知する処理を実装してください。
         * @param i_raster
         * 検出元のラスタ画像
         * @
         */
        public void detectMarker(NyARBinRaster i_raster, NyARSquareContourDetector.CbHandler i_cb)
        {
            NyARLabelingImage limage = this._limage;

            // ラベル数が0ならここまで
            int label_num = this._labeling.labeling(i_raster, this._limage);
            if (label_num < 1)
            {
                return;
            }

            NyARLabelingLabelStack stack = limage.getLabelStack();
            //ラベルをソートしておく
            stack.sortByArea();
            //
            NyARLabelingLabel[] labels = stack.getArray();

            // デカいラベルを読み飛ばし
            int i;
            for (i = 0; i < label_num; i++)
            {
                // 検査対象内のラベルサイズになるまで無視
                if (labels[i].area <= AR_AREA_MAX)
                {
                    break;
                }
            }
            int xsize = this._width;
            int ysize = this._height;
            NyARIntCoordinates coord = this._coord;
            int[] mkvertex = this.__detectMarker_mkvertex;

            NyARLabelOverlapChecker<NyARLabelingLabel> overlap = this._overlap_checker;

            //重なりチェッカの最大数を設定
            overlap.setMaxLabels(label_num);
            for (; i < label_num; i++)
            {
                NyARLabelingLabel label_pt = labels[i];
                int label_area = label_pt.area;
                // 検査対象サイズよりも小さくなったら終了
                if (label_area < AR_AREA_MIN)
                {
                    break;
                }
                // クリップ領域が画面の枠に接していれば除外
                if (label_pt.clip_l == 1 || label_pt.clip_r == xsize - 2)
                {// if(wclip[i*4+0] == 1 || wclip[i*4+1] ==xsize-2){
                    continue;
                }
                if (label_pt.clip_t == 1 || label_pt.clip_b == ysize - 2)
                {// if( wclip[i*4+2] == 1 || wclip[i*4+3] ==ysize-2){
                    continue;
                }
                // 既に検出された矩形との重なりを確認
                if (!overlap.check(label_pt))
                {
                    // 重なっているようだ。
                    continue;
                }
                // 輪郭を取得
                if (!this._cpickup.getContour(limage, limage.getTopClipTangentX(label_pt), 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;
        }
        /**
         * この関数は、ラスタから矩形を検出して、自己コールバック関数{@link #onSquareDetect}で通知します。
         * @param i_raster
         * 検出元のラスタ画像
         * 入力できるラスタの画素形式は、{@link NyARLabeling_Rle#labeling(INyARRaster, int)}と同じです。
         * @param i_area
         * 検出する範囲。検出元のラスタの内側である必要があります。
         * @param i_th
         * ラベルと判定する敷居値
         * @
         */
        public void detectMarker(INyARGrayscaleRaster i_raster, NyARIntRect i_area, int i_th, NyARSquareContourDetector.CbHandler i_cb)
        {
            Debug.Assert(i_area.w * i_area.h > 0);

            NyARRleLabelFragmentInfoPtrStack flagment = this._labeling.label_stack;
            NyARLabelOverlapChecker<NyARRleLabelFragmentInfo> overlap = this._overlap_checker;
            //ラベルの生成エラーならここまで
            if (!this._labeling.labeling(i_raster, i_area, i_th))
            {
                return;
            }
            // ラベル数が0ならここまで
            int label_num = flagment.getLength();
            if (label_num < 1)
            {
                return;
            }

            //ラベルリストを取得
            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];
                // 既に検出された矩形との重なりを確認
                if (!overlap.check(label_pt))
                {
                    // 重なっているようだ。
                    continue;
                }

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

                // 検出済の矩形の属したラベルを重なりチェックに追加する。
                overlap.push(label_pt);

            }
            return;
        }
 public void detectMarkerCb(NyARSensor i_sensor, int i_th, NyARSquareContourDetector.CbHandler i_handler)
 {
     this._sd.detectMarker(i_sensor.GetGsImage(), i_th, i_handler);
 }