/** * 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; }
/**オブジェクトのステータスを更新し、必要に応じてハンドル関数を駆動します。 */ private bool updateStatus(NyARSquare i_square, INyIdMarkerData i_marker_data) { bool is_id_found = false; NyARTransMatResult result = this.__NyARSquare_result; if (!this._is_active) { // 未認識中 if (i_marker_data == null) { // 未認識から未認識の遷移 // なにもしないよーん。 this._is_active = false; } else {// 未認識から認識の遷移 this._data_current.copyFrom(i_marker_data); // イベント生成 // OnEnter this.onEnterHandler(this._data_current); // 変換行列を作成 this._transmat.transMat(i_square, this._offset, result); // OnUpdate this.onUpdateHandler(i_square, result); this._lost_delay_count = 0; this._is_active = true; is_id_found = true; } } else {// 認識中 if (i_marker_data == null) { // 認識から未認識の遷移 this._lost_delay_count++; if (this._lost_delay < this._lost_delay_count) { // OnLeave this.onLeaveHandler(); this._is_active = false; } } else if (this._data_current.isEqual(i_marker_data)) { //同じidの再認識 this._transmat.transMatContinue(i_square, this._offset, result); // OnUpdate this.onUpdateHandler(i_square, result); this._lost_delay_count = 0; is_id_found = true; } else {// 異なるコードの認識→今はサポートしない。 throw new NyARException(); } } return(is_id_found); }
/** オブジェクトのステータスを更新し、必要に応じてハンドル関数を駆動します。 * 戻り値は、「実際にマーカを発見する事ができたか」です。クラスの状態とは異なります。 */ private bool updateStatus(NyARSquare i_square, int i_code_index) { NyARTransMatResult result = this.__NyARSquare_result; if (this._current_arcode_index < 0) { // 未認識中 if (i_code_index < 0) { // 未認識から未認識の遷移 // なにもしないよーん。 return(false); } else {// 未認識から認識の遷移 this._current_arcode_index = i_code_index; // イベント生成 // OnEnter this.onEnterHandler(i_code_index); // 変換行列を作成 this._transmat.transMat(i_square, this._offset, result); // OnUpdate this.onUpdateHandler(i_square, result); this._lost_delay_count = 0; return(true); } } else { // 認識中 if (i_code_index < 0) { // 認識から未認識の遷移 this._lost_delay_count++; if (this._lost_delay < this._lost_delay_count) { // OnLeave this._current_arcode_index = -1; this.onLeaveHandler(); } return(false); } else if (i_code_index == this._current_arcode_index) {// 同じARCodeの再認識 // イベント生成 // 変換行列を作成 this._transmat.transMatContinue(i_square, this._offset, result); // OnUpdate this.onUpdateHandler(i_square, result); this._lost_delay_count = 0; return(true); } else {// 異なるコードの認識→今はサポートしない。 throw new NyARException(); } } }
/* * (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; }
/** * 検出したマーカーの変換行列を計算して、o_resultへ値を返します。 * 直前に実行したdetectMarkerLiteが成功していないと使えません。 * * @param o_result * 変換行列を受け取るオブジェクトを指定します。 * @throws NyARException */ public void getTransmationMatrix(NyARTransMatResult o_result) { // 一番一致したマーカーの位置とかその辺を計算 if (this._is_continue) { this._transmat.transMatContinue(this._detect_cb.square, this._offset, o_result); } else { this._transmat.transMat(this._detect_cb.square, this._offset, o_result); } return; }
public void Test_arDetectMarkerLite() { Assembly assembly = Assembly.GetExecutingAssembly(); //AR用カメラパラメタファイルをロード NyARParam ap = new NyARParam(); ap.loadARParam(assembly.GetManifestResourceStream(RES_CAMERA)); ap.changeScreenSize(320, 240); //AR用のパターンコードを読み出し NyARCode code = new NyARCode(16, 16); Stream sr1 = assembly.GetManifestResourceStream(RES_PATT); code.loadARPatt(new StreamReader(sr1)); //試験イメージの読み出し(320x240 BGRAのRAWデータ) StreamReader sr = new StreamReader(assembly.GetManifestResourceStream(RES_DATA)); BinaryReader bs = new BinaryReader(sr.BaseStream); byte[] raw = bs.ReadBytes(320 * 240 * 4); NyARRgbRaster_BGRA ra = new NyARRgbRaster_BGRA(320, 240, false); ra.wrapBuffer(raw); // Blank_Raster ra=new Blank_Raster(320, 240); //1パターンのみを追跡するクラスを作成 // NyARSingleDetectMarker_Quad ar = new NyARSingleDetectMarker_Quad(ap, code, 80.0); NyARSingleDetectMarker ar = new NyARSingleDetectMarker(ap, code, 80.0, ra.getBufferType()); NyARTransMatResult result_mat = new NyARTransMatResult(); ar.setContinueMode(false); ar.detectMarkerLite(ra, 100); ar.getTransmationMatrix(result_mat); //マーカーを検出 for (int i3 = 0; i3 < 10; i3++) { Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < 10; i++) { //変換行列を取得 ar.detectMarkerLite(ra, 100); ar.getTransmationMatrix(result_mat); } sw.Stop(); Debug.WriteLine(sw.ElapsedMilliseconds + "[ms]"); } return; }
/** * i_indexのマーカーに対する変換行列を計算し、結果値をo_resultへ格納します。 直前に実行したdetectMarkerLiteが成功していないと使えません。 * * @param i_index * マーカーのインデックス番号を指定します。 直前に実行したdetectMarkerLiteの戻り値未満かつ0以上である必要があります。 * @param o_result * 結果値を受け取るオブジェクトを指定してください。 * @throws NyARException */ public void getTransmationMatrix(int i_index, NyARTransMatResult o_result) { NyARDetectMarkerResult result = this._square_detect.result_stack.getItem(i_index); // 一番一致したマーカーの位置とかその辺を計算 if (_is_continue) { _transmat.transMatContinue(result.square, this._offset[result.arcode_id], o_result, o_result); } else { _transmat.transMat(result.square, this._offset[result.arcode_id], o_result); } return; }
public void toD3dMatrix(NyARTransMatResult i_ny_result, ref Matrix o_result) { //ARのMatrixをDirectXのMatrixに変換 o_result.M11 = (float)i_ny_result.m00; o_result.M12 = (float)i_ny_result.m10; o_result.M13 = (float)i_ny_result.m20; o_result.M14 = 0; o_result.M21 = (float)i_ny_result.m01; o_result.M22 = (float)i_ny_result.m11; o_result.M23 = (float)i_ny_result.m21; o_result.M24 = 0; o_result.M31 = (float)i_ny_result.m02; o_result.M32 = (float)i_ny_result.m12; o_result.M33 = (float)i_ny_result.m22; o_result.M34 = 0; o_result.M41 = (float)i_ny_result.m03; o_result.M42 = (float)i_ny_result.m13; o_result.M43 = (float)i_ny_result.m23; o_result.M44 = 1; return; }
/** * 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 = 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.initRotBySquare(i_square.line, i_square.sqvertex); //回転後の3D座標系から、平行移動量を計算 this._rotmatrix.getPoint3dBatch(i_offset.vertex, vertex_3d, 4); this._transsolver.solveTransportVector(vertex_3d, trans); //計算結果の最適化(平行移動量と回転行列の最適化) o_result_conv.error = this.optimize(this._rotmatrix, trans, this._transsolver, i_offset.vertex, vertex_2d); // マトリクスの保存 this.updateMatrixValue(this._rotmatrix, trans, o_result_conv); return; }
/// <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)); } } }
//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); } }
void CaptureListener.OnBuffer(CaptureDevice i_sender, double i_sample_time, IntPtr i_buffer, int i_buffer_len) { // calculate size of the frame bitmap int w = i_sender.video_width; int h = i_sender.video_height; int s = w * (i_sender.video_bit_count / 8); // stride AForge.Imaging.Filters.FiltersSequence seq = new AForge.Imaging.Filters.FiltersSequence(); seq.Add(new AForge.Imaging.Filters.Grayscale(0.2125, 0.7154, 0.0721)); seq.Add(new AForge.Imaging.Filters.Threshold(127)); seq.Add(new AForge.Imaging.Filters.GrayscaleToRGB()); AForge.Imaging.UnmanagedImage srcImg = new AForge.Imaging.UnmanagedImage(i_buffer, w, h, s, System.Drawing.Imaging.PixelFormat.Format32bppRgb); AForge.Imaging.UnmanagedImage outputImg = seq.Apply(srcImg); byte[] destArr = new byte[outputImg.Stride * outputImg.Height]; System.Runtime.InteropServices.Marshal.Copy(outputImg.ImageData, destArr, 0, outputImg.Stride * outputImg.Height); this.m_raster.wrapBuffer(destArr); try { int detectedMkrs = this.m_ar.detectMarkerLite(this.m_raster, m_threshold); NyARSquare square = null; if (detectedMkrs > 0) { NyARTransMatResult transMat = new NyARTransMatResult(); NyARDoublePoint2d[] points = m_ar.getCorners(0); // RichF added this method square = new NyARSquare(); square.sqvertex = points; } Dispatcher.BeginInvoke(new Action(delegate() { TransformedBitmap b = new TransformedBitmap(); b.BeginInit(); b.Source = BitmapSource.Create(w, h, dpiX, dpiY, PixelFormats.Bgr32, BitmapPalettes.WebPalette, i_buffer, i_buffer_len, s); b.SetValue(TransformedBitmap.TransformProperty, new ScaleTransform(-1, -1)); b.EndInit(); image1.SetValue(Image.SourceProperty, b); if (square != null) { recognizedTag.Points = new PointCollection(new Point[] { new Point(cameraResX - square.sqvertex[0].x, cameraResY - square.sqvertex[0].y), new Point(cameraResX - square.sqvertex[1].x, cameraResY - square.sqvertex[1].y), new Point(cameraResX - square.sqvertex[2].x, cameraResY - square.sqvertex[2].y), new Point(cameraResX - square.sqvertex[3].x, cameraResY - square.sqvertex[3].y) }); recognizedTag.Visibility = System.Windows.Visibility.Visible; } else { recognizedTag.Visibility = System.Windows.Visibility.Hidden; } }), null); } catch { } }
//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); } }
/** * この関数は、理想座標系の四角系を元に、位置姿勢変換行列を求めます。 * 計算に過去の履歴を使う点が、{@link #transMat}と異なります。 * @see INyARTransMat#transMatContinue */ public bool transMatContinue(NyARSquare i_square, NyARRectOffset i_offset, NyARTransMatResult i_prev_result, NyARTransMatResult o_result) { NyARDoublePoint3d trans = this.__transMat_trans; // i_prev_resultが初期値なら、transMatで計算する。 if (!i_prev_result.has_value) { this.transMat(i_square, i_offset, o_result); return true; } //平行移動量計算機に、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, err); // エラー値が許容範囲でなければ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) { // 良い値が取れたら、差換え o_result.setValue(this._rotmatrix, trans, err2); } err = err2; } //エラー値保存 return true; }
/** * この関数は、理想座標系の四角系を元に、位置姿勢変換行列を求めます。 * ARToolKitのarGetTransMatに該当します。 * @see INyARTransMat#transMatContinue */ public bool 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 true; }
protected abstract void onUpdateHandler(NyARSquare i_square, NyARTransMatResult result);
/** * @deprecated * {@link #getTransmat} */ public void getTransmationMatrix(NyARTransMatResult o_result) { this.getTransmat(o_result); return; }
/** * パラメータで変換行列を更新します。 * * @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; }
/** * This function retrieves bitmap from the area defined by RECT(i_l,i_t,i_r,i_b) above transform matrix i_base_mat. * ---- * この関数は、basementで示される平面のAで定義される領域から、ビットマップを読み出します。 * 例えば、8cmマーカでRECT(i_l,i_t,i_r,i_b)に-40,0,0,-40.0を指定すると、マーカの左下部分の画像を抽出します。 * * マーカから離れた場所になるほど、また、マーカの鉛直方向から外れるほど誤差が大きくなります。 * @param i_src_imege * 詠み出し元の画像を指定します。 * @param i_l * 基準点からの左上の相対座標(x)を指定します。 * @param i_t * 基準点からの左上の相対座標(y)を指定します。 * @param i_r * 基準点からの右下の相対座標(x)を指定します。 * @param i_b * 基準点からの右下の相対座標(y)を指定します。 * @param i_base_mat * @return 画像の取得の成否を返す。 */ public bool pickupImage2d(INyARRgbRaster i_src_imege, double i_l, double i_t, double i_r, double i_b, NyARTransMatResult i_base_mat) { double cp00, cp01, cp02, cp11, cp12; cp00 = this._ref_perspective.m00; cp01 = this._ref_perspective.m01; cp02 = this._ref_perspective.m02; cp11 = this._ref_perspective.m11; cp12 = this._ref_perspective.m12; //マーカと同一平面上にある矩形の4個の頂点を座標変換して、射影変換して画面上の //頂点を計算する。 //[hX,hY,h]=[P][RT][x,y,z] //出力先 NyARIntPoint2d[] poinsts = this._work_points; double yt0, yt1, yt2; double x3, y3, z3; double m00 = i_base_mat.m00; double m10 = i_base_mat.m10; double m20 = i_base_mat.m20; //yとtの要素を先に計算 yt0 = i_base_mat.m01 * i_t + i_base_mat.m03; yt1 = i_base_mat.m11 * i_t + i_base_mat.m13; yt2 = i_base_mat.m21 * i_t + i_base_mat.m23; // l,t x3 = m00 * i_l + yt0; y3 = m10 * i_l + yt1; z3 = m20 * i_l + yt2; poinsts[0].x = (int)((x3 * cp00 + y3 * cp01 + z3 * cp02) / z3); poinsts[0].y = (int)((y3 * cp11 + z3 * cp12) / z3); // r,t x3 = m00 * i_r + yt0; y3 = m10 * i_r + yt1; z3 = m20 * i_r + yt2; poinsts[1].x = (int)((x3 * cp00 + y3 * cp01 + z3 * cp02) / z3); poinsts[1].y = (int)((y3 * cp11 + z3 * cp12) / z3); //yとtの要素を先に計算 yt0 = i_base_mat.m01 * i_b + i_base_mat.m03; yt1 = i_base_mat.m11 * i_b + i_base_mat.m13; yt2 = i_base_mat.m21 * i_b + i_base_mat.m23; // r,b x3 = m00 * i_r + yt0; y3 = m10 * i_r + yt1; z3 = m20 * i_r + yt2; poinsts[2].x = (int)((x3 * cp00 + y3 * cp01 + z3 * cp02) / z3); poinsts[2].y = (int)((y3 * cp11 + z3 * cp12) / z3); // l,b x3 = m00 * i_l + yt0; y3 = m10 * i_l + yt1; z3 = m20 * i_l + yt2; poinsts[3].x = (int)((x3 * cp00 + y3 * cp01 + z3 * cp02) / z3); poinsts[3].y = (int)((y3 * cp11 + z3 * cp12) / z3); return(this.pickFromRaster(i_src_imege, poinsts)); }
void DrawWord(string word, NyARTransMatResult result) { NyARD3dUtil.toD3dCameraView(result, 1f, ref this._trans_mat); this._surface.CopyFromXRGB32(Core.raster); lock (pbxNyAR) { //Ajustando a escala para cada desenho switch (word) { case "bola": scaling = scaleArray[0]; break; case "gato": scaling = scaleArray[1]; break; case "peixe": scaling = scaleArray[2]; break; case "garfo": scaling = scaleArray[3]; break; case "leao": scaling = scaleArray[4]; break; case "caneta": scaling = scaleArray[5]; break; case "panela": scaling = scaleArray[6]; break; case "radio": scaling = scaleArray[7]; break; case "tesoura": scaling = scaleArray[8]; break; case "faca": scaling = scaleArray[9]; break; case "espada": scaling = scaleArray[10]; break; case "mesa": scaling = scaleArray[11]; break; } // Background directly to the surface drawing Surface dest_surface = this._device.GetBackBuffer(0, 0, BackBufferType.Mono); Rectangle src_dest_rect = new Rectangle(0, 0, 543, 348); this._device.StretchRectangle(this._surface.d3d_surface, src_dest_rect, dest_surface, src_dest_rect, TextureFilter.None); // Drawing 3D objects from here this._device.BeginScene(); this._device.Clear(ClearFlags.ZBuffer, Color.DarkBlue, 1.0f, 0); //MATRIZ QUE DEFINE O POSICIONAMENTO DO OBJETO 3D //On 20mm cube (top marker) to be shifted Matrix transform_mat2 = Matrix.Scaling(scaling, scaling, scaling); transform_mat2 *= Matrix.RotationX((float)Math.PI * 1 / 2); //Multiply the transformation matrix transform_mat2 *= this._trans_mat; // Coordinate transformation matrix was calculated this._device.SetTransform(TransformType.World, transform_mat2); // Rendering (drawing) //this._cube.draw(this._device); //switch (word) //{ // case "sapo": // DrawMesh(listSpacemesh[0], listSpacemeshmaterials[0], listSpacemeshtextures[0]); // break; // case "bola": // DrawMesh(listSpacemesh[1], listSpacemeshmaterials[1], listSpacemeshtextures[1]); // break; //} //Plota a imagem switch (word) { case "bola": DrawMesh(listSpacemesh[0], listSpacemeshmaterials[0], listSpacemeshtextures[0]); break; case "gato": DrawMesh(listSpacemesh[1], listSpacemeshmaterials[1], listSpacemeshtextures[1]); break; case "peixe": DrawMesh(listSpacemesh[2], listSpacemeshmaterials[2], listSpacemeshtextures[2]); break; case "garfo": DrawMesh(listSpacemesh[3], listSpacemeshmaterials[3], listSpacemeshtextures[3]); break; case "leao": DrawMesh(listSpacemesh[4], listSpacemeshmaterials[4], listSpacemeshtextures[4]); break; case "caneta": DrawMesh(listSpacemesh[5], listSpacemeshmaterials[5], listSpacemeshtextures[5]); break; case "panela": DrawMesh(listSpacemesh[6], listSpacemeshmaterials[6], listSpacemeshtextures[6]); break; case "radio": DrawMesh(listSpacemesh[7], listSpacemeshmaterials[7], listSpacemeshtextures[7]); break; case "tesoura": DrawMesh(listSpacemesh[8], listSpacemeshmaterials[8], listSpacemeshtextures[8]); break; case "faca": DrawMesh(listSpacemesh[9], listSpacemeshmaterials[9], listSpacemeshtextures[9]); break; case "espada": DrawMesh(listSpacemesh[10], listSpacemeshmaterials[10], listSpacemeshtextures[10]); break; case "mesa": DrawMesh(listSpacemesh[11], listSpacemeshmaterials[11], listSpacemeshtextures[11]); break; } //DrawMesh(spacemesh, spacemeshmaterials, spacemeshtextures); //DrawMesh(listSpacemesh[2], listSpacemeshmaterials[2], listSpacemeshtextures[2]); // Drawing up here this._device.EndScene(); // Drawing on the actual display this._device.Present(); } }