OSDN Git Service

e0059d2744797729680422f3042fdd16fea606c6
[nyartoolkit-and/nyartoolkit-and.git] / 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\r
14  * modify it under the terms of the GNU Lesser General Public License\r
15  * as published by the Free Software Foundation; either version 3\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 Lesser General Public License for more details\r
22  * \r
23  * You should have received a copy of the GNU Lesser General Public\r
24  * License 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                 int label_img_ptr1, label_pixel;\r
58                 int i, j;\r
59                 int n, k; /* work */\r
60                 \r
61                 // サイズチェック\r
62                 NyARIntSize in_size = i_raster.getSize();\r
63                 assert(o_destination.getSize().isEqualSize(in_size));\r
64 \r
65                 final int lxsize = in_size.w;// lxsize = arUtil_c.arImXsize;\r
66                 final int lysize = in_size.h;// lysize = arUtil_c.arImYsize;\r
67                 final int[] label_img = (int[]) o_destination.getBufferReader().getBuffer();\r
68 \r
69                 // 枠作成はインスタンスを作った直後にやってしまう。\r
70 \r
71                 // ラベリング情報のリセット(ラベリングインデックスを使用)\r
72                 o_destination.reset(true);\r
73 \r
74                 int[] label_idxtbl = o_destination.getIndexArray();\r
75                 int[] raster_buf = (int[]) i_raster.getBufferReader().getBuffer();\r
76 \r
77                 int[] work2_pt;\r
78                 int wk_max = 0;\r
79 \r
80                 int pixel_index;\r
81                 int[][] work2 = this.work_holder.work2;\r
82 \r
83                 // [1,1](ptr0)と、[0,1](ptr1)のインデクス値を計算する。\r
84                 for (j = 1; j < lysize - 1; j++) {// for (int j = 1; j < lysize - 1;j++, pnt += poff*2, pnt2 += 2) {\r
85                         pixel_index = j * lxsize + 1;\r
86                         label_img_ptr1 = pixel_index - lxsize;// label_img_pt1 = label_img[j - 1];\r
87                         for (i = 1; i < lxsize - 1; i++, pixel_index++, label_img_ptr1++) {// for(int i = 1; i < lxsize-1;i++, pnt+=poff, pnt2++) {\r
88                                 // RGBの合計値が閾値より小さいかな?\r
89                                 if (raster_buf[pixel_index] != 0) {\r
90                                         label_img[pixel_index] = 0;// label_img_pt0[i] = 0;// *pnt2 = 0;\r
91                                 } else {\r
92                                         // pnt1 = ShortPointer.wrap(pnt2, -lxsize);//pnt1 =&(pnt2[-lxsize]);\r
93                                         if (label_img[label_img_ptr1] > 0) {// if (label_img_pt1[i] > 0) {// if( *pnt1 > 0 ) {\r
94                                                 label_pixel = label_img[label_img_ptr1];// label_pixel = label_img_pt1[i];// *pnt2 = *pnt1;\r
95 \r
96                                                 work2_pt = work2[label_pixel - 1];\r
97                                                 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;\r
98                                                 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;\r
99                                                 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;\r
100                                                 work2_pt[6] = j;// work2[((*pnt2)-1)*7+6] = j;\r
101                                         } else if (label_img[label_img_ptr1 + 1] > 0) {// } else if (label_img_pt1[i + 1] > 0) {// }else if(*(pnt1+1) > 0 ) {\r
102                                                 if (label_img[label_img_ptr1 - 1] > 0) {// if (label_img_pt1[i - 1] > 0) {// if( *(pnt1-1) > 0 ) {\r
103                                                         label_pixel = label_idxtbl[label_img[label_img_ptr1 + 1] - 1];// m = label_idxtbl[label_img_pt1[i + 1] - 1];// m\r
104                                                                                                                                                                                         // =work[*(pnt1+1)-1];\r
105                                                         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
106                                                         if (label_pixel > n) {\r
107                                                                 // wk=IntPointer.wrap(work, 0);//wk = &(work[0]);\r
108                                                                 for (k = 0; k < wk_max; k++) {\r
109                                                                         if (label_idxtbl[k] == label_pixel) {// if( *wk == m )\r
110                                                                                 label_idxtbl[k] = n;// *wk = n;\r
111                                                                         }\r
112                                                                 }\r
113                                                                 label_pixel = n;// *pnt2 = n;\r
114                                                         } else if (label_pixel < n) {\r
115                                                                 // wk=IntPointer.wrap(work,0);//wk = &(work[0]);\r
116                                                                 for (k = 0; k < wk_max; k++) {\r
117                                                                         if (label_idxtbl[k] == n) {// if( *wk == n ){\r
118                                                                                 label_idxtbl[k] = label_pixel;// *wk = m;\r
119                                                                         }\r
120                                                                 }\r
121                                                         }\r
122                                                         work2_pt = work2[label_pixel - 1];\r
123                                                         work2_pt[0]++;\r
124                                                         work2_pt[1] += i;\r
125                                                         work2_pt[2] += j;\r
126                                                         work2_pt[6] = j;\r
127                                                 } else if ((label_img[pixel_index - 1]) > 0) {// } else if ((label_img_pt0[i - 1]) > 0) {// }else if(*(pnt2-1) > 0) {\r
128                                                         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
129                                                         n = label_idxtbl[label_img[pixel_index - 1] - 1];// n = label_idxtbl[label_img_pt0[i - 1] - 1];// n =work[*(pnt2-1)-1];\r
130                                                         if (label_pixel > n) {\r
131                                                                 for (k = 0; k < wk_max; k++) {\r
132                                                                         if (label_idxtbl[k] == label_pixel) {// if( *wk == m ){\r
133                                                                                 label_idxtbl[k] = n;// *wk = n;\r
134                                                                         }\r
135                                                                 }\r
136                                                                 label_pixel = n;// *pnt2 = n;\r
137                                                         } else if (label_pixel < n) {\r
138                                                                 for (k = 0; k < wk_max; k++) {\r
139                                                                         if (label_idxtbl[k] == n) {// if( *wk == n ){\r
140                                                                                 label_idxtbl[k] = label_pixel;// *wk = m;\r
141                                                                         }\r
142                                                                 }\r
143                                                         }\r
144                                                         work2_pt = work2[label_pixel - 1];\r
145                                                         work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;\r
146                                                         work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;\r
147                                                         work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;\r
148                                                 } else {\r
149 \r
150                                                         label_pixel = label_img[label_img_ptr1 + 1];// label_pixel = label_img_pt1[i + 1];// *pnt2 =\r
151                                                         // *(pnt1+1);\r
152 \r
153                                                         work2_pt = work2[label_pixel - 1];\r
154                                                         work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;\r
155                                                         work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;\r
156                                                         work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;\r
157                                                         if (work2_pt[3] > i) {// if(work2[((*pnt2)-1)*7+3] > i ){\r
158                                                                 work2_pt[3] = i;// work2[((*pnt2)-1)*7+3] = i;\r
159                                                         }\r
160                                                         work2_pt[6] = j;// work2[((*pnt2)-1)*7+6] = j;\r
161                                                 }\r
162                                         } else if ((label_img[label_img_ptr1 - 1]) > 0) {// } else if ((label_img_pt1[i - 1]) > 0) {// }else if(\r
163                                                 // *(pnt1-1) > 0 ) {\r
164                                                 label_pixel = label_img[label_img_ptr1 - 1];// label_pixel = label_img_pt1[i - 1];// *pnt2 =\r
165                                                 // *(pnt1-1);\r
166 \r
167                                                 work2_pt = work2[label_pixel - 1];\r
168                                                 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;\r
169                                                 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;\r
170                                                 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;\r
171                                                 if (work2_pt[4] < i) {// if( work2[((*pnt2)-1)*7+4] <i ){\r
172                                                         work2_pt[4] = i;// work2[((*pnt2)-1)*7+4] = i;\r
173                                                 }\r
174                                                 work2_pt[6] = j;// work2[((*pnt2)-1)*7+6] = j;\r
175                                         } else if (label_img[pixel_index - 1] > 0) {// } else if (label_img_pt0[i - 1] > 0) {// }else if(*(pnt2-1) > 0) {\r
176                                                 label_pixel = label_img[pixel_index - 1];// label_pixel = label_img_pt0[i - 1];// *pnt2 =*(pnt2-1);\r
177 \r
178                                                 work2_pt = work2[label_pixel - 1];\r
179                                                 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;\r
180                                                 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;\r
181                                                 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;\r
182                                                 if (work2_pt[4] < i) {// if( work2[((*pnt2)-1)*7+4] <i ){\r
183                                                         work2_pt[4] = i;// work2[((*pnt2)-1)*7+4] = i;\r
184                                                 }\r
185                                         } else {\r
186                                                 // 現在地までの領域を予約\r
187                                                 this.work_holder.reserv(wk_max);\r
188                                                 wk_max++;\r
189                                                 label_idxtbl[wk_max - 1] = wk_max;\r
190                                                 label_pixel = wk_max;// work[wk_max-1] = *pnt2 = wk_max;\r
191                                                 work2_pt = work2[wk_max - 1];\r
192                                                 work2_pt[0] = 1;\r
193                                                 work2_pt[1] = i;\r
194                                                 work2_pt[2] = j;\r
195                                                 work2_pt[3] = i;\r
196                                                 work2_pt[4] = i;\r
197                                                 work2_pt[5] = j;\r
198                                                 work2_pt[6] = j;\r
199                                         }\r
200                                         label_img[pixel_index] = label_pixel;// label_img_pt0[i] = label_pixel;\r
201                                 }\r
202                         }\r
203 \r
204                 }\r
205                 // インデックステーブルとラベル数の計算\r
206                 int wlabel_num = 1;// *label_num = *wlabel_num = j - 1;\r
207 \r
208                 for (i = 0; i < wk_max; i++) {// for(int i = 1; i <= wk_max; i++,wk++) {\r
209                         label_idxtbl[i] = (label_idxtbl[i] == i + 1) ? wlabel_num++ : label_idxtbl[label_idxtbl[i] - 1];// *wk=(*wk==i)?j++:work[(*wk)-1];\r
210                 }\r
211                 wlabel_num -= 1;// *label_num = *wlabel_num = j - 1;\r
212                 if (wlabel_num == 0) {// if( *label_num == 0 ) {\r
213                         // 発見数0\r
214                         o_destination.getLabelStack().clear();\r
215                         return 0;\r
216                 }\r
217                 // ラベル情報の保存等\r
218                 NyARLabelingLabelStack label_list = o_destination.getLabelStack();\r
219 \r
220                 // ラベルバッファを予約\r
221                 label_list.reserv(wlabel_num);\r
222 \r
223                 // エリアと重心、クリップ領域を計算\r
224                 NyARLabelingLabel label_pt;\r
225                 NyARLabelingLabel[] labels =label_list.getArray();\r
226                 for (i = 0; i < wlabel_num; i++) {\r
227                         label_pt = labels[i];\r
228                         label_pt.id = (short)(i + 1);\r
229                         label_pt.area = 0;\r
230                         label_pt.pos_x = label_pt.pos_y = 0;\r
231                         label_pt.clip_l = lxsize;// wclip[i*4+0] = lxsize;\r
232                         label_pt.clip_t = lysize;// wclip[i*4+2] = lysize;\r
233                         label_pt.clip_r = label_pt.clip_b = 0;// wclip[i*4+3] = 0;\r
234                 }\r
235 \r
236                 for (i = 0; i < wk_max; i++) {\r
237                         label_pt = labels[label_idxtbl[i] - 1];\r
238                         work2_pt = work2[i];\r
239                         label_pt.area += work2_pt[0];\r
240                         label_pt.pos_x += work2_pt[1];\r
241                         label_pt.pos_y += work2_pt[2];\r
242                         if (label_pt.clip_l > work2_pt[3]) {\r
243                                 label_pt.clip_l = work2_pt[3];\r
244                         }\r
245                         if (label_pt.clip_r < work2_pt[4]) {\r
246                                 label_pt.clip_r = work2_pt[4];\r
247                         }\r
248                         if (label_pt.clip_t > work2_pt[5]) {\r
249                                 label_pt.clip_t = work2_pt[5];\r
250                         }\r
251                         if (label_pt.clip_b < work2_pt[6]) {\r
252                                 label_pt.clip_b = work2_pt[6];\r
253                         }\r
254                 }\r
255 \r
256                 for (i = 0; i < wlabel_num; i++) {// for(int i = 0; i < *label_num; i++ ) {\r
257                         label_pt = labels[i];\r
258                         label_pt.pos_x /= label_pt.area;\r
259                         label_pt.pos_y /= label_pt.area;\r
260                 }               \r
261                 return wlabel_num;\r
262         }\r
263 \r
264 }\r
265 \r
266 /**\r
267  * NyARLabeling_O2のworkとwork2を可変長にするためのクラス\r
268  * \r
269  * \r
270  */\r
271 final class NyARWorkHolder\r
272 {\r
273         private final static int ARRAY_APPEND_STEP = 256;\r
274 \r
275         public final int[][] work2;\r
276 \r
277         private int allocate_size;\r
278 \r
279         /**\r
280          * 最大i_holder_size個の動的割り当てバッファを準備する。\r
281          * \r
282          * @param i_holder_size\r
283          */\r
284         public NyARWorkHolder(int i_holder_size)\r
285         {\r
286                 // ポインタだけははじめに確保しておく\r
287                 this.work2 = new int[i_holder_size][];\r
288                 this.allocate_size = 0;\r
289         }\r
290 \r
291         /**\r
292          * i_indexで指定した番号までのバッファを準備する。\r
293          * \r
294          * @param i_index\r
295          */\r
296         public final void reserv(int i_index) throws NyARException\r
297         {\r
298                 // アロケート済みなら即リターン\r
299                 if (this.allocate_size > i_index) {\r
300                         return;\r
301                 }\r
302                 // 要求されたインデクスは範囲外\r
303                 if (i_index >= this.work2.length) {\r
304                         throw new NyARException();\r
305                 }\r
306                 // 追加アロケート範囲を計算\r
307                 int range = i_index + ARRAY_APPEND_STEP;\r
308                 if (range >= this.work2.length) {\r
309                         range = this.work2.length;\r
310                 }\r
311                 // アロケート\r
312                 for (int i = this.allocate_size; i < range; i++) {\r
313                         this.work2[i] = new int[7];\r
314                 }\r
315                 this.allocate_size = range;\r
316         }\r
317 }\r