OSDN Git Service

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