/** * 矩形が見付かるたびに呼び出されます。 * 発見した矩形のパターンを検査して、方位を考慮した頂点データを確保します。 */ 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 } } }
/// <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 string location = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); StreamReader reader = new StreamReader(location + "/Content/Data/Camera_Calibration_1280x720.dat"); var cameraParameters = new NyARParam(); using (var cameraCalibrationDataStream = reader.BaseStream) { cameraParameters.loadARParam(cameraCalibrationDataStream); cameraParameters.changeScreenSize(width, height); } //var asmName = new System.Reflection.AssemblyName(System.Reflection.Assembly.GetExecutingAssembly().FullName).Name; //var uri = new Uri(asmName + ";component/Assets/data/Camera_Calibration_1280x720.dat", UriKind.Relative); //var streamResInfoCam = Application.GetResourceStream(uri); //if (null == streamResInfoCam) // throw new FileNotFoundException("Application.GetResourceStream returned null", uri.OriginalString); //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); } }
/** * この関数は、ラスタから矩形を検出して、自己コールバック関数{@link #onSquareDetect}で通知します。 * ARToolKitのarDetectMarker2を基にしています。 * @param i_raster * 検出元のラスタ画像 * 入力できるラスタの画素形式は、{@link NyARLabeling_Rle#labeling(NyARGrayscaleRaster, int)}と同じです。 * @param i_th * 画素の二値判定敷居値です。この値は、ラベリングと、輪郭線追跡時に使われます。 */ public void detectMarker(INyARGrayscaleRaster i_raster, int i_th, NyARSquareContourDetector.CbHandler i_cb) { NyARRleLabelFragmentInfoPtrStack flagment = this._labeling.label_stack; NyARLabelOverlapChecker<NyARRleLabelFragmentInfo> overlap = this._overlap_checker; flagment.clear(); //ラベルの生成エラーならここまで if (!this._labeling.labeling(i_raster, i_th)) { return; } int label_num = flagment.getLength(); // ラベル数が0ならここまで if (label_num < 1) { return; } //ラベルをソートしておく flagment.sortByArea(); //ラベルリストを取得 NyARRleLabelFragmentInfo[] labels = flagment.getArray(); NyARIntCoordinates coord = this._coord; int[] mkvertex = this.__detectMarker_mkvertex; //重なりチェッカの最大数を設定 overlap.setMaxLabels(label_num); for (int i = 0; i < label_num; i++) { NyARRleLabelFragmentInfo label_pt = labels[i]; int label_area = label_pt.area; // 既に検出された矩形との重なりを確認 if (!overlap.check(label_pt)) { // 重なっているようだ。 continue; } //輪郭を取得 if (!this._cpickup.getContour(i_raster, i_th, label_pt.entry_x, label_pt.clip_t, coord)) { continue; } //輪郭線をチェックして、矩形かどうかを判定。矩形ならばmkvertexに取得 if (!this._coord2vertex.getVertexIndexes(coord, label_area, mkvertex)) { // 頂点の取得が出来なかった continue; } //矩形を発見したことをコールバック関数で通知 i_cb.detectMarkerCallback(coord, mkvertex); // 検出済の矩形の属したラベルを重なりチェックに追加する。 overlap.push(label_pt); } return; }
/** * 矩形が見付かるたびに呼び出されます。 * 発見した矩形のパターンを検査して、方位を考慮した頂点データを確保します。 */ 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;//みつかった。 }
public void detectMarkerCb(NyARSensor i_sensor,int i_th,NyARSquareContourDetector.CbHandler i_handler) { this._sd.detectMarker(i_sensor.getGsImage(), i_th,i_handler); }
/// <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)); } } }
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; }
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; }
/** * 矩形が見付かるたびに呼び出されます。 * 発見した矩形のパターンを検査して、方位を考慮した頂点データを確保します。 */ 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 } } }