OSDN Git Service

dc7e6143bd23ca59b5c21f99d8d5b06218b3e9d5
[nyartoolkit-and/nyartoolkit-and.git] / sample / sandbox / jp / nyatla / nyartoolkit / sandbox / x2 / NyARLabeling_ARToolKit_X2.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.sandbox.x2;\r
33 \r
34 import jp.nyatla.nyartoolkit.NyARException;\r
35 import jp.nyatla.nyartoolkit.core.raster.*;\r
36 import jp.nyatla.nyartoolkit.core.types.*;\r
37 import jp.nyatla.nyartoolkit.core.labeling.*;\r
38 import jp.nyatla.nyartoolkit.core.labeling.artoolkit.NyARLabelingImage;\r
39 import jp.nyatla.nyartoolkit.core.labeling.artoolkit.NyARLabelingLabel;\r
40 import jp.nyatla.nyartoolkit.core.labeling.artoolkit.NyARLabelingLabelStack;\r
41 \r
42 /**\r
43  * 計算部から浮動小数点計算を除外したNyARLabeling_ARToolKit\r
44  * NyARLabeling_ARToolKitと同じ処理をするけど、エリア計算にintを使う。 \r
45  * 画面サイズが1600x1600を超えると挙動が怪しくなる。\r
46  * \r
47  */\r
48 public class NyARLabeling_ARToolKit_X2\r
49 {\r
50         private static final int WORK_SIZE = 1024 * 32;// #define WORK_SIZE 1024*32\r
51 \r
52         private final NyARWorkHolder work_holder = new NyARWorkHolder(WORK_SIZE);\r
53 \r
54         private NyARIntSize _dest_size;\r
55 \r
56         private NyARLabelingImage _out_image;\r
57 \r
58         public void attachDestination(NyARLabelingImage i_destination_image) throws NyARException\r
59         {\r
60                 // サイズチェック\r
61                 NyARIntSize size = i_destination_image.getSize();\r
62                 this._out_image = i_destination_image;\r
63 \r
64                 // NyLabelingImageのイメージ初期化(枠書き)\r
65                 int[] img = (int[])i_destination_image.getBufferReader().getBuffer();\r
66                 int bottom_ptr=(size.h - 1)*size.w;\r
67                 for (int i = 0; i < size.w; i++) {\r
68                         img[i] = 0;\r
69                         img[bottom_ptr+i] = 0;\r
70                 }\r
71                 for (int i = 0; i < size.h; i++) {\r
72                         img[i*size.w] = 0;\r
73                         img[(i+1)*size.w - 1] = 0;\r
74                 }\r
75 \r
76                 // サイズ(参照値)を保存\r
77                 this._dest_size = size;\r
78                 return;\r
79         }\r
80 \r
81         public NyARLabelingImage getAttachedDestination()\r
82         {\r
83                 return this._out_image;\r
84         }\r
85 \r
86         /**\r
87          * static ARInt16 *labeling2( ARUint8 *image, int thresh,int *label_num, int **area, double **pos, int **clip,int **label_ref, int LorR ) 関数の代替品\r
88          * ラスタimageをラベリングして、結果を保存します。 Optimize:STEP[1514->1493]\r
89          * \r
90          * @param i_raster\r
91          * @throws NyARException\r
92          */\r
93         public void labeling(NyARBinRaster i_raster) throws NyARException\r
94         {\r
95                 int m, n; /* work */\r
96                 int i, j, k;\r
97                 NyARLabelingImage out_image = this._out_image;\r
98 \r
99                 // サイズチェック\r
100                 NyARIntSize in_size = i_raster.getSize();\r
101                 this._dest_size.isEqualSize(in_size);\r
102 \r
103                 final int lxsize = in_size.w;// lxsize = arUtil_c.arImXsize;\r
104                 final int lysize = in_size.h;// lysize = arUtil_c.arImYsize;\r
105                 int[] label_img = (int[])out_image.getBufferReader().getBuffer();\r
106 \r
107                 // 枠作成はインスタンスを作った直後にやってしまう。\r
108                 \r
109                 //ラベリング情報のリセット(ラベリングインデックスを使用)\r
110                 out_image.reset(true);\r
111                 \r
112                 int[] label_idxtbl=out_image.getIndexArray();\r
113 \r
114                 int[] work2_pt;\r
115                 int wk_max = 0;\r
116 \r
117                 int label_pixel;\r
118                 int[] raster_buf=(int[])i_raster.getBufferReader().getBuffer();\r
119                 int line_ptr;\r
120                 int[][] work2 = this.work_holder.work2;\r
121                 int label_img_ptr0, label_img_ptr1;\r
122                 for (j = 1; j < lysize - 1; j++) {// for (int j = 1; j < lysize - 1;j++, pnt += poff*2, pnt2 += 2) {\r
123                         line_ptr=j*lxsize;\r
124                         label_img_ptr0=j*lxsize;//label_img_pt0 = label_img[j];\r
125                         label_img_ptr1=label_img_ptr0-lxsize;//label_img_pt1 = label_img[j - 1];\r
126                         for (i = 1; i < lxsize - 1; i++) {// for(int i = 1; i < lxsize-1;i++, pnt+=poff, pnt2++) {\r
127                                 // RGBの合計値が閾値より小さいかな?\r
128                                 if (raster_buf[line_ptr+i]==0) {\r
129                                         // pnt1 = ShortPointer.wrap(pnt2, -lxsize);//pnt1 =&(pnt2[-lxsize]);\r
130                                         if (label_img[label_img_ptr1+i] > 0) {//if (label_img_pt1[i] > 0) {// if( *pnt1 > 0 ) {\r
131                                                 label_pixel = label_img[label_img_ptr1+i];//label_pixel = label_img_pt1[i];// *pnt2 = *pnt1;\r
132 \r
133                                                 work2_pt = work2[label_pixel - 1];\r
134                                                 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;\r
135                                                 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;\r
136                                                 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;\r
137                                                 work2_pt[6] = j;// work2[((*pnt2)-1)*7+6] = j;\r
138                                         } else if (label_img[label_img_ptr1+i + 1] > 0) {//} else if (label_img_pt1[i + 1] > 0) {// }else if(*(pnt1+1) > 0 ) {\r
139                                                 if (label_img[label_img_ptr1+i - 1] > 0) {//if (label_img_pt1[i - 1] > 0) {// if( *(pnt1-1) > 0 ) {\r
140                                                         m = label_idxtbl[label_img[label_img_ptr1+i + 1] - 1];//m = label_idxtbl[label_img_pt1[i + 1] - 1];// m =work[*(pnt1+1)-1];\r
141                                                         n = label_idxtbl[label_img[label_img_ptr1+i - 1] - 1];//n = label_idxtbl[label_img_pt1[i - 1] - 1];// n =work[*(pnt1-1)-1];\r
142                                                         if (m > n) {\r
143                                                                 label_pixel = n;// *pnt2 = n;\r
144                                                                 // wk=IntPointer.wrap(work, 0);//wk =\r
145                                                                 // &(work[0]);\r
146                                                                 for (k = 0; k < wk_max; k++) {\r
147                                                                         if (label_idxtbl[k] == m) {// if( *wk == m )\r
148                                                                                 label_idxtbl[k] = n;// *wk = n;\r
149                                                                         }\r
150                                                                 }\r
151                                                         } else if (m < n) {\r
152                                                                 label_pixel = m;// *pnt2 = m;\r
153                                                                 // wk=IntPointer.wrap(work,0);//wk = &(work[0]);\r
154                                                                 for (k = 0; k < wk_max; k++) {\r
155                                                                         if (label_idxtbl[k] == n) {// if( *wk == n ){\r
156                                                                                 label_idxtbl[k] = m;// *wk = m;\r
157                                                                         }\r
158                                                                 }\r
159                                                         } else {\r
160                                                                 label_pixel = m;// *pnt2 = m;\r
161                                                         }\r
162                                                         work2_pt = work2[label_pixel - 1];\r
163                                                         work2_pt[0]++;\r
164                                                         work2_pt[1] += i;\r
165                                                         work2_pt[2] += j;\r
166                                                         work2_pt[6] = j;\r
167                                                 } else if ((label_img[label_img_ptr0+i - 1]) > 0) {//} else if ((label_img_pt0[i - 1]) > 0) {// }else if(*(pnt2-1) > 0) {\r
168                                                         m = label_idxtbl[label_img[label_img_ptr1+i + 1] - 1];//m = label_idxtbl[label_img_pt1[i + 1] - 1];// m =work[*(pnt1+1)-1];\r
169                                                         n = label_idxtbl[label_img[label_img_ptr0+i - 1] - 1];//n = label_idxtbl[label_img_pt0[i - 1] - 1];// n =work[*(pnt2-1)-1];\r
170                                                         if (m > n) {\r
171 \r
172                                                                 label_pixel = n;// *pnt2 = n;\r
173                                                                 for (k = 0; k < wk_max; k++) {\r
174                                                                         if (label_idxtbl[k] == m) {// if( *wk == m ){\r
175                                                                                 label_idxtbl[k] = n;// *wk = n;\r
176                                                                         }\r
177                                                                 }\r
178                                                         } else if (m < n) {\r
179                                                                 label_pixel = m;// *pnt2 = m;\r
180                                                                 for (k = 0; k < wk_max; k++) {\r
181                                                                         if (label_idxtbl[k] == n) {// if( *wk == n ){\r
182                                                                                 label_idxtbl[k] = m;// *wk = m;\r
183                                                                         }\r
184                                                                 }\r
185                                                         } else {\r
186                                                                 label_pixel = m;// *pnt2 = m;\r
187                                                         }\r
188                                                         work2_pt = work2[label_pixel - 1];\r
189                                                         work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;\r
190                                                         work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;\r
191                                                         work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;\r
192                                                 } else {\r
193 \r
194                                                         label_pixel = label_img[label_img_ptr1+i + 1];//label_pixel = label_img_pt1[i + 1];// *pnt2 =\r
195                                                                                                                                 // *(pnt1+1);\r
196 \r
197                                                         work2_pt = work2[label_pixel - 1];\r
198                                                         work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;\r
199                                                         work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;\r
200                                                         work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;\r
201                                                         if (work2_pt[3] > i) {// if(\r
202                                                                                                         // work2[((*pnt2)-1)*7+3] >\r
203                                                                                                         // i ){\r
204                                                                 work2_pt[3] = i;// work2[((*pnt2)-1)*7+3] = i;\r
205                                                         }\r
206                                                         work2_pt[6] = j;// work2[((*pnt2)-1)*7+6] = j;\r
207                                                 }\r
208                                         } else if ((label_img[label_img_ptr1+i - 1]) > 0) {//} else if ((label_img_pt1[i - 1]) > 0) {// }else if(\r
209                                                                                                                         // *(pnt1-1) > 0 ) {\r
210                                                 label_pixel = label_img[label_img_ptr1+i - 1];//label_pixel = label_img_pt1[i - 1];// *pnt2 =\r
211                                                                                                                         // *(pnt1-1);\r
212 \r
213                                                 work2_pt = work2[label_pixel - 1];\r
214                                                 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;\r
215                                                 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;\r
216                                                 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;\r
217                                                 if (work2_pt[4] < i) {// if( work2[((*pnt2)-1)*7+4] <i ){\r
218                                                         work2_pt[4] = i;// work2[((*pnt2)-1)*7+4] = i;\r
219                                                 }\r
220                                                 work2_pt[6] = j;// work2[((*pnt2)-1)*7+6] = j;\r
221                                         } else if (label_img[label_img_ptr0+i - 1] > 0) {//} else if (label_img_pt0[i - 1] > 0) {// }else if(*(pnt2-1) > 0) {\r
222                                                 label_pixel = label_img[label_img_ptr0+i - 1];//label_pixel = label_img_pt0[i - 1];// *pnt2 =*(pnt2-1);\r
223 \r
224                                                 work2_pt = work2[label_pixel - 1];\r
225                                                 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;\r
226                                                 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;\r
227                                                 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;\r
228                                                 if (work2_pt[4] < i) {// if( work2[((*pnt2)-1)*7+4] <i ){\r
229                                                         work2_pt[4] = i;// work2[((*pnt2)-1)*7+4] = i;\r
230                                                 }\r
231                                         } else {\r
232                                                 // 現在地までの領域を予約\r
233                                                 this.work_holder.reserv(wk_max);\r
234                                                 wk_max++;\r
235                                                 label_idxtbl[wk_max - 1] = wk_max;\r
236                                                 label_pixel = wk_max;// work[wk_max-1] = *pnt2 = wk_max;\r
237                                                 work2_pt = work2[wk_max - 1];\r
238                                                 work2_pt[0] = 1;\r
239                                                 work2_pt[1] = i;\r
240                                                 work2_pt[2] = j;\r
241                                                 work2_pt[3] = i;\r
242                                                 work2_pt[4] = i;\r
243                                                 work2_pt[5] = j;\r
244                                                 work2_pt[6] = j;\r
245                                         }\r
246                                         label_img[label_img_ptr0+i] = label_pixel;//label_img_pt0[i] = label_pixel;\r
247                                 } else {\r
248                                         label_img[label_img_ptr0+i] = 0;//label_img_pt0[i] = 0;// *pnt2 = 0;\r
249                                 }\r
250                         }\r
251                 }\r
252                 // インデックステーブルとラベル数の計算\r
253                 int wlabel_num = 1;// *label_num = *wlabel_num = j - 1;\r
254 \r
255                 for (i = 0; i < wk_max; i++) {// for(int i = 1; i <= wk_max; i++,wk++) {\r
256                         label_idxtbl[i] = (label_idxtbl[i] == i + 1) ? wlabel_num++ : label_idxtbl[label_idxtbl[i] - 1];// *wk=(*wk==i)?j++:work[(*wk)-1];\r
257                 }\r
258                 wlabel_num -= 1;// *label_num = *wlabel_num = j - 1;\r
259                 if (wlabel_num == 0) {// if( *label_num == 0 ) {\r
260                         // 発見数0\r
261                         out_image.getLabelStack().clear();\r
262                         return;\r
263                 }\r
264                 // ラベルの整理\r
265                 updateLabelStackLarge(out_image.getLabelStack(), label_idxtbl, in_size, work2, wk_max, wlabel_num);\r
266 \r
267                 return;\r
268         }\r
269         private int[][] __updateLabelStackLarge_temp=new int[64][7];/*area,x,y,l,r,t,b*/\r
270 \r
271         /* 構造が変わるから、ハイスピード版実装するときに使う。 */\r
272         private void updateLabelStackLarge(NyARLabelingLabelStack i_stack, int[] i_lindex, NyARIntSize i_size, int[][] i_work, int i_work_max, int i_number_of_label) throws NyARException\r
273         {\r
274                 //計算用のワークを確保\r
275                 int[][] temp=this.__updateLabelStackLarge_temp;\r
276                 if(temp.length<i_number_of_label){\r
277                         temp=new int[i_number_of_label+64][7];\r
278                         this.__updateLabelStackLarge_temp=temp;\r
279                 }\r
280                 \r
281                 // ラベルバッファを予約\r
282                 i_stack.reserv(i_number_of_label);\r
283                 // エリアと重心、クリップ領域を計算\r
284                 final NyARLabelingLabel[] labels = i_stack.getArray();\r
285                 for (int i = 0; i < i_number_of_label; i++) {\r
286                         final int[] temp_ptr = temp[i];\r
287                         temp_ptr[0]=0;//area\r
288                         temp_ptr[1]=0;//x\r
289                         temp_ptr[2]=0;//y\r
290                         temp_ptr[3]=i_size.w;//l\r
291                         temp_ptr[4]=0;//r\r
292                         temp_ptr[5]=i_size.h;//t\r
293                         temp_ptr[6]=0;//b\r
294                 }\r
295                 //計算!\r
296 \r
297                 for (int i = 0; i < i_work_max; i++) {\r
298                         final int temp_ptr[] = temp[i_lindex[i] - 1];\r
299                         final int[] work2_pt = i_work[i];\r
300                         temp_ptr[0] += work2_pt[0];\r
301                         temp_ptr[1] += work2_pt[1];\r
302                         temp_ptr[2] += work2_pt[2];\r
303                         if (temp_ptr[3] > work2_pt[3]) {\r
304                                 temp_ptr[3] = work2_pt[3];\r
305                         }\r
306                         if (temp_ptr[4] < work2_pt[4]) {\r
307                                 temp_ptr[4] = work2_pt[4];\r
308                         }\r
309                         if (temp_ptr[5] > work2_pt[5]) {\r
310                                 temp_ptr[5] = work2_pt[5];\r
311                         }\r
312                         if (temp_ptr[6] < work2_pt[6]) {\r
313                                 temp_ptr[6] = work2_pt[6];\r
314                         }\r
315                 }\r
316                 //ストア\r
317                 for (int i = 0; i < i_number_of_label; i++) {// for(int i = 0; i < *label_num; i++ ) {\r
318                         final NyARLabelingLabel label_pt = labels[i];\r
319                         final int temp_ptr[] = temp[i];\r
320                         label_pt.id=i+1;\r
321                         label_pt.area=temp_ptr[0];                      \r
322                         label_pt.pos_x= (double)temp_ptr[1]/label_pt.area;\r
323                         label_pt.pos_y= (double)temp_ptr[2]/label_pt.area;\r
324                         label_pt.clip_l= temp_ptr[3];\r
325                         label_pt.clip_r= temp_ptr[4];\r
326                         label_pt.clip_t= temp_ptr[5];\r
327                         label_pt.clip_b= temp_ptr[6];\r
328                 }\r
329                 return;\r
330         }\r
331 }\r
332 \r
333 /**\r
334  * NyARLabeling_O2のworkとwork2を可変長にするためのクラス\r
335  * \r
336  * \r
337  */\r
338 final class NyARWorkHolder\r
339 {\r
340         private final static int ARRAY_APPEND_STEP = 256;\r
341 \r
342         public final int[] work;\r
343 \r
344         public final int[][] work2;\r
345 \r
346         private int allocate_size;\r
347 \r
348         /**\r
349          * 最大i_holder_size個の動的割り当てバッファを準備する。\r
350          * \r
351          * @param i_holder_size\r
352          */\r
353         public NyARWorkHolder(int i_holder_size)\r
354         {\r
355                 // ポインタだけははじめに確保しておく\r
356                 this.work = new int[i_holder_size];\r
357                 this.work2 = new int[i_holder_size][];\r
358                 this.allocate_size = 0;\r
359         }\r
360 \r
361         /**\r
362          * i_indexで指定した番号までのバッファを準備する。\r
363          * \r
364          * @param i_index\r
365          */\r
366         public final void reserv(int i_index) throws NyARException\r
367         {\r
368                 // アロケート済みなら即リターン\r
369                 if (this.allocate_size > i_index) {\r
370                         return;\r
371                 }\r
372                 // 要求されたインデクスは範囲外\r
373                 if (i_index >= this.work.length) {\r
374                         throw new NyARException();\r
375                 }\r
376                 // 追加アロケート範囲を計算\r
377                 int range = i_index + ARRAY_APPEND_STEP;\r
378                 if (range >= this.work.length) {\r
379                         range = this.work.length;\r
380                 }\r
381                 // アロケート\r
382                 for (int i = this.allocate_size; i < range; i++) {\r
383                         this.work2[i] = new int[8];\r
384                 }\r
385                 this.allocate_size = range;\r
386         }\r
387 }\r