OSDN Git Service

580fc5030025dd7a978718b12b5c01af28d7da9a
[nyartoolkit-and/nyartoolkit-and.git] / branches / nyatla / src / jp / nyatla / nyartoolkit / core / NyARDetectMarker.java
1 /* \r
2  * PROJECT: NyARToolkit\r
3  * --------------------------------------------------------------------------------\r
4  * This work is based on the original ARToolKit developed by\r
5  *   Hirokazu Kato\r
6  *   Mark Billinghurst\r
7  *   HITLab, University of Washington, Seattle\r
8  * http://www.hitl.washington.edu/artoolkit/\r
9  *\r
10  * The NyARToolkit is Java version ARToolkit class library.\r
11  * Copyright (C)2008 R.Iizuka\r
12  *\r
13  * This program is free software; you can redistribute it and/or\r
14  * modify it under the terms of the GNU General Public License\r
15  * as published by the Free Software Foundation; either version 2\r
16  * of the License, or (at your option) any later version.\r
17  * \r
18  * This program is distributed in the hope that it will be useful,\r
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
21  * GNU General Public License for more details.\r
22  * \r
23  * You should have received a copy of the GNU General Public License\r
24  * along with this framework; if not, write to the Free Software\r
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
26  * \r
27  * For further information please contact.\r
28  *      http://nyatla.jp/nyatoolkit/\r
29  *      <airmail(at)ebony.plala.or.jp>\r
30  * \r
31  */\r
32 package jp.nyatla.nyartoolkit.core;\r
33 \r
34 \r
35 \r
36 \r
37 import jp.nyatla.nyartoolkit.NyARException;\r
38 import jp.nyatla.nyartoolkit.core.labeling.*;\r
39 \r
40 \r
41 \r
42 /**\r
43  * イメージからマーカー情報を検出するクラス。\r
44  * このクラスは、arDetectMarker2.cとの置き換えになります。\r
45  * ラベリング済みのラスタデータからマーカー位置を検出して、結果を保持します。\r
46  *\r
47  */\r
48 public class NyARDetectMarker {\r
49     private static final int AR_AREA_MAX=100000;//#define   AR_AREA_MAX      100000\r
50     private static final int AR_AREA_MIN=70;//#define   AR_AREA_MIN          70\r
51 \r
52 //    private final NyARMarker[] marker_holder;     //マーカーデータの保持配列\r
53 //    private final NyARMarker[] marker_info2_array;//マーカーデータのインデックス配列\r
54 //    private int marker_num;\r
55     private int width,height;\r
56     /**\r
57      * 最大i_squre_max個のマーカーを検出するクラスを作成する。\r
58      * @param i_width\r
59      * @param i_height\r
60      */\r
61     public NyARDetectMarker(int i_width,int i_height)\r
62     {\r
63         this.width =i_width;\r
64         this.height=i_height;\r
65         \r
66 //      this.marker_holder=new NyARMarker[i_squre_max];\r
67 //      this.marker_info2_array=new NyARMarker[i_squre_max];\r
68 //      //先にマーカーホルダにオブジェクトを作っておく\r
69 //      for(int i=0;i<i_squre_max;i++){\r
70 //          this.marker_holder[i]=new NyARMarker();\r
71 //      }\r
72     }\r
73     private static final int AR_CHAIN_MAX=10000;\r
74     private final int[] wk_arGetContour_xdir={0,  1, 1, 1, 0,-1,-1,-1};\r
75     private final int[] wk_arGetContour_ydir={-1,-1, 0, 1, 1, 1, 0,-1};\r
76     private final int[] wk_arGetContour_xcoord=new int[AR_CHAIN_MAX];\r
77     private final int[] wk_arGetContour_ycoord=new int[AR_CHAIN_MAX];\r
78     /**\r
79      * int arGetContour( ARInt16 *limage, int *label_ref,int label, int clip[4], ARMarkerInfo2 *marker_info2 )\r
80      * 関数の代替品\r
81      * detectMarker関数から使う関数です。o_markerにlabelとclipで示される1個のマーカーを格納します。\r
82      * marker_holder[i_holder_num]にオブジェクトが無ければまず新規に作成し、もし\r
83      * 既に存在すればそこにマーカー情報を上書きして記録します。\r
84      * Optimize:STEP[369->336]\r
85      * @param o_marker\r
86      * @param limage\r
87      * @param label_ref\r
88      * @param label\r
89      * @param clip\r
90      * @throws NyARException\r
91      */\r
92     private final void arGetContour(NyARMarker o_marker,int[][] limage,int i_labelnum, NyARLabel i_label) throws NyARException\r
93     {\r
94         final int[] xcoord=wk_arGetContour_xcoord;\r
95         final int[] ycoord=wk_arGetContour_ycoord;\r
96         final int[] xdir=wk_arGetContour_xdir; //static int      xdir[8] = { 0, 1, 1, 1, 0,-1,-1,-1};\r
97         final int[] ydir=wk_arGetContour_ydir;//static int      ydir[8] = {-1,-1, 0, 1, 1, 1, 0,-1};\r
98         //ShortPointer p1;//ARInt16         *p1;\r
99         int coord_num;\r
100         int             sx=0, sy=0, dir;\r
101         int             dmax, d, v1=0;\r
102         int             i, j,w;\r
103 \r
104         int[] limage_j;\r
105         j = i_label.clip_t;\r
106         limage_j=limage[j];\r
107         final int clip1=i_label.clip_r;\r
108         //p1=ShortPointer.wrap(limage,j*xsize+clip.get());//p1 = &(limage[j*xsize+clip[0]]);\r
109         for( i = i_label.clip_l; i <= clip1; i++){//for( i = clip[0]; i <= clip[1]; i++, p1++ ) {\r
110             w=limage_j[i];\r
111             if(w > 0 && w == i_labelnum ) {\r
112                 sx = i;\r
113                 sy = j;\r
114                 break;\r
115             }\r
116         }\r
117         if(i>clip1){//if( i > clip[1] ) {\r
118             System.out.println("??? 1");//printf();\r
119             throw new NyARException();//return(-1);\r
120         }\r
121 \r
122 //      //マーカーホルダが既に確保済みかを調べる\r
123 //      if(marker_holder[i_holder_num]==null){\r
124 //          //確保していなければ確保\r
125 //          marker_holder[i_holder_num]=new NyARMarker();\r
126 //      }\r
127 \r
128 \r
129         coord_num=1;//marker_info2->coord_num = 1;\r
130         xcoord[0]=sx;//marker_info2->x_coord[0] = sx;\r
131         ycoord[0]=sy;//marker_info2->y_coord[0] = sy;\r
132         dir = 5;\r
133         \r
134         int r,c;\r
135         c=xcoord[0];\r
136         r=ycoord[0];\r
137         dmax=0;\r
138         //本家はdmaxの作成とxcoordの作成を別のループでやってるけど、非効率なので統合\r
139         for(;;){\r
140             //xcoord[1]-xcoord[n]までのデータを作る。\r
141             \r
142 //          1個前のxcoordとycoordはループ後半で格納される。\r
143 //          c=xcoord[coord_num-1];\r
144 //          r=ycoord[coord_num-1];\r
145             //p1 = &(limage[marker_info2->y_coord[marker_info2->coord_num-1] * xsize+ marker_info2->x_coord[marker_info2->coord_num-1]]);\r
146             dir = (dir+5)%8;\r
147             for(i=0;i<8;i++) {\r
148                 if(limage[r+ydir[dir]][c+xdir[dir]]>0){//if( p1[ydir[dir]*xsize+xdir[dir]] > 0 ){\r
149                     break;\r
150                 }\r
151                 dir = (dir+1)%8;        \r
152             }\r
153             if( i == 8 ){\r
154                 System.out.println("??? 2");//printf("??? 2\n");\r
155                 throw new NyARException();//return(-1);\r
156             }\r
157 //          xcoordとycoordをc,rにも保存\r
158             c= c + xdir[dir];//marker_info2->x_coord[marker_info2->coord_num]= marker_info2->x_coord[marker_info2->coord_num-1] + xdir[dir];\r
159             r= r + ydir[dir];//marker_info2->y_coord[marker_info2->coord_num]= marker_info2->y_coord[marker_info2->coord_num-1] + ydir[dir];\r
160             xcoord[coord_num]=c;//marker_info2->x_coord[marker_info2->coord_num]= marker_info2->x_coord[marker_info2->coord_num-1] + xdir[dir];\r
161             ycoord[coord_num]=r;//marker_info2->y_coord[marker_info2->coord_num]= marker_info2->y_coord[marker_info2->coord_num-1] + ydir[dir];\r
162             if(c == sx && r == sy ){\r
163                 break;\r
164             }\r
165             //dmaxの計算\r
166             d=(c-sx)*(c-sx)+(r-sy)*(r-sy);\r
167             if( d > dmax ) {\r
168                 dmax = d;\r
169                 v1 = coord_num;\r
170             }\r
171             //終了条件判定\r
172             coord_num++;\r
173             if(coord_num == AR_CHAIN_MAX-1){//if( marker_info2.coord_num == Config.AR_CHAIN_MAX-1 ){\r
174                 System.out.println("??? 3");//printf("??? 3\n");\r
175                 throw new NyARException();//return(-1);\r
176             }\r
177         }\r
178 //\r
179 //      dmax = 0;\r
180 //      for(i=1;i<coord_num;i++) {//    for(i=1;i<marker_info2->coord_num;i++) {\r
181 //          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
182 //          if( d > dmax ) {\r
183 //              dmax = d;\r
184 //              v1 = i;\r
185 //          }\r
186 //      }\r
187         //NyARMarkerへcoord情報をセット\r
188         //coordの並び替えと保存はNyARMarkerへ移動\r
189         o_marker.setCoordXY(v1,coord_num,xcoord,ycoord);\r
190         return;\r
191     }\r
192 \r
193     /**\r
194      * 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
195      * 関数の代替品\r
196      * ラベリング情報からマーカー一覧を作成してo_marker_listを更新します。\r
197      * 関数はo_marker_listに重なりを除外したマーカーリストを作成します。\r
198      * \r
199      * @param i_labeling\r
200      * ラベリング済みの情報を持つラベリングオブジェクト\r
201      * @param i_factor\r
202      * 何かの閾値?\r
203      * @param o_marker_list\r
204      * 抽出したマーカーを格納するリスト\r
205      * @throws NyARException\r
206      */\r
207     public final void detectMarker(NyLabelingImage i_labeling,double i_factor,NyARMarkerList o_marker_list) throws NyARException\r
208     {\r
209         int label_area;\r
210         int i;\r
211         int xsize, ysize;\r
212         NyARLabel[] labels=i_labeling.getLabelList().getArray();\r
213 //      int[] warea     =i_labeling.getArea();\r
214         int label_num   =i_labeling.getLabelList().getCount();\r
215 //      int[][] wclip   =i_labeling.getClip();\r
216 //      double[] wpos   =i_labeling.getPos();\r
217         int[][] limage=i_labeling.getImage();\r
218 \r
219         //マーカーホルダをリセット\r
220         o_marker_list.reset();\r
221 //      marker_num=0;\r
222         xsize =width;\r
223         ysize =height;\r
224 //      マーカーをmarker_holderに蓄積する。\r
225         NyARMarker current_marker=o_marker_list.getCurrentHolder();\r
226         NyARLabel label_pt;\r
227         for(i=0; i<label_num; i++ ){\r
228             label_pt=labels[i];\r
229             label_area=label_pt.area;\r
230             if(label_area < AR_AREA_MIN || label_area > AR_AREA_MAX ){\r
231                 continue;\r
232             }\r
233             if( label_pt.clip_l == 1 || label_pt.clip_r == xsize-2 ){//if( wclip[i*4+0] == 1 || wclip[i*4+1] == xsize-2 ){\r
234                 continue;\r
235             }\r
236             if( label_pt.clip_t == 1 || label_pt.clip_b == ysize-2 ){//if( wclip[i*4+2] == 1 || wclip[i*4+3] == ysize-2 ){\r
237                 continue;\r
238             }\r
239             //ret = arGetContour( limage, label_ref, i+1,&(wclip[i*4]), &(marker_info2[marker_num2]));\r
240             arGetContour(current_marker,limage, i+1,label_pt);\r
241 \r
242             if(!current_marker.checkSquare(label_area,i_factor,label_pt.pos_x,label_pt.pos_y)){\r
243                 //後半で整理するからここはいらない。//         marker_holder[marker_num2]=null;\r
244                 continue;\r
245             }\r
246 //          この3行はcheckSquareの最終段に含める。\r
247 //          marker_holder[marker_num2].area   = warea[i];\r
248 //          marker_holder[marker_num2].pos[0] = wpos[i*2+0];\r
249 //          marker_holder[marker_num2].pos[1] = wpos[i*2+1];\r
250             //マーカー検出→次のホルダを取得\r
251             current_marker=o_marker_list.getNextHolder();\r
252             //マーカーリストが上限に達したか確認\r
253             if(current_marker==null){\r
254                 break;\r
255             }\r
256         }\r
257         //マーカーリストを整理(重なり処理とかはマーカーリストに責務押し付け)\r
258         o_marker_list.updateMarkerArray();\r
259 //      重なり処理かな?\r
260 //      double[] pos_j,pos_i;\r
261 //      for(i=0; i < marker_num2; i++ ){\r
262 //          pos_i=marker_holder[i].pos;\r
263 //          for(j=i+1; j < marker_num2; j++ ) {\r
264 //              pos_j=marker_holder[j].pos;\r
265 //              d = (pos_i[0] - pos_j[0])*(pos_i[0] - pos_j[0])+\r
266 //              (pos_i[1] - pos_j[1])*(pos_i[1] - pos_j[1]);\r
267 //              if(marker_holder[i].area >marker_holder[j].area ) {\r
268 //                  if( d <marker_holder[i].area / 4 ) {\r
269 //                      marker_holder[j].area = 0;\r
270 //                  }\r
271 //              }else{\r
272 //                  if( d < marker_holder[j].area / 4 ) {\r
273 //                      marker_holder[i].area = 0;\r
274 //                  }\r
275 //              }\r
276 //          }\r
277 //      }\r
278 //      みつかったマーカーを整理する。\r
279 //      エリアが0のマーカーを外した配列を作って、その数もついでに計算\r
280 //      for(i=0;i<marker_num2;i++){\r
281 //          if(marker_holder[i].area==0.0){\r
282 //              continue;\r
283 //          }\r
284 //          marker_info2_array[marker_num]=marker_holder[i];\r
285 //          marker_num++;\r
286 //      }        \r
287 //      for( i=0; i < marker_num2; i++ ) {\r
288 //      if( marker_info2_array[i].area == 0.0 ) {\r
289 //      for( j=i+1; j < marker_num2; j++ ){\r
290 //      marker_info2_array[j-1] = marker_info2_array[j];\r
291 //      }\r
292 //      marker_num2--;\r
293 //      }\r
294 //      }\r
295 //      発見したマーカー数をセット\r
296 //      marker_num=marker_num2;//*marker_num = marker_num2;\r
297 //      return( &(marker_info2[0]) );\r
298         return;\r
299     }\r
300 \r
301 }\r