OSDN Git Service

[backup]NyARToolkit
[nyartoolkit-and/nyartoolkit-and.git] / trunk / src / jp / nyatla / nyartoolkit / core / labeling / artoolkit / NyARLabeling_ARToolKit.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 edition ARToolKit class library.\r
11  * Copyright (C)2008-2009 Ryo Iizuka\r
12  *\r
13  * This program is free software: you can redistribute it and/or modify\r
14  * it under the terms of the GNU General Public License as published by\r
15  * the Free Software Foundation, either version 3 of the License, or\r
16  * (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 program.  If not, see <http://www.gnu.org/licenses/>.\r
25  * \r
26  * For further information please contact.\r
27  *      http://nyatla.jp/nyatoolkit/\r
28  *      <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>\r
29  * \r
30  */\r
31 package jp.nyatla.nyartoolkit.core.labeling.artoolkit;\r
32 \r
33 import jp.nyatla.nyartoolkit.NyARException;\r
34 import jp.nyatla.nyartoolkit.core.raster.*;\r
35 import jp.nyatla.nyartoolkit.core.types.*;\r
36 \r
37 /**\r
38  * ARToolKit互換のラベリングクラスです。 ARToolKitと同一な評価結果を返します。\r
39  * \r
40  */\r
41 final public class NyARLabeling_ARToolKit\r
42 {\r
43         private static final int WORK_SIZE = 1024 * 32;// #define WORK_SIZE 1024*32\r
44 \r
45         private final NyARWorkHolder work_holder = new NyARWorkHolder(WORK_SIZE);\r
46 \r
47 \r
48         /**\r
49          * static ARInt16 *labeling2( ARUint8 *image, int thresh,int *label_num, int **area, double **pos, int **clip,int **label_ref, int LorR ) 関数の代替品\r
50          * ラスタimageをラベリングして、結果を保存します。 Optimize:STEP[1514->1493]\r
51          * \r
52          * @param i_raster\r
53          * @throws NyARException\r
54          */\r
55         public int labeling(NyARBinRaster i_raster,NyARLabelingImage o_destination) throws NyARException\r
56         {\r
57                 assert(i_raster.getBufferType()==INyARRaster.BUFFERFORMAT_INT1D_BIN_8);\r
58                 int label_img_ptr1, label_pixel;\r
59                 int i, j;\r
60                 int n, k; /* work */\r
61                 \r
62                 // サイズチェック\r
63                 NyARIntSize in_size = i_raster.getSize();\r
64                 assert(o_destination.getSize().isEqualSize(in_size));\r
65 \r
66                 final int lxsize = in_size.w;// lxsize = arUtil_c.arImXsize;\r
67                 final int lysize = in_size.h;// lysize = arUtil_c.arImYsize;\r
68                 final int[] label_img = (int[]) o_destination.getBuffer();\r
69 \r
70                 // 枠作成はインスタンスを作った直後にやってしまう。\r
71 \r
72                 // ラベリング情報のリセット(ラベリングインデックスを使用)\r
73                 o_destination.reset(true);\r
74 \r
75                 int[] label_idxtbl = o_destination.getIndexArray();\r
76                 int[] raster_buf = (int[]) i_raster.getBuffer();\r
77 \r
78                 int[] work2_pt;\r
79                 int wk_max = 0;\r
80 \r
81                 int pixel_index;\r
82                 int[][] work2 = this.work_holder.work2;\r
83 \r
84                 // [1,1](ptr0)と、[0,1](ptr1)のインデクス値を計算する。\r
85                 for (j = 1; j < lysize - 1; j++) {// for (int j = 1; j < lysize - 1;j++, pnt += poff*2, pnt2 += 2) {\r
86                         pixel_index = j * lxsize + 1;\r
87                         label_img_ptr1 = pixel_index - lxsize;// label_img_pt1 = label_img[j - 1];\r
88                         for (i = 1; i < lxsize - 1; i++, pixel_index++, label_img_ptr1++) {// for(int i = 1; i < lxsize-1;i++, pnt+=poff, pnt2++) {\r
89                                 // RGBの合計値が閾値より小さいかな?\r
90                                 if (raster_buf[pixel_index] != 0) {\r
91                                         label_img[pixel_index] = 0;// label_img_pt0[i] = 0;// *pnt2 = 0;\r
92                                 } else {\r
93                                         // pnt1 = ShortPointer.wrap(pnt2, -lxsize);//pnt1 =&(pnt2[-lxsize]);\r
94                                         if (label_img[label_img_ptr1] > 0) {// if (label_img_pt1[i] > 0) {// if( *pnt1 > 0 ) {\r
95                                                 label_pixel = label_img[label_img_ptr1];// label_pixel = label_img_pt1[i];// *pnt2 = *pnt1;\r
96 \r
97                                                 work2_pt = work2[label_pixel - 1];\r
98                                                 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;\r
99                                                 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;\r
100                                                 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;\r
101                                                 work2_pt[6] = j;// work2[((*pnt2)-1)*7+6] = j;\r
102                                         } else if (label_img[label_img_ptr1 + 1] > 0) {// } else if (label_img_pt1[i + 1] > 0) {// }else if(*(pnt1+1) > 0 ) {\r
103                                                 if (label_img[label_img_ptr1 - 1] > 0) {// if (label_img_pt1[i - 1] > 0) {// if( *(pnt1-1) > 0 ) {\r
104                                                         label_pixel = label_idxtbl[label_img[label_img_ptr1 + 1] - 1];// m = label_idxtbl[label_img_pt1[i + 1] - 1];// m\r
105                                                                                                                                                                                         // =work[*(pnt1+1)-1];\r
106                                                         n = label_idxtbl[label_img[label_img_ptr1 - 1] - 1];// n = label_idxtbl[label_img_pt1[i - 1] - 1];// n =work[*(pnt1-1)-1];\r
107                                                         if (label_pixel > n) {\r
108                                                                 // wk=IntPointer.wrap(work, 0);//wk = &(work[0]);\r
109                                                                 for (k = 0; k < wk_max; k++) {\r
110                                                                         if (label_idxtbl[k] == label_pixel) {// if( *wk == m )\r
111                                                                                 label_idxtbl[k] = n;// *wk = n;\r
112                                                                         }\r
113                                                                 }\r
114                                                                 label_pixel = n;// *pnt2 = n;\r
115                                                         } else if (label_pixel < n) {\r
116                                                                 // wk=IntPointer.wrap(work,0);//wk = &(work[0]);\r
117                                                                 for (k = 0; k < wk_max; k++) {\r
118                                                                         if (label_idxtbl[k] == n) {// if( *wk == n ){\r
119                                                                                 label_idxtbl[k] = label_pixel;// *wk = m;\r
120                                                                         }\r
121                                                                 }\r
122                                                         }\r
123                                                         work2_pt = work2[label_pixel - 1];\r
124                                                         work2_pt[0]++;\r
125                                                         work2_pt[1] += i;\r
126                                                         work2_pt[2] += j;\r
127                                                         work2_pt[6] = j;\r
128                                                 } else if ((label_img[pixel_index - 1]) > 0) {// } else if ((label_img_pt0[i - 1]) > 0) {// }else if(*(pnt2-1) > 0) {\r
129                                                         label_pixel = label_idxtbl[label_img[label_img_ptr1 + 1] - 1];// m = label_idxtbl[label_img_pt1[i + 1] - 1];// m =work[*(pnt1+1)-1];\r
130                                                         n = label_idxtbl[label_img[pixel_index - 1] - 1];// n = label_idxtbl[label_img_pt0[i - 1] - 1];// n =work[*(pnt2-1)-1];\r
131                                                         if (label_pixel > n) {\r
132                                                                 for (k = 0; k < wk_max; k++) {\r
133                                                                         if (label_idxtbl[k] == label_pixel) {// if( *wk == m ){\r
134                                                                                 label_idxtbl[k] = n;// *wk = n;\r
135                                                                         }\r
136                                                                 }\r
137                                                                 label_pixel = n;// *pnt2 = n;\r
138                                                         } else if (label_pixel < n) {\r
139                                                                 for (k = 0; k < wk_max; k++) {\r
140                                                                         if (label_idxtbl[k] == n) {// if( *wk == n ){\r
141                                                                                 label_idxtbl[k] = label_pixel;// *wk = m;\r
142                                                                         }\r
143                                                                 }\r
144                                                         }\r
145                                                         work2_pt = work2[label_pixel - 1];\r
146                                                         work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;\r
147                                                         work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;\r
148                                                         work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;\r
149                                                 } else {\r
150 \r
151                                                         label_pixel = label_img[label_img_ptr1 + 1];// label_pixel = label_img_pt1[i + 1];// *pnt2 =\r
152                                                         // *(pnt1+1);\r
153 \r
154                                                         work2_pt = work2[label_pixel - 1];\r
155                                                         work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;\r
156                                                         work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;\r
157                                                         work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;\r
158                                                         if (work2_pt[3] > i) {// if(work2[((*pnt2)-1)*7+3] > i ){\r
159                                                                 work2_pt[3] = i;// work2[((*pnt2)-1)*7+3] = i;\r
160                                                         }\r
161                                                         work2_pt[6] = j;// work2[((*pnt2)-1)*7+6] = j;\r
162                                                 }\r
163                                         } else if ((label_img[label_img_ptr1 - 1]) > 0) {// } else if ((label_img_pt1[i - 1]) > 0) {// }else if(\r
164                                                 // *(pnt1-1) > 0 ) {\r
165                                                 label_pixel = label_img[label_img_ptr1 - 1];// label_pixel = label_img_pt1[i - 1];// *pnt2 =\r
166                                                 // *(pnt1-1);\r
167 \r
168                                                 work2_pt = work2[label_pixel - 1];\r
169                                                 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;\r
170                                                 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;\r
171                                                 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;\r
172                                                 if (work2_pt[4] < i) {// if( work2[((*pnt2)-1)*7+4] <i ){\r
173                                                         work2_pt[4] = i;// work2[((*pnt2)-1)*7+4] = i;\r
174                                                 }\r
175                                                 work2_pt[6] = j;// work2[((*pnt2)-1)*7+6] = j;\r
176                                         } else if (label_img[pixel_index - 1] > 0) {// } else if (label_img_pt0[i - 1] > 0) {// }else if(*(pnt2-1) > 0) {\r
177                                                 label_pixel = label_img[pixel_index - 1];// label_pixel = label_img_pt0[i - 1];// *pnt2 =*(pnt2-1);\r
178 \r
179                                                 work2_pt = work2[label_pixel - 1];\r
180                                                 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;\r
181                                                 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;\r
182                                                 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;\r
183                                                 if (work2_pt[4] < i) {// if( work2[((*pnt2)-1)*7+4] <i ){\r
184                                                         work2_pt[4] = i;// work2[((*pnt2)-1)*7+4] = i;\r
185                                                 }\r
186                                         } else {\r
187                                                 // 現在地までの領域を予約\r
188                                                 this.work_holder.reserv(wk_max);\r
189                                                 wk_max++;\r
190                                                 label_idxtbl[wk_max - 1] = wk_max;\r
191                                                 label_pixel = wk_max;// work[wk_max-1] = *pnt2 = wk_max;\r
192                                                 work2_pt = work2[wk_max - 1];\r
193                                                 work2_pt[0] = 1;\r
194                                                 work2_pt[1] = i;\r
195                                                 work2_pt[2] = j;\r
196                                                 work2_pt[3] = i;\r
197                                                 work2_pt[4] = i;\r
198                                                 work2_pt[5] = j;\r
199                                                 work2_pt[6] = j;\r
200                                         }\r
201                                         label_img[pixel_index] = label_pixel;// label_img_pt0[i] = label_pixel;\r
202                                 }\r
203                         }\r
204 \r
205                 }\r
206                 // インデックステーブルとラベル数の計算\r
207                 int wlabel_num = 1;// *label_num = *wlabel_num = j - 1;\r
208 \r
209                 for (i = 0; i < wk_max; i++) {// for(int i = 1; i <= wk_max; i++,wk++) {\r
210                         label_idxtbl[i] = (label_idxtbl[i] == i + 1) ? wlabel_num++ : label_idxtbl[label_idxtbl[i] - 1];// *wk=(*wk==i)?j++:work[(*wk)-1];\r
211                 }\r
212                 wlabel_num -= 1;// *label_num = *wlabel_num = j - 1;\r
213                 if (wlabel_num == 0) {// if( *label_num == 0 ) {\r
214                         // 発見数0\r
215                         o_destination.getLabelStack().clear();\r
216                         return 0;\r
217                 }\r
218                 // ラベル情報の保存等\r
219                 NyARLabelingLabelStack label_list = o_destination.getLabelStack();\r
220 \r
221                 // ラベルバッファを予約\r
222                 label_list.init(wlabel_num);\r
223 \r
224                 // エリアと重心、クリップ領域を計算\r
225                 NyARLabelingLabel label_pt;\r
226                 NyARLabelingLabel[] labels =label_list.getArray();\r
227                 for (i = 0; i < wlabel_num; i++) {\r
228                         label_pt = labels[i];\r
229                         label_pt.id = (short)(i + 1);\r
230                         label_pt.area = 0;\r
231                         label_pt.pos_x = label_pt.pos_y = 0;\r
232                         label_pt.clip_l = lxsize;// wclip[i*4+0] = lxsize;\r
233                         label_pt.clip_t = lysize;// wclip[i*4+2] = lysize;\r
234                         label_pt.clip_r = label_pt.clip_b = 0;// wclip[i*4+3] = 0;\r
235                 }\r
236 \r
237                 for (i = 0; i < wk_max; i++) {\r
238                         label_pt = labels[label_idxtbl[i] - 1];\r
239                         work2_pt = work2[i];\r
240                         label_pt.area += work2_pt[0];\r
241                         label_pt.pos_x += work2_pt[1];\r
242                         label_pt.pos_y += work2_pt[2];\r
243                         if (label_pt.clip_l > work2_pt[3]) {\r
244                                 label_pt.clip_l = work2_pt[3];\r
245                         }\r
246                         if (label_pt.clip_r < work2_pt[4]) {\r
247                                 label_pt.clip_r = work2_pt[4];\r
248                         }\r
249                         if (label_pt.clip_t > work2_pt[5]) {\r
250                                 label_pt.clip_t = work2_pt[5];\r
251                         }\r
252                         if (label_pt.clip_b < work2_pt[6]) {\r
253                                 label_pt.clip_b = work2_pt[6];\r
254                         }\r
255                 }\r
256 \r
257                 for (i = 0; i < wlabel_num; i++) {// for(int i = 0; i < *label_num; i++ ) {\r
258                         label_pt = labels[i];\r
259                         label_pt.pos_x /= label_pt.area;\r
260                         label_pt.pos_y /= label_pt.area;\r
261                 }               \r
262                 return wlabel_num;\r
263         }\r
264 \r
265 }\r
266 \r
267 /**\r
268  * NyARLabeling_O2のworkとwork2を可変長にするためのクラス\r
269  * \r
270  * \r
271  */\r
272 final class NyARWorkHolder\r
273 {\r
274         private final static int ARRAY_APPEND_STEP = 256;\r
275 \r
276         public final int[][] work2;\r
277 \r
278         private int allocate_size;\r
279 \r
280         /**\r
281          * 最大i_holder_size個の動的割り当てバッファを準備する。\r
282          * \r
283          * @param i_holder_size\r
284          */\r
285         public NyARWorkHolder(int i_holder_size)\r
286         {\r
287                 // ポインタだけははじめに確保しておく\r
288                 this.work2 = new int[i_holder_size][];\r
289                 this.allocate_size = 0;\r
290         }\r
291 \r
292         /**\r
293          * i_indexで指定した番号までのバッファを準備する。\r
294          * \r
295          * @param i_index\r
296          */\r
297         public final void reserv(int i_index) throws NyARException\r
298         {\r
299                 // アロケート済みなら即リターン\r
300                 if (this.allocate_size > i_index) {\r
301                         return;\r
302                 }\r
303                 // 要求されたインデクスは範囲外\r
304                 if (i_index >= this.work2.length) {\r
305                         throw new NyARException();\r
306                 }\r
307                 // 追加アロケート範囲を計算\r
308                 int range = i_index + ARRAY_APPEND_STEP;\r
309                 if (range >= this.work2.length) {\r
310                         range = this.work2.length;\r
311                 }\r
312                 // アロケート\r
313                 for (int i = this.allocate_size; i < range; i++) {\r
314                         this.work2[i] = new int[7];\r
315                 }\r
316                 this.allocate_size = range;\r
317         }\r
318 }\r