From: nyatla Date: Mon, 27 Oct 2008 15:19:44 +0000 (+0000) Subject: [更新]NyARToolkit/2.1 X-Git-Tag: 2.1.0~2 X-Git-Url: http://git.osdn.net/view?p=nyartoolkit-and%2Fnyartoolkit-and.git;a=commitdiff_plain;h=07e13eb57d1b78509c1dbbc77ff20742996049ab [更新]NyARToolkit/2.1 --- diff --git a/readme.ja.txt b/readme.ja.txt index 8c369da..c08e897 100644 --- a/readme.ja.txt +++ b/readme.ja.txt @@ -1,7 +1,7 @@ ARToolKit Java class library NyARToolkit. Copyright (C)2008 R.Iizuka -version 2.0.0 +version 2.1.0 http://nyatla.jp/nyartoolkit/ airmail(at)ebony.plala.or.jp @@ -10,13 +10,14 @@ airmail(at)ebony.plala.or.jp -・NyARToolkit/2.0 +・NyARToolkit/2.1 NyARToolkitは、Pure Javaで実装したARToolKitクラスライブラリです。 ARToolKit 2.72.1をベースに構築されています。 -NyARToolkit/1.xと比較し、構造的な最適化がされ、可読性が向上しています。 +NyARToolkit/2.0系は、NyARToolkit/1.xと比較して構造的な最適化がされており、 +可読性と分離性が向上しています。 diff --git a/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/qrcode/NyARQrCodeDetector.java b/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/qrcode/NyARQrCodeDetector.java index 387fb4c..0433686 100644 --- a/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/qrcode/NyARQrCodeDetector.java +++ b/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/qrcode/NyARQrCodeDetector.java @@ -12,7 +12,7 @@ import jp.nyatla.nyartoolkit.core.labeling.NyARLabelingLabelStack; import jp.nyatla.nyartoolkit.core.labeling.NyARLabeling_ARToolKit; import jp.nyatla.nyartoolkit.core.param.NyARCameraDistortionFactor; import jp.nyatla.nyartoolkit.core.pca2d.INyARPca2d; -import jp.nyatla.nyartoolkit.core.pca2d.NyARPca2d_MatrixPCA_O2; +import jp.nyatla.nyartoolkit.core.pca2d.*; import jp.nyatla.nyartoolkit.core.raster.NyARBinRaster; import jp.nyatla.nyartoolkit.core.types.NyARDoublePoint2d; import jp.nyatla.nyartoolkit.core.types.NyARIntPoint; @@ -38,7 +38,8 @@ public class NyARQrCodeDetector implements INyARSquareDetector private final NyARLabelingImage _limage; private final NyARCameraDistortionFactor _dist_factor_ref; - + private final double[] _xpos; + private final double[] _ypos; /** * 最大i_squre_max個のマーカーを検出するクラスを作成する。 * @@ -61,6 +62,9 @@ public class NyARQrCodeDetector implements INyARSquareDetector this._max_coord = number_of_coord; this._xcoord = new int[number_of_coord * 2]; this._ycoord = new int[number_of_coord * 2]; + this._xpos=new double[this._width+this._height];//最大辺長はthis._width+this._height + this._ypos=new double[this._width+this._height];//最大辺長はthis._width+this._height + } private final int _max_coord; @@ -216,7 +220,7 @@ public class NyARQrCodeDetector implements INyARSquareDetector return; } private static int MAX_COORD_NUM=(320+240)*2;//サイズの1/2の長方形の編程度が目安(VGAなら(320+240)*2) - private final INyARPca2d _pca=new NyARPca2d_MatrixPCA_O2(MAX_COORD_NUM); + private final INyARPca2d _pca=new NyARPca2d_MatrixPCA_O2(); private final NyARDoubleMatrix22 __getSquareLine_evec=new NyARDoubleMatrix22(); private final NyARDoublePoint2d __getSquareLine_mean=new NyARDoublePoint2d(); private final NyARDoublePoint2d __getSquareLine_ev=new NyARDoublePoint2d(); @@ -228,7 +232,6 @@ public class NyARQrCodeDetector implements INyARSquareDetector */ private boolean getSquareLine(int[] i_mkvertex, int[] i_xcoord, int[] i_ycoord, NyARLinear[] o_line,NyARIntPoint[] o_imvertex) throws NyARException { - final NyARCameraDistortionFactor dist_factor=this._dist_factor_ref; final NyARDoubleMatrix22 evec=this.__getSquareLine_evec; final NyARDoublePoint2d mean=this.__getSquareLine_mean; final NyARDoublePoint2d ev=this.__getSquareLine_ev; @@ -243,8 +246,11 @@ public class NyARQrCodeDetector implements INyARSquareDetector // nが2以下、又はMAX_COORD_NUM以上なら主成分分析をしない。 return false; } + //配列作成 + this._dist_factor_ref.observ2IdealBatch(i_xcoord, i_ycoord, st, n,this._xpos,this._ypos); + //主成分分析する。 - this._pca.pcaWithDistortionFactor(i_xcoord, i_ycoord, st, n,dist_factor, evec, ev,mean); + this._pca.pca(this._xpos,this._ypos,n,evec, ev,mean); final NyARLinear l_line_i = o_line[i]; l_line_i.run = evec.m01;// line[i][0] = evec->m[1]; l_line_i.rise = -evec.m00;// line[i][1] = -evec->m[0]; diff --git a/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/quadx2/NyARSquareDetector_Quad.java b/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/quadx2/NyARSquareDetector_Quad.java index 4d696fd..f22b964 100644 --- a/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/quadx2/NyARSquareDetector_Quad.java +++ b/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/quadx2/NyARSquareDetector_Quad.java @@ -35,9 +35,11 @@ import jp.nyatla.nyartoolkit.core.labeling.*; import jp.nyatla.nyartoolkit.core.raster.*; import jp.nyatla.nyartoolkit.core.types.*; import jp.nyatla.nyartoolkit.core.param.*; -import jp.nyatla.nyartoolkit.core.types.matrix.*; -import jp.nyatla.nyartoolkit.core.pca2d.*; -import jp.nyatla.nyartoolkit.core2.pca2d.NyARPca2d_SamplingPCA; + + +import jp.nyatla.nyartoolkit.core2.types.NyARI64Linear; +import jp.nyatla.nyartoolkit.core2.types.NyARI64Point2d; +import jp.nyatla.nyartoolkit.core2.types.matrix.NyARI64Matrix22; import jp.nyatla.nyartoolkit.core.*; import jp.nyatla.nyartoolkit.sandbox.x2.*; @@ -48,408 +50,463 @@ import jp.nyatla.nyartoolkit.sandbox.x2.*; */ public class NyARSquareDetector_Quad implements INyARSquareDetector { - private static final double VERTEX_FACTOR = 1.0;// 線検出のファクタ - - private static final int AR_AREA_MAX = 25000;// #define AR_AREA_MAX 100000 - - private static final int AR_AREA_MIN = 20;// #define AR_AREA_MIN 70 - private final int _width; - private final int _height; - - private final INyARLabeling _labeling; - - private final NyARLabelingImage _limage; - - private final OverlapChecker _overlap_checker = new OverlapChecker(); - private final NyARCameraDistortionFactor _dist_factor=new NyARCameraDistortionFactor(); - - /** - * 最大i_squre_max個のマーカーを検出するクラスを作成する。 - * - * @param i_param - */ - public NyARSquareDetector_Quad(NyARCameraDistortionFactor i_dist_factor_ref,NyARIntSize i_size) throws NyARException - { - this._width = i_size.w/2; - this._height = i_size.h/2; - this._labeling = new NyARLabeling_ARToolKit_X2(); - this._limage = new NyARLabelingImage(this._width, this._height); - this._labeling.attachDestination(this._limage); - - // 輪郭の最大長は画面に映りうる最大の長方形サイズ。 - int number_of_coord = (this._width + this._height) * 2; - - // 輪郭バッファは頂点変換をするので、輪郭バッファの2倍取る。 - this._max_coord = number_of_coord; - this._xcoord = new int[number_of_coord * 2]; - this._ycoord = new int[number_of_coord * 2]; - //PCA - this._pca=new NyARPca2d_SamplingPCA(20); - //内部的に1/4のサイズで取り扱う - this._dist_factor.copyFrom(i_dist_factor_ref); - this._dist_factor.changeScale(0.5); - - } - - private final int _max_coord; - private final int[] _xcoord; - private final int[] _ycoord; - - private void normalizeCoord(int[] i_coord_x, int[] i_coord_y, int i_index, int i_coord_num) - { - // vertex1を境界にして、後方に配列を連結 - System.arraycopy(i_coord_x, 1, i_coord_x, i_coord_num, i_index); - System.arraycopy(i_coord_y, 1, i_coord_y, i_coord_num, i_index); - } - - private final int[] __detectMarker_mkvertex = new int[5]; - - /** - * arDetectMarker2を基にした関数 - * この関数はNyARSquare要素のうち、directionを除くパラメータを取得して返します。 - * directionの確定は行いません。 - * @param i_raster - * 解析する2値ラスタイメージを指定します。 - * @param o_square_stack - * 抽出した正方形候補を格納するリスト - * @throws NyARException - */ - public final void detectMarker(NyARBinRaster i_raster, NyARSquareStack o_square_stack) throws NyARException - { - final INyARLabeling labeling_proc = this._labeling; - final NyARLabelingImage limage = this._limage; - - // 初期化 - - // マーカーホルダをリセット - o_square_stack.clear(); - - // ラベリング - labeling_proc.labeling(i_raster); - - // ラベル数が0ならここまで - final int label_num = limage.getLabelStack().getLength(); - if (label_num < 1) { - return; - } - - final NyARLabelingLabelStack stack = limage.getLabelStack(); - final NyARLabelingLabel[] labels = (NyARLabelingLabel[])stack.getArray(); - - - // ラベルを大きい順に整列 - stack.sortByArea(); - - // デカいラベルを読み飛ばし - int i; - for (i = 0; i < label_num; i++) { - // 検査対象内のラベルサイズになるまで無視 - if (labels[i].area <= AR_AREA_MAX) { - break; - } - } - - final int xsize = this._width; - final int ysize = this._height; - final int[] xcoord = this._xcoord; - final int[] ycoord = this._ycoord; - final int coord_max = this._max_coord; - final int[] mkvertex = this.__detectMarker_mkvertex; - final OverlapChecker overlap = this._overlap_checker; - int coord_num; - int label_area; - NyARLabelingLabel label_pt; - - //重なりチェッカの最大数を設定 - overlap.reset(label_num); - - for (; i < label_num; i++) { - label_pt = labels[i]; - 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; - } - - // 輪郭を取得 - coord_num = limage.getContour(i, coord_max, xcoord, ycoord); - if (coord_num == coord_max) { - // 輪郭が大きすぎる。 - continue; - } - //頂点候補のインデクスを取得 - final int vertex1 = scanVertex(xcoord, ycoord, coord_num); - - // 頂点候補(vertex1)を先頭に並べなおした配列を作成する。 - normalizeCoord(xcoord, ycoord, vertex1, coord_num); - - // 領域を準備する。 - NyARSquare square_ptr = (NyARSquare)o_square_stack.prePush(); - - // 頂点情報を取得 - if (!getSquareVertex(xcoord, ycoord, vertex1, coord_num, label_area, mkvertex)) { - o_square_stack.pop();// 頂点の取得が出来なかったので破棄 - continue; - } - // マーカーを検出 - if (!getSquareLine(mkvertex, xcoord, ycoord, square_ptr)) { - // 矩形が成立しなかった。 - o_square_stack.pop(); - continue; - } - // 検出済の矩形の属したラベルを重なりチェックに追加する。 - overlap.push(label_pt); - } - return; - } - - /** - * 辺からの対角線が最長になる点を対角線候補として返す。 - * - * @param i_xcoord - * @param i_ycoord - * @param i_coord_num - * @return - */ - private int scanVertex(int[] i_xcoord, int[] i_ycoord, int i_coord_num) - { - final int sx = i_xcoord[0]; - final int sy = i_ycoord[0]; - int d = 0; - int w, x, y; - int ret = 0; - for (int i = 1; i < i_coord_num; i++) { - x = i_xcoord[i] - sx; - y = i_ycoord[i] - sy; - w = x * x + y * y; - if (w > d) { - d = w; - ret = i; - } - // ここでうまく終了条件入れられないかな。 - } - return ret; - } - - private final NyARFixedFloatVertexCounter __getSquareVertex_wv1 = new NyARFixedFloatVertexCounter(); - - private final NyARFixedFloatVertexCounter __getSquareVertex_wv2 = new NyARFixedFloatVertexCounter(); - - /** - * static int arDetectMarker2_check_square( int area, ARMarkerInfo2 *marker_info2, double factor ) 関数の代替関数 OPTIMIZED STEP [450->415] o_squareに頂点情報をセットします。 - * - * @param i_x_coord - * @param i_y_coord - * @param i_vertex1_index - * @param i_coord_num - * @param i_area - * @param o_vertex - * 要素数はint[4]である事 - * @return - */ - private boolean getSquareVertex(int[] i_x_coord, int[] i_y_coord, int i_vertex1_index, int i_coord_num, int i_area, int[] o_vertex) - { - final NyARFixedFloatVertexCounter wv1 = this.__getSquareVertex_wv1; - final NyARFixedFloatVertexCounter wv2 = this.__getSquareVertex_wv2; - final int end_of_coord = i_vertex1_index + i_coord_num - 1; - final int sx = i_x_coord[i_vertex1_index];// sx = marker_info2->x_coord[0]; - final int sy = i_y_coord[i_vertex1_index];// sy = marker_info2->y_coord[0]; - int dmax = 0; - int v1 = i_vertex1_index; - for (int i = 1 + i_vertex1_index; i < end_of_coord; i++) {// for(i=1;icoord_num-1;i++) - // { - final int d = (i_x_coord[i] - sx) * (i_x_coord[i] - sx) + (i_y_coord[i] - sy) * (i_y_coord[i] - sy); - if (d > dmax) { - dmax = d; - v1 = i; - } - } - final double thresh = (i_area / 0.75) * 0.01 * VERTEX_FACTOR; - - o_vertex[0] = i_vertex1_index; - - if (!wv1.getVertex(i_x_coord, i_y_coord, i_vertex1_index, v1, thresh)) { // if(get_vertex(marker_info2->x_coord,marker_info2->y_coord,0,v1,thresh,wv1,&wvnum1)< - // 0 ) { - return false; - } - if (!wv2.getVertex(i_x_coord, i_y_coord, v1, end_of_coord, thresh)) {// if(get_vertex(marker_info2->x_coord,marker_info2->y_coord,v1,marker_info2->coord_num-1,thresh,wv2,&wvnum2) - // < 0) { - return false; - } - - int v2; - if (wv1.number_of_vertex == 1 && wv2.number_of_vertex == 1) {// if(wvnum1 == 1 && wvnum2== 1) { - o_vertex[1] = wv1.vertex[0]; - o_vertex[2] = v1; - o_vertex[3] = wv2.vertex[0]; - } else if (wv1.number_of_vertex > 1 && wv2.number_of_vertex == 0) {// }else if( wvnum1 > 1 && wvnum2== 0) { - //頂点位置を、起点から対角点の間の1/2にあると予想して、検索する。 - v2 = (v1-i_vertex1_index)/2+i_vertex1_index; - if (!wv1.getVertex(i_x_coord, i_y_coord, i_vertex1_index, v2, thresh)) { - return false; - } - if (!wv2.getVertex(i_x_coord, i_y_coord, v2, v1, thresh)) { - return false; - } - if (wv1.number_of_vertex == 1 && wv2.number_of_vertex == 1) { - o_vertex[1] = wv1.vertex[0]; - o_vertex[2] = wv2.vertex[0]; - o_vertex[3] = v1; - } else { - return false; - } - } else if (wv1.number_of_vertex == 0 && wv2.number_of_vertex > 1) { - //v2 = (v1-i_vertex1_index+ end_of_coord-i_vertex1_index) / 2+i_vertex1_index; - v2 = (v1+ end_of_coord)/2; - - if (!wv1.getVertex(i_x_coord, i_y_coord, v1, v2, thresh)) { - return false; - } - if (!wv2.getVertex(i_x_coord, i_y_coord, v2, end_of_coord, thresh)) { - return false; - } - if (wv1.number_of_vertex == 1 && wv2.number_of_vertex == 1) { - o_vertex[1] = v1; - o_vertex[2] = wv1.vertex[0]; - o_vertex[3] = wv2.vertex[0]; - } else { - return false; - } - } else { - return false; - } - o_vertex[4] = end_of_coord; - return true; - } - - private final INyARPca2d _pca; - private final NyARDoubleMatrix22 __getSquareLine_evec=new NyARDoubleMatrix22(); - private final NyARDoublePoint2d __getSquareLine_mean=new NyARDoublePoint2d(); - private final NyARDoublePoint2d __getSquareLine_ev=new NyARDoublePoint2d(); - /** - * arGetLine(int x_coord[], int y_coord[], int coord_num,int vertex[], double line[4][3], double v[4][2]) arGetLine2(int x_coord[], int y_coord[], int - * coord_num,int vertex[], double line[4][3], double v[4][2], double *dist_factor) の2関数の合成品です。 マーカーのvertex,lineを計算して、結果をo_squareに保管します。 - * Optimize:STEP[424->391] - * - * @param i_cparam - * @return - * @throws NyARException - */ - private boolean getSquareLine(int[] i_mkvertex, int[] i_xcoord, int[] i_ycoord, NyARSquare o_square) throws NyARException - { - final NyARLinear[] l_line = o_square.line; - final NyARCameraDistortionFactor dist_factor=this._dist_factor; - final NyARDoubleMatrix22 evec=this.__getSquareLine_evec; - final NyARDoublePoint2d mean=this.__getSquareLine_mean; - final NyARDoublePoint2d ev=this.__getSquareLine_ev; - - - for (int i = 0; i < 4; i++) { - final double w1 = (double) (i_mkvertex[i + 1] - i_mkvertex[i] + 1) * 0.05 + 0.5; - final int st = (int) (i_mkvertex[i] + w1); - final int ed = (int) (i_mkvertex[i + 1] - w1); - final int n = ed - st + 1; - if (n < 2) { - // nが2以下でmatrix.PCAを計算することはできないので、エラー - return false; - } - //主成分分析する。 - this._pca.pcaWithDistortionFactor(i_xcoord, i_ycoord, st, n,dist_factor, evec, ev,mean); - final NyARLinear l_line_i = l_line[i]; - l_line_i.run = evec.m01;// line[i][0] = evec->m[1]; - l_line_i.rise = -evec.m00;// line[i][1] = -evec->m[0]; - l_line_i.intercept = -(l_line_i.run * mean.x + l_line_i.rise * mean.y)*2;// line[i][2] = -(line[i][0]*mean->v[0] + line[i][1]*mean->v[1]); - } - - final NyARDoublePoint2d[] l_sqvertex = o_square.sqvertex; - final NyARIntPoint[] l_imvertex = o_square.imvertex; - for (int i = 0; i < 4; i++) { - final NyARLinear l_line_i = l_line[i]; - final NyARLinear l_line_2 = l_line[(i + 3) % 4]; - final double w1 = l_line_2.run * l_line_i.rise - l_line_i.run * l_line_2.rise; - if (w1 == 0.0) { - return false; - } - l_sqvertex[i].x = (l_line_2.rise * l_line_i.intercept - l_line_i.rise * l_line_2.intercept) / w1; - l_sqvertex[i].y = (l_line_i.run * l_line_2.intercept - l_line_2.run * l_line_i.intercept) / w1; - // 頂点インデクスから頂点座標を得て保存 - l_imvertex[i].x = i_xcoord[i_mkvertex[i]]*2; - l_imvertex[i].y = i_ycoord[i_mkvertex[i]]*2; - } - return true; - } + private static int PCA_LENGTH = 20; + private static double VERTEX_FACTOR = 1.0;// 線検出のファクタ + + private static int AR_AREA_MAX = 25000;// #define AR_AREA_MAX 100000 + + private static int AR_AREA_MIN = 20;// #define AR_AREA_MIN 70 + private int _width; + private int _height; + + private INyARLabeling _labeling; + + private NyARLabelingImage _limage; + + private OverlapChecker _overlap_checker = new OverlapChecker(); + private NyARFixedFloatObserv2IdealMap _dist_factor; + /** + * 最大i_squre_max個のマーカーを検出するクラスを作成する。 + * + * @param i_param + */ + public NyARSquareDetector_Quad(NyARCameraDistortionFactor i_dist_factor_ref, NyARIntSize i_size) throws NyARException + { + this._width = i_size.w / 2; + this._height = i_size.h / 2; + this._labeling = new NyARLabeling_ARToolKit_X2(); + this._limage = new NyARLabelingImage(this._width, this._height); + this._labeling.attachDestination(this._limage); + + // 輪郭の最大長は画面に映りうる最大の長方形サイズ。 + int number_of_coord = (this._width + this._height) * 2; + + // 輪郭バッファは頂点変換をするので、輪郭バッファの2倍取る。 + this._max_coord = number_of_coord; + this._xcoord = new int[number_of_coord * 2]; + this._ycoord = new int[number_of_coord * 2]; + + //1/4サイズの歪みマップを作る + NyARCameraDistortionFactor quadfactor = new NyARCameraDistortionFactor(); + quadfactor.copyFrom(i_dist_factor_ref); + quadfactor.changeScale(0.5); + this._dist_factor = new NyARFixedFloatObserv2IdealMap(quadfactor, i_size); + //PCA + this._pca = new NyARFixedFloatPca2d(); + this._xpos = new int[PCA_LENGTH];//最大辺長はthis._width+this._height + this._ypos = new int[PCA_LENGTH];//最大辺長はthis._width+this._height + + } + + private int _max_coord; + private int[] _xcoord; + private int[] _ycoord; + + private void normalizeCoord(int[] i_coord_x, int[] i_coord_y, int i_index, int i_coord_num) + { + // vertex1を境界にして、後方に配列を連結 + System.arraycopy(i_coord_x, 1, i_coord_x, i_coord_num, i_index); + System.arraycopy(i_coord_y, 1, i_coord_y, i_coord_num, i_index); + } + + private int[] __detectMarker_mkvertex = new int[5]; + + /** + * arDetectMarker2を基にした関数 + * この関数はNyARSquare要素のうち、directionを除くパラメータを取得して返します。 + * directionの確定は行いません。 + * @param i_raster + * 解析する2値ラスタイメージを指定します。 + * @param o_square_stack + * 抽出した正方形候補を格納するリスト + * @throws NyARException + */ + public void detectMarker(NyARBinRaster i_raster, NyARSquareStack o_square_stack) throws NyARException + { + INyARLabeling labeling_proc = this._labeling; + NyARLabelingImage limage = this._limage; + + // 初期化 + + // マーカーホルダをリセット + o_square_stack.clear(); + + // ラベリング + labeling_proc.labeling(i_raster); + + // ラベル数が0ならここまで + int label_num = limage.getLabelStack().getLength(); + if (label_num < 1) + { + return; + } + + NyARLabelingLabelStack stack = limage.getLabelStack(); + NyARLabelingLabel[] labels = (NyARLabelingLabel[])stack.getArray(); + + + // ラベルを大きい順に整列 + stack.sortByArea(); + + // デカいラベルを読み飛ばし + 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; + int[] xcoord = this._xcoord; + int[] ycoord = this._ycoord; + int coord_max = this._max_coord; + int[] mkvertex = this.__detectMarker_mkvertex; + OverlapChecker overlap = this._overlap_checker; + int coord_num; + int label_area; + NyARLabelingLabel label_pt; + + //重なりチェッカの最大数を設定 + overlap.reset(label_num); + + for (; i < label_num; i++) + { + label_pt = labels[i]; + 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; + } + + // 輪郭を取得 + coord_num = limage.getContour(i, coord_max, xcoord, ycoord); + if (coord_num == coord_max) + { + // 輪郭が大きすぎる。 + continue; + } + //頂点候補のインデクスを取得 + int vertex1 = scanVertex(xcoord, ycoord, coord_num); + + // 頂点候補(vertex1)を先頭に並べなおした配列を作成する。 + normalizeCoord(xcoord, ycoord, vertex1, coord_num); + + // 領域を準備する。 + NyARSquare square_ptr = (NyARSquare)o_square_stack.prePush(); + + // 頂点情報を取得 + if (!getSquareVertex(xcoord, ycoord, vertex1, coord_num, label_area, mkvertex)) + { + o_square_stack.pop();// 頂点の取得が出来なかったので破棄 + continue; + } + // マーカーを検出 + if (!getSquareLine(mkvertex, xcoord, ycoord, square_ptr)) + { + // 矩形が成立しなかった。 + o_square_stack.pop(); + continue; + } + // 検出済の矩形の属したラベルを重なりチェックに追加する。 + overlap.push(label_pt); + } + return; + } + + /** + * 辺からの対角線が最長になる点を対角線候補として返す。 + * + * @param i_xcoord + * @param i_ycoord + * @param i_coord_num + * @return + */ + private int scanVertex(int[] i_xcoord, int[] i_ycoord, int i_coord_num) + { + int sx = i_xcoord[0]; + int sy = i_ycoord[0]; + int d = 0; + int w, x, y; + int ret = 0; + for (int i = 1; i < i_coord_num; i++) + { + x = i_xcoord[i] - sx; + y = i_ycoord[i] - sy; + w = x * x + y * y; + if (w > d) + { + d = w; + ret = i; + } + // ここでうまく終了条件入れられないかな。 + } + return ret; + } + + private NyARVertexCounter __getSquareVertex_wv1 = new NyARVertexCounter(); + + private NyARVertexCounter __getSquareVertex_wv2 = new NyARVertexCounter(); + + /** + * static int arDetectMarker2_check_square( int area, ARMarkerInfo2 *marker_info2, double factor ) 関数の代替関数 OPTIMIZED STEP [450->415] o_squareに頂点情報をセットします。 + * + * @param i_x_coord + * @param i_y_coord + * @param i_vertex1_index + * @param i_coord_num + * @param i_area + * @param o_vertex + * 要素数はint[4]である事 + * @return + */ + private boolean getSquareVertex(int[] i_x_coord, int[] i_y_coord, int i_vertex1_index, int i_coord_num, int i_area, int[] o_vertex) + { + NyARVertexCounter wv1 = this.__getSquareVertex_wv1; + NyARVertexCounter wv2 = this.__getSquareVertex_wv2; + int end_of_coord = i_vertex1_index + i_coord_num - 1; + int sx = i_x_coord[i_vertex1_index];// sx = marker_info2->x_coord[0]; + int sy = i_y_coord[i_vertex1_index];// sy = marker_info2->y_coord[0]; + int dmax = 0; + int v1 = i_vertex1_index; + for (int i = 1 + i_vertex1_index; i < end_of_coord; i++) + {// for(i=1;icoord_num-1;i++) + // { + int d = (i_x_coord[i] - sx) * (i_x_coord[i] - sx) + (i_y_coord[i] - sy) * (i_y_coord[i] - sy); + if (d > dmax) + { + dmax = d; + v1 = i; + } + } + double thresh = (i_area / 0.75) * 0.01 * VERTEX_FACTOR; + + o_vertex[0] = i_vertex1_index; + + if (!wv1.getVertex(i_x_coord, i_y_coord, i_vertex1_index, v1, thresh)) + { // if(get_vertex(marker_info2->x_coord,marker_info2->y_coord,0,v1,thresh,wv1,&wvnum1)< + // 0 ) { + return false; + } + if (!wv2.getVertex(i_x_coord, i_y_coord, v1, end_of_coord, thresh)) + {// if(get_vertex(marker_info2->x_coord,marker_info2->y_coord,v1,marker_info2->coord_num-1,thresh,wv2,&wvnum2) + // < 0) { + return false; + } + + int v2; + if (wv1.number_of_vertex == 1 && wv2.number_of_vertex == 1) + {// if(wvnum1 == 1 && wvnum2== 1) { + o_vertex[1] = wv1.vertex[0]; + o_vertex[2] = v1; + o_vertex[3] = wv2.vertex[0]; + } + else if (wv1.number_of_vertex > 1 && wv2.number_of_vertex == 0) + {// }else if( wvnum1 > 1 && wvnum2== 0) { + //頂点位置を、起点から対角点の間の1/2にあると予想して、検索する。 + v2 = (v1 - i_vertex1_index) / 2 + i_vertex1_index; + if (!wv1.getVertex(i_x_coord, i_y_coord, i_vertex1_index, v2, thresh)) + { + return false; + } + if (!wv2.getVertex(i_x_coord, i_y_coord, v2, v1, thresh)) + { + return false; + } + if (wv1.number_of_vertex == 1 && wv2.number_of_vertex == 1) + { + o_vertex[1] = wv1.vertex[0]; + o_vertex[2] = wv2.vertex[0]; + o_vertex[3] = v1; + } + else + { + return false; + } + } + else if (wv1.number_of_vertex == 0 && wv2.number_of_vertex > 1) + { + //v2 = (v1-i_vertex1_index+ end_of_coord-i_vertex1_index) / 2+i_vertex1_index; + v2 = (v1 + end_of_coord) / 2; + + if (!wv1.getVertex(i_x_coord, i_y_coord, v1, v2, thresh)) + { + return false; + } + if (!wv2.getVertex(i_x_coord, i_y_coord, v2, end_of_coord, thresh)) + { + return false; + } + if (wv1.number_of_vertex == 1 && wv2.number_of_vertex == 1) + { + o_vertex[1] = v1; + o_vertex[2] = wv1.vertex[0]; + o_vertex[3] = wv2.vertex[0]; + } + else + { + return false; + } + } + else + { + return false; + } + o_vertex[4] = end_of_coord; + return true; + } + private int[] _xpos; + private int[] _ypos; + private NyARFixedFloatPca2d _pca; + private NyARI64Matrix22 __getSquareLine_evec = new NyARI64Matrix22(); + private NyARI64Point2d __getSquareLine_mean = new NyARI64Point2d(); + private NyARI64Point2d __getSquareLine_ev = new NyARI64Point2d(); + private NyARI64Linear[] __getSquareLine_i64liner = NyARI64Linear.createArray(4); + /** + * arGetLine(int x_coord[], int y_coord[], int coord_num,int vertex[], double line[4][3], double v[4][2]) arGetLine2(int x_coord[], int y_coord[], int + * coord_num,int vertex[], double line[4][3], double v[4][2], double *dist_factor) の2関数の合成品です。 マーカーのvertex,lineを計算して、結果をo_squareに保管します。 + * Optimize:STEP[424->391] + * + * @param i_cparam + * @return + * @throws NyARException + */ + private boolean getSquareLine(int[] i_mkvertex, int[] i_xcoord, int[] i_ycoord, NyARSquare o_square) throws NyARException + { + NyARLinear[] l_line = o_square.line; + NyARI64Matrix22 evec = this.__getSquareLine_evec; + NyARI64Point2d mean = this.__getSquareLine_mean; + NyARI64Point2d ev = this.__getSquareLine_ev; + NyARI64Linear[] i64liner = this.__getSquareLine_i64liner; + + + for (int i = 0; i < 4; i++) + { + double w1 = (double)(i_mkvertex[i + 1] - i_mkvertex[i] + 1) * 0.05 + 0.5; + int st = (int)(i_mkvertex[i] + w1); + int ed = (int)(i_mkvertex[i + 1] - w1); + int n = ed - st + 1; + if (n < 2) + { + // nが2以下でmatrix.PCAを計算することはできないので、エラー + return false; + } + //配列作成 + n = this._dist_factor.observ2IdealSampling(i_xcoord, i_ycoord, st, n, this._xpos, this._ypos, PCA_LENGTH); + + //主成分分析する。 + this._pca.pcaF16(this._xpos, this._ypos, n, evec, ev, mean); + NyARI64Linear l_line_i = i64liner[i]; + l_line_i.run = evec.m01;// line[i][0] = evec->m[1]; + l_line_i.rise = -evec.m00;// line[i][1] = -evec->m[0]; + l_line_i.intercept = -((l_line_i.run * mean.x + l_line_i.rise * mean.y) >> 16);// line[i][2] = -(line[i][0]*mean->v[0] + line[i][1]*mean->v[1]); + } + + NyARDoublePoint2d[] l_sqvertex = o_square.sqvertex; + NyARIntPoint[] l_imvertex = o_square.imvertex; + for (int i = 0; i < 4; i++) + { + NyARI64Linear l_line_i = i64liner[i]; + NyARI64Linear l_line_2 = i64liner[(i + 3) % 4]; + long w1 = (l_line_2.run * l_line_i.rise - l_line_i.run * l_line_2.rise) >> 16; + if (w1 == 0) + { + return false; + } + l_sqvertex[i].x = (double)((l_line_2.rise * l_line_i.intercept - l_line_i.rise * l_line_2.intercept) / w1) *2/ 65536.0; + l_sqvertex[i].y = (double)((l_line_i.run * l_line_2.intercept - l_line_2.run * l_line_i.intercept) / w1) *2/ 65536.0; + // 頂点インデクスから頂点座標を得て保存 + l_imvertex[i].x = i_xcoord[i_mkvertex[i]]*2; + l_imvertex[i].y = i_ycoord[i_mkvertex[i]]*2; + l_line[i].run = (double)l_line_i.run / 65536.0; + l_line[i].rise = (double)l_line_i.rise / 65536.0; + l_line[i].intercept = (double)l_line_i.intercept*2 / 65536.0; + } + return true; + } } - /** * ラベル同士の重なり(内包関係)を調べるクラスです。 * ラベルリストに内包するラベルを蓄積し、それにターゲットのラベルが内包されているか を確認します。 */ class OverlapChecker { - private NyARLabelingLabel[] _labels = new NyARLabelingLabel[32]; - - private int _length; - - /** - * 最大i_max_label個のラベルを蓄積できるようにオブジェクトをリセットする - * - * @param i_max_label - */ - public void reset(int i_max_label) - { - if (i_max_label > this._labels.length) { - this._labels = new NyARLabelingLabel[i_max_label]; - } - this._length = 0; - } - - /** - * チェック対象のラベルを追加する。 - * - * @param i_label_ref - */ - public void push(NyARLabelingLabel i_label_ref) - { - this._labels[this._length] = i_label_ref; - this._length++; - } - - /** - * 現在リストにあるラベルと重なっているかを返す。 - * - * @param i_label - * @return 何れかのラベルの内側にあるならばfalse,独立したラベルである可能性が高ければtrueです. - */ - public boolean check(NyARLabelingLabel i_label) - { - // 重なり処理かな? - final NyARLabelingLabel[] label_pt = this._labels; - final int px1 = (int) i_label.pos_x; - final int py1 = (int) i_label.pos_y; - for (int i = this._length - 1; i >= 0; i--) { - final int px2 = (int) label_pt[i].pos_x; - final int py2 = (int) label_pt[i].pos_y; - final int d = (px1 - px2) * (px1 - px2) + (py1 - py2) * (py1 - py2); - if (d < label_pt[i].area / 4) { - // 対象外 - return false; - } - } - // 対象 - return true; - } -} \ No newline at end of file + private NyARLabelingLabel[] _labels = new NyARLabelingLabel[32]; + + private int _length; + + /** + * 最大i_max_label個のラベルを蓄積できるようにオブジェクトをリセットする + * + * @param i_max_label + */ + public void reset(int i_max_label) + { + if (i_max_label > this._labels.length) + { + this._labels = new NyARLabelingLabel[i_max_label]; + } + this._length = 0; + } + + /** + * チェック対象のラベルを追加する。 + * + * @param i_label_ref + */ + public void push(NyARLabelingLabel i_label_ref) + { + this._labels[this._length] = i_label_ref; + this._length++; + } + + /** + * 現在リストにあるラベルと重なっているかを返す。 + * + * @param i_label + * @return 何れかのラベルの内側にあるならばfalse,独立したラベルである可能性が高ければtrueです. + */ + public boolean check(NyARLabelingLabel i_label) + { + // 重なり処理かな? + NyARLabelingLabel[] label_pt = this._labels; + int px1 = (int)i_label.pos_x; + int py1 = (int)i_label.pos_y; + for (int i = this._length - 1; i >= 0; i--) + { + int px2 = (int)label_pt[i].pos_x; + int py2 = (int)label_pt[i].pos_y; + int d = (px1 - px2) * (px1 - px2) + (py1 - py2) * (py1 - py2); + if (d < label_pt[i].area / 4) + { + // 対象外 + return false; + } + } + // 対象 + return true; + } +} + + diff --git a/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/x2/NyARFixedFloatIdeal2Observ.java b/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/x2/NyARFixedFloatIdeal2Observ.java new file mode 100644 index 0000000..dce3668 --- /dev/null +++ b/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/x2/NyARFixedFloatIdeal2Observ.java @@ -0,0 +1,52 @@ +package jp.nyatla.nyartoolkit.sandbox.x2; + +import jp.nyatla.nyartoolkit.core.param.*; +import jp.nyatla.nyartoolkit.core.types.NyARDoublePoint2d; +import jp.nyatla.nyartoolkit.core2.types.NyARFixedFloat16Point2d; + +public class NyARFixedFloatIdeal2Observ +{ + private double[] _factor=new double[4]; + public NyARFixedFloatIdeal2Observ(NyARCameraDistortionFactor i_distfactor) + { + i_distfactor.getValue(this._factor); + return; + } + public void ideal2ObservBatch(final NyARDoublePoint2d[] i_in, NyARFixedFloat16Point2d[] o_out, int i_size) + { + double x, y; + final double d0 = this._factor[0]; + final double d1 = this._factor[1]; + final double d3 = this._factor[3]; + final double d2_w = this._factor[2] / 100000000.0; + for (int i = 0; i < i_size; i++) { + x = (i_in[i].x - d0) * d3; + y = (i_in[i].y - d1) * d3; + if (x == 0.0 && y == 0.0) { + o_out[i].x = (long)(d0*NyMath.FIXEDFLOAT16_1); + o_out[i].y = (long)(d1*NyMath.FIXEDFLOAT16_1); + } else { + final double d = 1.0 - d2_w * (x * x + y * y); + o_out[i].x = (long)((x * d + d0)*NyMath.FIXEDFLOAT16_1); + o_out[i].y = (long)((y * d + d1)*NyMath.FIXEDFLOAT16_1); + } + } + return; + } + public void ideal2Observ(final NyARFixedFloat16Point2d i_in, NyARFixedFloat16Point2d o_out) + { + final double f0=this._factor[0]; + final double f1=this._factor[1]; + final double x = (((double)i_in.x/NyMath.FIXEDFLOAT16_1) - f0) * this._factor[3]; + final double y = (((double)i_in.y/NyMath.FIXEDFLOAT16_1) - f1) * this._factor[3]; + if (x == 0.0 && y == 0.0) { + o_out.x = (long)(f0*NyMath.FIXEDFLOAT16_1); + o_out.y = (long)(f1*NyMath.FIXEDFLOAT16_1); + } else { + final double d = 1.0 - this._factor[2] / 100000000.0 * (x * x + y * y); + o_out.x = (long)((x * d + f0)*NyMath.FIXEDFLOAT16_1); + o_out.y = (long)((y * d + f1)*NyMath.FIXEDFLOAT16_1); + } + return; + } +} diff --git a/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/x2/NyARFixedFloatVertexCounter.java b/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/x2/NyARFixedFloatVertexCounter.java new file mode 100644 index 0000000..afa8b93 --- /dev/null +++ b/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/x2/NyARFixedFloatVertexCounter.java @@ -0,0 +1,66 @@ +package jp.nyatla.nyartoolkit.sandbox.x2; + +public final class NyARFixedFloatVertexCounter +{ + public final int[] vertex = new int[6];// 5まで削れる + + public int number_of_vertex; + + private long thresh_16f; + + private int[] x_coord; + + private int[] y_coord; + + public boolean getVertex(int[] i_x_coord, int[] i_y_coord, int st, int ed, long i_thresh) + { + this.number_of_vertex = 0; + this.thresh_16f = i_thresh; + this.x_coord = i_x_coord; + this.y_coord = i_y_coord; + return get_vertex(st, ed); + } + + /** + * static int get_vertex( int x_coord[], int y_coord[], int st, int ed,double thresh, int vertex[], int *vnum) 関数の代替関数 + * + * @param x_coord + * @param y_coord + * @param st + * @param ed + * @param thresh + * @return + */ + private boolean get_vertex(int st, int ed) + { + int v1 = 0; + final int[] lx_coord = this.x_coord; + final int[] ly_coord = this.y_coord; + final int a = ly_coord[ed] - ly_coord[st]; + final int b = lx_coord[st] - lx_coord[ed]; + final int c = lx_coord[ed] * ly_coord[st] - ly_coord[ed] * lx_coord[st]; + long dmax = 0; + for (int i = st + 1; i < ed; i++) { + final long d = a * lx_coord[i] + b * ly_coord[i] + c; + if (d * d > dmax) { + dmax = d * d; + v1 = i; + } + } + if ((dmax<<16) / (long)(a * a + b * b) > this.thresh_16f) { + if (!get_vertex(st, v1)) { + return false; + } + if (number_of_vertex > 5) { + return false; + } + vertex[number_of_vertex] = v1;// vertex[(*vnum)] = v1; + number_of_vertex++;// (*vnum)++; + + if (!get_vertex(v1, ed)) { + return false; + } + } + return true; + } +} diff --git a/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/x2/NyARSquareDetector_X2.java b/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/x2/NyARSquareDetector_X2.java index 53cb4a3..f53c3e0 100644 --- a/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/x2/NyARSquareDetector_X2.java +++ b/sample/sandbox/jp/nyatla/nyartoolkit/sandbox/x2/NyARSquareDetector_X2.java @@ -402,70 +402,6 @@ public class NyARSquareDetector_X2 implements INyARSquareDetector return true; } } -final class NyARFixedFloatVertexCounter -{ - public final int[] vertex = new int[6];// 5まで削れる - - public int number_of_vertex; - - private long thresh_16f; - - private int[] x_coord; - - private int[] y_coord; - - public boolean getVertex(int[] i_x_coord, int[] i_y_coord, int st, int ed, long i_thresh) - { - this.number_of_vertex = 0; - this.thresh_16f = i_thresh; - this.x_coord = i_x_coord; - this.y_coord = i_y_coord; - return get_vertex(st, ed); - } - - /** - * static int get_vertex( int x_coord[], int y_coord[], int st, int ed,double thresh, int vertex[], int *vnum) 関数の代替関数 - * - * @param x_coord - * @param y_coord - * @param st - * @param ed - * @param thresh - * @return - */ - private boolean get_vertex(int st, int ed) - { - int v1 = 0; - final int[] lx_coord = this.x_coord; - final int[] ly_coord = this.y_coord; - final int a = ly_coord[ed] - ly_coord[st]; - final int b = lx_coord[st] - lx_coord[ed]; - final int c = lx_coord[ed] * ly_coord[st] - ly_coord[ed] * lx_coord[st]; - long dmax = 0; - for (int i = st + 1; i < ed; i++) { - final long d = a * lx_coord[i] + b * ly_coord[i] + c; - if (d * d > dmax) { - dmax = d * d; - v1 = i; - } - } - if ((dmax<<16) / (long)(a * a + b * b) > this.thresh_16f) { - if (!get_vertex(st, v1)) { - return false; - } - if (number_of_vertex > 5) { - return false; - } - vertex[number_of_vertex] = v1;// vertex[(*vnum)] = v1; - number_of_vertex++;// (*vnum)++; - - if (!get_vertex(v1, ed)) { - return false; - } - } - return true; - } -} /**