2 * PROJECT: NyARToolkit
\r
3 * --------------------------------------------------------------------------------
\r
4 * This work is based on the original ARToolKit developed by
\r
7 * HITLab, University of Washington, Seattle
\r
8 * http://www.hitl.washington.edu/artoolkit/
\r
10 * The NyARToolkit is Java version ARToolkit class library.
\r
11 * Copyright (C)2008 R.Iizuka
\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
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
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
27 * For further information please contact.
\r
28 * http://nyatla.jp/nyatoolkit/
\r
29 * <airmail(at)ebony.plala.or.jp>
\r
32 package jp.nyatla.nyartoolkit.toys.x2;
\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
40 * 計算部から浮動小数点計算を除外したNyARLabeling_ARToolKit
\r
41 * NyARLabeling_ARToolKitと同じ処理をするけど、エリア計算にintを使う。
\r
42 * 画面サイズが1600x1600を超えると挙動が怪しくなる。
\r
45 public class NyARLabeling_ARToolKit_X2 implements INyARLabeling
\r
47 private static final int WORK_SIZE = 1024 * 32;// #define WORK_SIZE 1024*32
\r
49 private final NyARWorkHolder work_holder = new NyARWorkHolder(WORK_SIZE);
\r
51 private NyARIntSize _dest_size;
\r
53 private INyARLabelingImage _out_image;
\r
55 public void attachDestination(INyARLabelingImage i_destination_image) throws NyARException
\r
58 NyARIntSize size = i_destination_image.getSize();
\r
59 this._out_image = i_destination_image;
\r
61 // NyLabelingImageのイメージ初期化(枠書き)
\r
62 int[][] img = (int[][]) i_destination_image.getBufferReader().getBuffer();
\r
63 for (int i = 0; i < size.w; i++) {
\r
65 img[size.h - 1][i] = 0;
\r
67 for (int i = 0; i < size.h; i++) {
\r
69 img[i][size.w - 1] = 0;
\r
73 this._dest_size = size;
\r
76 public INyARLabelingImage getAttachedDestination()
\r
78 return this._out_image;
\r
82 * static ARInt16 *labeling2( ARUint8 *image, int thresh,int *label_num, int **area, double **pos, int **clip,int **label_ref, int LorR ) 関数の代替品
\r
83 * ラスタimageをラベリングして、結果を保存します。 Optimize:STEP[1514->1493]
\r
86 * @throws NyARException
\r
88 public void labeling(NyARBinRaster i_raster) throws NyARException
\r
90 int m, n; /* work */
\r
92 INyARLabelingImage out_image = this._out_image;
\r
95 NyARIntSize in_size = i_raster.getSize();
\r
96 this._dest_size.isEqualSize(in_size);
\r
98 final int lxsize = in_size.w;// lxsize = arUtil_c.arImXsize;
\r
99 final int lysize = in_size.h;// lysize = arUtil_c.arImYsize;
\r
100 int[][] label_img = (int[][]) out_image.getBufferReader().getBuffer();
\r
102 // 枠作成はインスタンスを作った直後にやってしまう。
\r
104 // ラベリング情報のリセット(ラベリングインデックスを使用)
\r
105 out_image.reset(true);
\r
107 int[] label_idxtbl = out_image.getIndexArray();
\r
113 int[][] raster_buf = (int[][]) i_raster.getBufferReader().getBuffer();
\r
115 int[][] work2 = this.work_holder.work2;
\r
116 int[] label_img_pt0, label_img_pt1;
\r
117 for (j = 1; j < lysize - 1; j++) {// for (int j = 1; j < lysize - 1;j++, pnt += poff*2, pnt2 += 2) {
\r
118 line_ptr = raster_buf[j];
\r
119 label_img_pt0 = label_img[j];
\r
120 label_img_pt1 = label_img[j - 1];
\r
121 for (i = 1; i < lxsize - 1; i++) {// for(int i = 1; i < lxsize-1;i++, pnt+=poff, pnt2++) {
\r
122 // RGBの合計値が閾値より小さいかな?
\r
123 if (line_ptr[i] == 0) {
\r
124 // pnt1 = ShortPointer.wrap(pnt2, -lxsize);//pnt1 =&(pnt2[-lxsize]);
\r
125 if (label_img_pt1[i] > 0) {// if( *pnt1 > 0 ) {
\r
126 label_pixel = label_img_pt1[i];// *pnt2 = *pnt1;
\r
128 work2_pt = work2[label_pixel - 1];
\r
129 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;
\r
130 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;
\r
131 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;
\r
132 work2_pt[6] = j;// work2[((*pnt2)-1)*7+6] = j;
\r
133 } else if (label_img_pt1[i + 1] > 0) {// }else if(*(pnt1+1) > 0 ) {
\r
134 if (label_img_pt1[i - 1] > 0) {// if( *(pnt1-1) > 0 ) {
\r
135 m = label_idxtbl[label_img_pt1[i + 1] - 1];// m =work[*(pnt1+1)-1];
\r
136 n = label_idxtbl[label_img_pt1[i - 1] - 1];// n =work[*(pnt1-1)-1];
\r
138 label_pixel = n;// *pnt2 = n;
\r
139 // wk=IntPointer.wrap(work, 0);//wk =
\r
141 for (k = 0; k < wk_max; k++) {
\r
142 if (label_idxtbl[k] == m) {// if( *wk == m )
\r
143 label_idxtbl[k] = n;// *wk = n;
\r
146 } else if (m < n) {
\r
147 label_pixel = m;// *pnt2 = m;
\r
148 // wk=IntPointer.wrap(work,0);//wk = &(work[0]);
\r
149 for (k = 0; k < wk_max; k++) {
\r
150 if (label_idxtbl[k] == n) {// if( *wk == n ){
\r
151 label_idxtbl[k] = m;// *wk = m;
\r
155 label_pixel = m;// *pnt2 = m;
\r
157 work2_pt = work2[label_pixel - 1];
\r
162 } else if ((label_img_pt0[i - 1]) > 0) {// }else if(*(pnt2-1) > 0) {
\r
163 m = label_idxtbl[(label_img_pt1[i + 1]) - 1];// m =work[*(pnt1+1)-1];
\r
164 n = label_idxtbl[label_img_pt0[i - 1] - 1];// n =work[*(pnt2-1)-1];
\r
167 label_pixel = n;// *pnt2 = n;
\r
168 for (k = 0; k < wk_max; k++) {
\r
169 if (label_idxtbl[k] == m) {// if( *wk == m ){
\r
170 label_idxtbl[k] = n;// *wk = n;
\r
173 } else if (m < n) {
\r
174 label_pixel = m;// *pnt2 = m;
\r
175 for (k = 0; k < wk_max; k++) {
\r
176 if (label_idxtbl[k] == n) {// if( *wk == n ){
\r
177 label_idxtbl[k] = m;// *wk = m;
\r
181 label_pixel = m;// *pnt2 = m;
\r
183 work2_pt = work2[label_pixel - 1];
\r
184 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;
\r
185 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;
\r
186 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;
\r
189 label_pixel = label_img_pt1[i + 1];// *pnt2 =
\r
192 work2_pt = work2[label_pixel - 1];
\r
193 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;
\r
194 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;
\r
195 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;
\r
196 if (work2_pt[3] > i) {// if(
\r
197 // work2[((*pnt2)-1)*7+3] >
\r
199 work2_pt[3] = i;// work2[((*pnt2)-1)*7+3] = i;
\r
201 work2_pt[6] = j;// work2[((*pnt2)-1)*7+6] = j;
\r
203 } else if ((label_img_pt1[i - 1]) > 0) {// }else if(
\r
204 // *(pnt1-1) > 0 ) {
\r
205 label_pixel = label_img_pt1[i - 1];// *pnt2 =
\r
208 work2_pt = work2[label_pixel - 1];
\r
209 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;
\r
210 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;
\r
211 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;
\r
212 if (work2_pt[4] < i) {// if( work2[((*pnt2)-1)*7+4] <i ){
\r
213 work2_pt[4] = i;// work2[((*pnt2)-1)*7+4] = i;
\r
215 work2_pt[6] = j;// work2[((*pnt2)-1)*7+6] = j;
\r
216 } else if (label_img_pt0[i - 1] > 0) {// }else if(*(pnt2-1) > 0) {
\r
217 label_pixel = label_img_pt0[i - 1];// *pnt2 =*(pnt2-1);
\r
219 work2_pt = work2[label_pixel - 1];
\r
220 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;
\r
221 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;
\r
222 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;
\r
223 if (work2_pt[4] < i) {// if( work2[((*pnt2)-1)*7+4] <i ){
\r
224 work2_pt[4] = i;// work2[((*pnt2)-1)*7+4] = i;
\r
228 this.work_holder.reserv(wk_max);
\r
230 label_idxtbl[wk_max - 1] = wk_max;
\r
231 label_pixel = wk_max;// work[wk_max-1] = *pnt2 = wk_max;
\r
232 work2_pt = work2[wk_max - 1];
\r
241 label_img_pt0[i] = label_pixel;
\r
243 label_img_pt0[i] = 0;// *pnt2 = 0;
\r
247 // インデックステーブルとラベル数の計算
\r
248 int wlabel_num = 1;// *label_num = *wlabel_num = j - 1;
\r
250 for (i = 0; i < wk_max; i++) {// for(int i = 1; i <= wk_max; i++,wk++) {
\r
251 label_idxtbl[i] = (label_idxtbl[i] == i + 1) ? wlabel_num++ : label_idxtbl[label_idxtbl[i] - 1];// *wk=(*wk==i)?j++:work[(*wk)-1];
\r
253 wlabel_num -= 1;// *label_num = *wlabel_num = j - 1;
\r
254 if (wlabel_num == 0) {// if( *label_num == 0 ) {
\r
256 out_image.getLabelStack().clear();
\r
260 updateLabelStackLarge(out_image.getLabelStack(), label_idxtbl, in_size, work2, wk_max, wlabel_num);
\r
264 private int[][] __updateLabelStackLarge_temp=new int[64][7];/*area,x,y,l,r,t,b*/
\r
266 /* 構造が変わるから、ハイスピード版実装するときに使う。 */
\r
267 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
270 int[][] temp=this.__updateLabelStackLarge_temp;
\r
271 if(temp.length<i_number_of_label){
\r
272 temp=new int[i_number_of_label+64][7];
\r
273 this.__updateLabelStackLarge_temp=temp;
\r
277 i_stack.reserv(i_number_of_label);
\r
278 // エリアと重心、クリップ領域を計算
\r
279 final NyARLabelingLabel[] labels = (NyARLabelingLabel[])i_stack.getArray();
\r
280 for (int i = 0; i < i_number_of_label; i++) {
\r
281 final int[] temp_ptr = temp[i];
\r
282 temp_ptr[0]=0;//area
\r
285 temp_ptr[3]=i_size.w;//l
\r
287 temp_ptr[5]=i_size.h;//t
\r
292 for (int i = 0; i < i_work_max; i++) {
\r
293 final int temp_ptr[] = temp[i_lindex[i] - 1];
\r
294 final int[] work2_pt = i_work[i];
\r
295 temp_ptr[0] += work2_pt[0];
\r
296 temp_ptr[1] += work2_pt[1];
\r
297 temp_ptr[2] += work2_pt[2];
\r
298 if (temp_ptr[3] > work2_pt[3]) {
\r
299 temp_ptr[3] = work2_pt[3];
\r
301 if (temp_ptr[4] < work2_pt[4]) {
\r
302 temp_ptr[4] = work2_pt[4];
\r
304 if (temp_ptr[5] > work2_pt[5]) {
\r
305 temp_ptr[5] = work2_pt[5];
\r
307 if (temp_ptr[6] < work2_pt[6]) {
\r
308 temp_ptr[6] = work2_pt[6];
\r
312 for (int i = 0; i < i_number_of_label; i++) {// for(int i = 0; i < *label_num; i++ ) {
\r
313 final NyARLabelingLabel label_pt = labels[i];
\r
314 final int temp_ptr[] = temp[i];
\r
316 label_pt.area=temp_ptr[0];
\r
317 label_pt.pos_x= (double)temp_ptr[1]/label_pt.area;
\r
318 label_pt.pos_y= (double)temp_ptr[2]/label_pt.area;
\r
319 label_pt.clip_l= temp_ptr[3];
\r
320 label_pt.clip_r= temp_ptr[4];
\r
321 label_pt.clip_t= temp_ptr[5];
\r
322 label_pt.clip_b= temp_ptr[6];
\r
329 * NyARLabeling_O2のworkとwork2を可変長にするためのクラス
\r
333 final class NyARWorkHolder
\r
335 private final static int ARRAY_APPEND_STEP = 256;
\r
337 public final int[] work;
\r
339 public final int[][] work2;
\r
341 private int allocate_size;
\r
344 * 最大i_holder_size個の動的割り当てバッファを準備する。
\r
346 * @param i_holder_size
\r
348 public NyARWorkHolder(int i_holder_size)
\r
350 // ポインタだけははじめに確保しておく
\r
351 this.work = new int[i_holder_size];
\r
352 this.work2 = new int[i_holder_size][];
\r
353 this.allocate_size = 0;
\r
357 * i_indexで指定した番号までのバッファを準備する。
\r
361 public final void reserv(int i_index) throws NyARException
\r
364 if (this.allocate_size > i_index) {
\r
368 if (i_index >= this.work.length) {
\r
369 throw new NyARException();
\r
372 int range = i_index + ARRAY_APPEND_STEP;
\r
373 if (range >= this.work.length) {
\r
374 range = this.work.length;
\r
377 for (int i = this.allocate_size; i < range; i++) {
\r
378 this.work2[i] = new int[8];
\r
380 this.allocate_size = range;
\r