/** * この関数は、オブジェクトからインスタンスに値をセットします。 * @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頂点でかこまれる領域を射影した平面から、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; }
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); }
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; }
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; }
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; }
/** * 画面座標群と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; }
/** * この関数は、理想座標系の四角系を元に、位置姿勢変換行列を求めます。 * 計算に過去の履歴を使う点が、{@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; }
/** * この関数は、理想座標系の四角系を元に、位置姿勢変換行列を求めます。 * 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; }
/** * カメラ座標系の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)); }
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); }
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; } } }
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; }
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)); }
/** * 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); }
//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); } }
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; }
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); }
/** * 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; }
//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); } }