OSDN Git Service

初期インポート。
[nyartoolkit-and/nyartoolkit-android-0.9.git] / src / jp / nyatla / nyartoolkit / core / NyARDetectMarker.java
diff --git a/src/jp/nyatla/nyartoolkit/core/NyARDetectMarker.java b/src/jp/nyatla/nyartoolkit/core/NyARDetectMarker.java
new file mode 100644 (file)
index 0000000..6a00050
--- /dev/null
@@ -0,0 +1,302 @@
+/* \r
+ * PROJECT: NyARToolkit\r
+ * --------------------------------------------------------------------------------\r
+ * This work is based on the original ARToolKit developed by\r
+ *   Hirokazu Kato\r
+ *   Mark Billinghurst\r
+ *   HITLab, University of Washington, Seattle\r
+ * http://www.hitl.washington.edu/artoolkit/\r
+ *\r
+ * The NyARToolkit is Java version ARToolkit class library.\r
+ * Copyright (C)2008 R.Iizuka\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ * \r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this framework; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ * \r
+ * For further information please contact.\r
+ *     http://nyatla.jp/nyatoolkit/\r
+ *     <airmail(at)ebony.plala.or.jp>\r
+ * \r
+ */\r
+package jp.nyatla.nyartoolkit.core;\r
+\r
+\r
+\r
+\r
+import jp.nyatla.nyartoolkit.NyARException;\r
+\r
+\r
+\r
+\r
+/**\r
+ * イメージからマーカー情報を検出するクラス。\r
+ * このクラスは、arDetectMarker2.cとの置き換えになります。\r
+ * ラベリング済みのラスタデータからマーカー位置を検出して、結果を保持します。\r
+ *\r
+ */\r
+public class NyARDetectMarker {\r
+    private static final int AR_AREA_MAX=100000;//#define   AR_AREA_MAX      100000\r
+    private static final int AR_AREA_MIN=70;//#define   AR_AREA_MIN          70\r
+\r
+//    private final NyARMarker[] marker_holder;            //マーカーデータの保持配列\r
+//    private final NyARMarker[] marker_info2_array;//マーカーデータのインデックス配列\r
+//    private int marker_num;\r
+    private int width,height;\r
+    /**\r
+     * 最大i_squre_max個のマーカーを検出するクラスを作成する。\r
+     * @param i_width\r
+     * @param i_height\r
+     */\r
+    public NyARDetectMarker(int i_width,int i_height)\r
+    {\r
+       this.width =i_width;\r
+       this.height=i_height;\r
+       \r
+//     this.marker_holder=new NyARMarker[i_squre_max];\r
+//     this.marker_info2_array=new NyARMarker[i_squre_max];\r
+//     //先にマーカーホルダにオブジェクトを作っておく\r
+//     for(int i=0;i<i_squre_max;i++){\r
+//         this.marker_holder[i]=new NyARMarker();\r
+//     }\r
+    }\r
+    private static final int AR_CHAIN_MAX=10000;\r
+    private final int[] wk_arGetContour_xdir={0,  1, 1, 1, 0,-1,-1,-1};\r
+    private final int[] wk_arGetContour_ydir={-1,-1, 0, 1, 1, 1, 0,-1};\r
+    private final int[] wk_arGetContour_xcoord=new int[AR_CHAIN_MAX];\r
+    private final int[] wk_arGetContour_ycoord=new int[AR_CHAIN_MAX];\r
+    /**\r
+     * int arGetContour( ARInt16 *limage, int *label_ref,int label, int clip[4], ARMarkerInfo2 *marker_info2 )\r
+     * 関数の代替品\r
+     * detectMarker関数から使う関数です。o_markerにlabelとclipで示される1個のマーカーを格納します。\r
+     * marker_holder[i_holder_num]にオブジェクトが無ければまず新規に作成し、もし\r
+     * 既に存在すればそこにマーカー情報を上書きして記録します。\r
+     * Optimize:STEP[369->336]\r
+     * @param o_marker\r
+     * @param limage\r
+     * @param label_ref\r
+     * @param label\r
+     * @param clip\r
+     * @throws NyARException\r
+     */\r
+    private final void arGetContour(NyARMarker o_marker,int[][] limage, int[] label_ref,int i_labelnum, NyARLabel i_label) throws NyARException\r
+    {\r
+       final int[] xcoord=wk_arGetContour_xcoord;\r
+       final int[] ycoord=wk_arGetContour_ycoord;\r
+       final int[] xdir=wk_arGetContour_xdir; //static int      xdir[8] = { 0, 1, 1, 1, 0,-1,-1,-1};\r
+       final int[] ydir=wk_arGetContour_ydir;//static int      ydir[8] = {-1,-1, 0, 1, 1, 1, 0,-1};\r
+       //ShortPointer p1;//ARInt16         *p1;\r
+       int coord_num;\r
+       int             sx=0, sy=0, dir;\r
+       int             dmax, d, v1=0;\r
+       int             i, j,w;\r
+\r
+       int[] limage_j;\r
+       j = i_label.clip2;\r
+       limage_j=limage[j];\r
+       final int clip1=i_label.clip1;\r
+       //p1=ShortPointer.wrap(limage,j*xsize+clip.get());//p1 = &(limage[j*xsize+clip[0]]);\r
+       for( i = i_label.clip0; i <= clip1; i++){//for( i = clip[0]; i <= clip[1]; i++, p1++ ) {\r
+           w=limage_j[i];\r
+           if(w > 0 && label_ref[w-1] == i_labelnum ) {//if( *p1 > 0 && label_ref[(*p1)-1] == label ) {\r
+               sx = i;\r
+               sy = j;\r
+               break;\r
+           }\r
+       }\r
+       if(i>clip1){//if( i > clip[1] ) {\r
+           System.out.println("??? 1");//printf();\r
+           throw new NyARException();//return(-1);\r
+       }\r
+\r
+//     //マーカーホルダが既に確保済みかを調べる\r
+//     if(marker_holder[i_holder_num]==null){\r
+//         //確保していなければ確保\r
+//         marker_holder[i_holder_num]=new NyARMarker();\r
+//     }\r
+\r
+\r
+       coord_num=1;//marker_info2->coord_num = 1;\r
+       xcoord[0]=sx;//marker_info2->x_coord[0] = sx;\r
+       ycoord[0]=sy;//marker_info2->y_coord[0] = sy;\r
+       dir = 5;\r
+       \r
+       int r,c;\r
+        c=xcoord[0];\r
+        r=ycoord[0];\r
+        dmax=0;\r
+        //本家はdmaxの作成とxcoordの作成を別のループでやってるけど、非効率なので統合\r
+       for(;;){\r
+           //xcoord[1]-xcoord[n]までのデータを作る。\r
+           \r
+//         1個前のxcoordとycoordはループ後半で格納される。\r
+//         c=xcoord[coord_num-1];\r
+//         r=ycoord[coord_num-1];\r
+           //p1 = &(limage[marker_info2->y_coord[marker_info2->coord_num-1] * xsize+ marker_info2->x_coord[marker_info2->coord_num-1]]);\r
+           dir = (dir+5)%8;\r
+           for(i=0;i<8;i++) {\r
+               if(limage[r+ydir[dir]][c+xdir[dir]]>0){//if( p1[ydir[dir]*xsize+xdir[dir]] > 0 ){\r
+                   break;\r
+               }\r
+               dir = (dir+1)%8;        \r
+           }\r
+           if( i == 8 ){\r
+               System.out.println("??? 2");//printf("??? 2\n");\r
+               throw new NyARException();//return(-1);\r
+           }\r
+//         xcoordとycoordをc,rにも保存\r
+           c= c + xdir[dir];//marker_info2->x_coord[marker_info2->coord_num]= marker_info2->x_coord[marker_info2->coord_num-1] + xdir[dir];\r
+           r= r + ydir[dir];//marker_info2->y_coord[marker_info2->coord_num]= marker_info2->y_coord[marker_info2->coord_num-1] + ydir[dir];\r
+           xcoord[coord_num]=c;//marker_info2->x_coord[marker_info2->coord_num]= marker_info2->x_coord[marker_info2->coord_num-1] + xdir[dir];\r
+           ycoord[coord_num]=r;//marker_info2->y_coord[marker_info2->coord_num]= marker_info2->y_coord[marker_info2->coord_num-1] + ydir[dir];\r
+           if(c == sx && r == sy ){\r
+               break;\r
+           }\r
+           //dmaxの計算\r
+           d=(c-sx)*(c-sx)+(r-sy)*(r-sy);\r
+           if( d > dmax ) {\r
+               dmax = d;\r
+               v1 = coord_num;\r
+           }\r
+           //終了条件判定\r
+           coord_num++;\r
+           if(coord_num == AR_CHAIN_MAX-1){//if( marker_info2.coord_num == Config.AR_CHAIN_MAX-1 ){\r
+               System.out.println("??? 3");//printf("??? 3\n");\r
+               throw new NyARException();//return(-1);\r
+           }\r
+       }\r
+//\r
+//     dmax = 0;\r
+//     for(i=1;i<coord_num;i++) {//    for(i=1;i<marker_info2->coord_num;i++) {\r
+//         d = (xcoord[i]-sx)*(xcoord[i]-sx)+ (ycoord[i]-sy)*(ycoord[i]-sy);//   d = (marker_info2->x_coord[i]-sx)*(marker_info2->x_coord[i]-sx)+ (marker_info2->y_coord[i]-sy)*(marker_info2->y_coord[i]-sy);\r
+//         if( d > dmax ) {\r
+//             dmax = d;\r
+//             v1 = i;\r
+//         }\r
+//     }\r
+       //NyARMarkerへcoord情報をセット\r
+       //coordの並び替えと保存はNyARMarkerへ移動\r
+       o_marker.setCoordXY(v1,coord_num,xcoord,ycoord);\r
+       return;\r
+    }\r
+\r
+    /**\r
+     * ARMarkerInfo2 *arDetectMarker2( ARInt16 *limage, int label_num, int *label_ref,int *warea, double *wpos, int *wclip,int area_max, int area_min, double factor, int *marker_num )\r
+     * 関数の代替品\r
+     * ラベリング情報からマーカー一覧を作成してo_marker_listを更新します。\r
+     * 関数はo_marker_listに重なりを除外したマーカーリストを作成します。\r
+     * \r
+     * @param i_labeling\r
+     * ラベリング済みの情報を持つラベリングオブジェクト\r
+     * @param i_factor\r
+     * 何かの閾値?\r
+     * @param o_marker_list\r
+     * 抽出したマーカーを格納するリスト\r
+     * @throws NyARException\r
+     */\r
+    public final void detectMarker(NyARLabeling i_labeling,double i_factor,NyARMarkerList o_marker_list) throws NyARException\r
+    {\r
+       int label_area;\r
+       int i;\r
+       int xsize, ysize;\r
+       NyARLabel[] labels=i_labeling.getLabel();\r
+//     int[] warea     =i_labeling.getArea();\r
+       int label_num   =i_labeling.getLabelNum();\r
+//     int[][] wclip   =i_labeling.getClip();\r
+//     double[] wpos   =i_labeling.getPos();\r
+       int[][] limage=i_labeling.getLabelImg();\r
+       int[] label_ref =i_labeling.getLabelRef();\r
+\r
+       //マーカーホルダをリセット\r
+       o_marker_list.reset();\r
+//     marker_num=0;\r
+       xsize =width;\r
+       ysize =height;\r
+//     マーカーをmarker_holderに蓄積する。\r
+       NyARMarker current_marker=o_marker_list.getCurrentHolder();\r
+       NyARLabel label_pt;\r
+       for(i=0; i<label_num; i++ ){\r
+           label_pt=labels[i];\r
+           label_area=label_pt.area;\r
+           if(label_area < AR_AREA_MIN || label_area > AR_AREA_MAX ){\r
+               continue;\r
+           }\r
+           if( label_pt.clip0 == 1 || label_pt.clip1 == xsize-2 ){//if( wclip[i*4+0] == 1 || wclip[i*4+1] == xsize-2 ){\r
+               continue;\r
+           }\r
+           if( label_pt.clip2 == 1 || label_pt.clip3 == ysize-2 ){//if( wclip[i*4+2] == 1 || wclip[i*4+3] == ysize-2 ){\r
+               continue;\r
+           }\r
+           //ret = arGetContour( limage, label_ref, i+1,&(wclip[i*4]), &(marker_info2[marker_num2]));\r
+           arGetContour(current_marker,limage, label_ref, i+1,label_pt);\r
+\r
+           if(!current_marker.checkSquare(label_area,i_factor,label_pt.pos_x,label_pt.pos_y)){\r
+               //後半で整理するからここはいらない。//         marker_holder[marker_num2]=null;\r
+               continue;\r
+           }\r
+//         この3行はcheckSquareの最終段に含める。\r
+//         marker_holder[marker_num2].area   = warea[i];\r
+//         marker_holder[marker_num2].pos[0] = wpos[i*2+0];\r
+//         marker_holder[marker_num2].pos[1] = wpos[i*2+1];\r
+           //マーカー検出→次のホルダを取得\r
+           current_marker=o_marker_list.getNextHolder();\r
+           //マーカーリストが上限に達したか確認\r
+           if(current_marker==null){\r
+               break;\r
+           }\r
+       }\r
+       //マーカーリストを整理(重なり処理とかはマーカーリストに責務押し付け)\r
+       o_marker_list.updateMarkerArray();\r
+//     重なり処理かな?\r
+//     double[] pos_j,pos_i;\r
+//     for(i=0; i < marker_num2; i++ ){\r
+//         pos_i=marker_holder[i].pos;\r
+//         for(j=i+1; j < marker_num2; j++ ) {\r
+//             pos_j=marker_holder[j].pos;\r
+//             d = (pos_i[0] - pos_j[0])*(pos_i[0] - pos_j[0])+\r
+//             (pos_i[1] - pos_j[1])*(pos_i[1] - pos_j[1]);\r
+//             if(marker_holder[i].area >marker_holder[j].area ) {\r
+//                 if( d <marker_holder[i].area / 4 ) {\r
+//                     marker_holder[j].area = 0;\r
+//                 }\r
+//             }else{\r
+//                 if( d < marker_holder[j].area / 4 ) {\r
+//                     marker_holder[i].area = 0;\r
+//                 }\r
+//             }\r
+//         }\r
+//     }\r
+//     みつかったマーカーを整理する。\r
+//     エリアが0のマーカーを外した配列を作って、その数もついでに計算\r
+//     for(i=0;i<marker_num2;i++){\r
+//         if(marker_holder[i].area==0.0){\r
+//             continue;\r
+//         }\r
+//         marker_info2_array[marker_num]=marker_holder[i];\r
+//         marker_num++;\r
+//     }        \r
+//     for( i=0; i < marker_num2; i++ ) {\r
+//     if( marker_info2_array[i].area == 0.0 ) {\r
+//     for( j=i+1; j < marker_num2; j++ ){\r
+//     marker_info2_array[j-1] = marker_info2_array[j];\r
+//     }\r
+//     marker_num2--;\r
+//     }\r
+//     }\r
+//     発見したマーカー数をセット\r
+//     marker_num=marker_num2;//*marker_num = marker_num2;\r
+//     return( &(marker_info2[0]) );\r
+       return;\r
+    }\r
+\r
+}\r