Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
203 chris 1
/*
2
 * PROJECT: NyARToolkit
3
 * --------------------------------------------------------------------------------
4
 * This work is based on the original ARToolKit developed by
5
 *   Hirokazu Kato
6
 *   Mark Billinghurst
7
 *   HITLab, University of Washington, Seattle
8
 * http://www.hitl.washington.edu/artoolkit/
9
 *
10
 * The NyARToolkit is Java version ARToolkit class library.
11
 * Copyright (C)2008 R.Iizuka
12
 *
13
 * This program is free software; you can redistribute it and/or
14
 * modify it under the terms of the GNU General Public License
15
 * as published by the Free Software Foundation; either version 2
16
 * of the License, or (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this framework; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
 *
27
 * For further information please contact.
28
 *      http://nyatla.jp/nyatoolkit/
29
 *      <airmail(at)ebony.plala.or.jp>
30
 *
31
 */
32
package jp.nyatla.nyartoolkit.core;
33
 
34
import jp.nyatla.nyartoolkit.NyARException;
35
import jp.nyatla.nyartoolkit.core.raster.*;
36
 
37
 
38
interface NyARLabeling{
39
    /**
40
     * 検出したラベルの数を返す
41
     * @return
42
     */
43
    public int getLabelNum();
44
    /**
45
     *
46
     * @return
47
     * @throws NyARException
48
     */
49
    public int[] getLabelRef() throws NyARException;
50
    /**
51
     * 検出したラベル配列
52
     * @return
53
     * @throws NyARException
54
     */
55
    public NyARLabel[] getLabel() throws NyARException;
56
    /**
57
     * ラベリング済みイメージを返す
58
     * @return
59
     * @throws NyARException
60
     */
61
    public int[][] getLabelImg() throws NyARException;
62
    /**
63
     * static ARInt16 *labeling2( ARUint8 *image, int thresh,int *label_num, int **area, double **pos, int **clip,int **label_ref, int LorR )
64
     * 関数の代替品
65
     * ラスタimageをラベリングして、結果を保存します。
66
     * Optimize:STEP[1514->1493]
67
     * @param image
68
     * @param thresh
69
     * @throws NyARException
70
     */
71
    public void labeling(NyARRaster image,int thresh) throws NyARException;
72
}
73
 
74
 
75
 
76
 
77
/**
78
 * NyARLabeling_O2のworkとwork2を可変長にするためのクラス
79
 *
80
 *
81
 */
82
class NyARWorkHolder
83
{
84
    private final static int ARRAY_APPEND_STEP=256;
85
    public final int[] work;
86
    public final int[][] work2;
87
    private int allocate_size;
88
    /**
89
     * 最大i_holder_size個の動的割り当てバッファを準備する。
90
     * @param i_holder_size
91
     */
92
    public NyARWorkHolder(int i_holder_size)
93
    {
94
        //ポインタだけははじめに確保しておく
95
        this.work=new int[i_holder_size];
96
        this.work2=new int[i_holder_size][];
97
        this.allocate_size=0;
98
    }
99
    /**
100
     * i_indexで指定した番号までのバッファを準備する。
101
     * @param i_index
102
     */
103
    public final void reserv(int i_index) throws NyARException
104
    {
105
        //アロケート済みなら即リターン
106
        if(this.allocate_size>i_index){
107
            return;
108
        }
109
        //要求されたインデクスは範囲外
110
        if(i_index>=this.work.length){
111
            throw new NyARException();
112
        }      
113
        //追加アロケート範囲を計算
114
        int range=i_index+ARRAY_APPEND_STEP;
115
        if(range>=this.work.length){
116
            range=this.work.length;
117
        }
118
        //アロケート
119
        for(int i=this.allocate_size;i<range;i++)
120
        {
121
            this.work2[i]=new int[7];
122
        }
123
        this.allocate_size=range;
124
    }
125
}
126
 
127
class NyARLabel
128
{
129
    public int area;
130
    public int clip0;
131
    public int clip1;
132
    public int clip2;
133
    public int clip3;
134
    public double pos_x;
135
    public double pos_y;
136
}
137
 
138
 
139
class NyARLabelHolder
140
{
141
    private final static int ARRAY_APPEND_STEP=128;
142
    public final NyARLabel[] labels;
143
    private int allocate_size;
144
    /**
145
     * 最大i_holder_size個の動的割り当てバッファを準備する。
146
     * @param i_holder_size
147
     */
148
    public NyARLabelHolder(int i_holder_size)
149
    {
150
        //ポインタだけははじめに確保しておく
151
        this.labels=new NyARLabel[i_holder_size];
152
        this.allocate_size=0;
153
    }
154
    /**
155
     * i_indexで指定した番号までのバッファを準備する。
156
     * @param i_index
157
     */
158
    private final void reserv(int i_index) throws NyARException
159
    {
160
        //アロケート済みなら即リターン
161
        if(this.allocate_size>i_index){
162
            return;
163
        }
164
        //要求されたインデクスは範囲外
165
        if(i_index>=this.labels.length){
166
            throw new NyARException();
167
        }      
168
        //追加アロケート範囲を計算
169
        int range=i_index+ARRAY_APPEND_STEP;
170
        if(range>=this.labels.length){
171
            range=this.labels.length;
172
        }
173
        //アロケート
174
        for(int i=this.allocate_size;i<range;i++)
175
        {
176
            this.labels[i]=new NyARLabel();
177
        }
178
        this.allocate_size=range;
179
    }
180
    /**
181
     * i_reserv_sizeまでのバッファを、初期条件i_lxsizeとi_lysizeで初期化する。
182
     * @param i_reserv_size
183
     * @param i_lxsize
184
     * @param i_lysize
185
     * @throws NyARException
186
     */
187
    public final void init(int i_reserv_size,int i_lxsize,int i_lysize) throws NyARException
188
    {
189
        reserv(i_reserv_size);
190
        NyARLabel l;
191
        for(int i=0;i<i_reserv_size;i++){
192
            l=this.labels[i];
193
            l.area=0;
194
            l.pos_x=0;
195
            l.pos_y=0;
196
            l.clip0= i_lxsize;//wclip[i*4+0] = lxsize;
197
            l.clip1= 0;//wclip[i*4+0] = lxsize;
198
            l.clip2= i_lysize;//wclip[i*4+2] = lysize;
199
            l.clip3= 0;//wclip[i*4+3] = 0;
200
        }      
201
    }
202
}
203
 
204
 
205
/**
206
 * ラベリングクラス。NyARRasterをラベリングして、結果値を保持します。
207
 * 構造を維持して最適化をしたバージョン
208
 *
209
 */
210
class NyARLabeling_O2 implements NyARLabeling
211
{
212
    private static final int WORK_SIZE=1024*32;//#define WORK_SIZE   1024*32
213
    private final int[][] glabel_img;//static ARInt16 l_imageL[HARDCODED_BUFFER_WIDTH*HARDCODED_BUFFER_HEIGHT];
214
 
215
    private final NyARWorkHolder work_holder=new NyARWorkHolder(WORK_SIZE);
216
    private final NyARLabelHolder label_holder=new NyARLabelHolder(WORK_SIZE);
217
 
218
    private int label_num;
219
    //
220
    private final int width;
221
    private final int height;
222
    /**
223
     * @param i_width
224
     * ラベリング画像の幅。解析するラスタの幅より大きいこと。
225
     * @param i_height
226
     * ラベリング画像の高さ。解析するラスタの高さより大きいこと。
227
     */
228
    public NyARLabeling_O2(int i_width,int i_height)
229
    {
230
        width =i_width;
231
        height=i_height;
232
        glabel_img=new int[height][width];
233
        this.wk_reservLineBuffer_buf=new int[width];
234
        label_num=0;
235
 
236
 
237
        //ワークイメージに枠を書く
238
        int[][] label_img=this.glabel_img;
239
        for(int i = 0; i < i_width; i++){
240
            label_img[0][i]=0;
241
            label_img[i_height-1][i]=0;
242
        }
243
        //</Optimize>
244
        for(int i = 0; i < i_height; i++) {
245
            label_img[i][0]=0;
246
            label_img[i][i_width-1]=0;                     
247
        }
248
 
249
 
250
 
251
 
252
    }
253
    /**
254
     * 検出したラベルの数を返す
255
     * @return
256
     */
257
    public int getLabelNum()
258
    {
259
        return label_num;
260
    }
261
    /**
262
     * 検出したエリア配列?
263
     * @return
264
     * @throws NyARException
265
     */
266
    public NyARLabel[] getLabel() throws NyARException
267
    {
268
        if(label_num<1){
269
            throw new NyARException();
270
        }
271
        return this.label_holder.labels;
272
    }    
273
    /**
274
     *
275
     * @return
276
     * @throws NyARException
277
     */
278
    public int[] getLabelRef() throws NyARException
279
    {
280
        if(label_num<1){
281
            throw new NyARException();
282
        }
283
        return work_holder.work;
284
    }
285
    /**
286
     * ラベリング済みイメージを返す
287
     * @return
288
     * @throws NyARException
289
     */
290
    public int[][] getLabelImg() throws NyARException
291
    {
292
        return glabel_img;
293
    }
294
    //コンストラクタで作ること
295
    private int[] wk_reservLineBuffer_buf=null;
296
 
297
    /**
298
     * static ARInt16 *labeling2( ARUint8 *image, int thresh,int *label_num, int **area, double **pos, int **clip,int **label_ref, int LorR )
299
     * 関数の代替品
300
     * ラスタimageをラベリングして、結果を保存します。
301
     * Optimize:STEP[1514->1493]
302
     * @param image
303
     * @param thresh
304
     * @throws NyARException
305
     */
306
    public void labeling(NyARRaster image,int thresh) throws NyARException
307
    {
308
        int wk_max;                   /*  work                */
309
        int m,n;                      /*  work                */
310
        int lxsize, lysize;
311
        int thresht3 = thresh * 3;
312
        int i,j,k;
313
        lxsize=image.getWidth();//lxsize = arUtil_c.arImXsize;
314
        lysize=image.getHeight();//lysize = arUtil_c.arImYsize;
315
        //画素数の一致チェック
316
        if(lxsize!=this.width || lysize!=this.height){
317
            throw new NyARException();
318
        }      
319
        //ラベル数を0に初期化
320
        this.label_num=0;
321
 
322
 
323
 
324
        int[][] label_img=this.glabel_img;
325
 
326
 
327
        //枠作成はインスタンスを作った直後にやってしまう。
328
 
329
        int[] work2_pt;
330
        wk_max = 0;
331
 
332
        int label_pixel;
333
 
334
        int[] work=this.work_holder.work;
335
        int[][] work2=this.work_holder.work2;
336
        int[] line_bufferr=this.wk_reservLineBuffer_buf;
337
 
338
        int[] label_img_pt0,label_img_pt1;
339
        for(j = 1; j < lysize - 1; j++) {//for (int j = 1; j < lysize - 1; j++, pnt += poff*2, pnt2 += 2) {
340
            label_img_pt0=label_img[j];
341
            label_img_pt1=label_img[j-1];
342
            image.getPixelTotalRowLine(j,line_bufferr);
343
 
344
            for(i = 1; i < lxsize-1; i++) {//for(int i = 1; i < lxsize-1; i++, pnt+=poff, pnt2++) {
345
                //RGBの合計値が閾値より大きいかな?
346
                if(line_bufferr[i]<=thresht3){
347
                    //pnt1 = ShortPointer.wrap(pnt2, -lxsize);//pnt1 = &(pnt2[-lxsize]);
348
                    if(label_img_pt1[i]>0){//if( *pnt1 > 0 ) {
349
                        label_pixel=label_img_pt1[i];//*pnt2 = *pnt1;
350
 
351
 
352
                        work2_pt=work2[label_pixel-1];
353
                        work2_pt[0]++;//work2[((*pnt2)-1)*7+0] ++;
354
                        work2_pt[1]+=i;//work2[((*pnt2)-1)*7+1] += i;
355
                        work2_pt[2]+=j;//work2[((*pnt2)-1)*7+2] += j;
356
                        work2_pt[6]=j;//work2[((*pnt2)-1)*7+6] = j;
357
                    }else if(label_img_pt1[i+1]> 0 ) {//}else if( *(pnt1+1) > 0 ) {
358
                        if(label_img_pt1[i-1] > 0 ) {//if( *(pnt1-1) > 0 ) {
359
                            m = work[label_img_pt1[i+1]-1];//m = work[*(pnt1+1)-1];
360
                            n = work[label_img_pt1[i-1]-1];//n = work[*(pnt1-1)-1];
361
                            if( m > n ){
362
                                label_pixel=n;//*pnt2 = n;
363
                                //wk=IntPointer.wrap(work, 0);//wk = &(work[0]);
364
                                for(k = 0; k < wk_max; k++) {
365
                                    if(work[k] == m ){//if( *wk == m ) 
366
                                        work[k]=n;//*wk = n;
367
                                    }
368
                                }
369
                            }else if( m < n ) {
370
                                label_pixel=m;//*pnt2 = m;
371
                                //wk=IntPointer.wrap(work,0);//wk = &(work[0]);
372
                                for(k = 0; k < wk_max; k++){
373
                                    if(work[k]==n){//if( *wk == n ){
374
                                        work[k]=m;//*wk = m;
375
                                    }
376
                                }
377
                            }else{
378
                                label_pixel=m;//*pnt2 = m;
379
                            }
380
                            work2_pt=work2[label_pixel-1];
381
                            work2_pt[0] ++;
382
                            work2_pt[1] += i;
383
                            work2_pt[2] += j;
384
                            work2_pt[6] = j;
385
                        }else if( (label_img_pt0[i-1]) > 0 ) {//}else if( *(pnt2-1) > 0 ) {
386
                            m = work[(label_img_pt1[i+1])-1];//m = work[*(pnt1+1)-1];
387
                            n = work[label_img_pt0[i-1]-1];//n = work[*(pnt2-1)-1];
388
                            if( m > n ) {
389
 
390
                                label_pixel=n;//*pnt2 = n;
391
                                for(k = 0; k < wk_max; k++) {
392
                                    if(work[k]==m){//if( *wk == m ){
393
                                        work[k]=n;//*wk = n;
394
                                    }
395
                                }
396
                            }else if( m < n ) {
397
                                label_pixel=m;//*pnt2 = m;
398
                                for(k = 0; k < wk_max; k++) {
399
                                    if(work[k]==n){//if( *wk == n ){
400
                                        work[k]=m;//*wk = m;
401
                                    }
402
                                }
403
                            }else{
404
                                label_pixel=m;//*pnt2 = m;
405
                            }
406
                            work2_pt=work2[label_pixel-1];
407
                            work2_pt[0] ++;//work2[((*pnt2)-1)*7+0] ++;
408
                            work2_pt[1] += i;//work2[((*pnt2)-1)*7+1] += i;
409
                            work2_pt[2] += j;//work2[((*pnt2)-1)*7+2] += j;
410
                        }else{
411
 
412
                            label_pixel=label_img_pt1[i+1];//*pnt2 = *(pnt1+1);
413
 
414
                            work2_pt=work2[label_pixel-1];
415
                            work2_pt[0] ++;//work2[((*pnt2)-1)*7+0] ++;
416
                            work2_pt[1] += i;//work2[((*pnt2)-1)*7+1] += i;
417
                            work2_pt[2] += j;//work2[((*pnt2)-1)*7+2] += j;
418
                            if( work2_pt[3] > i ){//if( work2[((*pnt2)-1)*7+3] > i ){           
419
                                work2_pt[3] = i;//      work2[((*pnt2)-1)*7+3] = i;
420
                            }
421
                            work2_pt[6] = j;//work2[((*pnt2)-1)*7+6] = j;
422
                        }
423
                    }else if( (label_img_pt1[i-1]) > 0 ) {//}else if( *(pnt1-1) > 0 ) {
424
                        label_pixel=label_img_pt1[i-1];//*pnt2 = *(pnt1-1);
425
 
426
                        work2_pt=work2[label_pixel-1];
427
                        work2_pt[0] ++;//work2[((*pnt2)-1)*7+0] ++;
428
                        work2_pt[1] += i;//work2[((*pnt2)-1)*7+1] += i;
429
                        work2_pt[2] += j;//work2[((*pnt2)-1)*7+2] += j;
430
                        if( work2_pt[4] < i ){//if( work2[((*pnt2)-1)*7+4] < i ){
431
                            work2_pt[4] = i;//  work2[((*pnt2)-1)*7+4] = i;
432
                        }
433
                        work2_pt[6] = j;//work2[((*pnt2)-1)*7+6] = j;
434
                    }else if(label_img_pt0[i-1] > 0) {//}else if( *(pnt2-1) > 0) {
435
                        label_pixel=label_img_pt0[i-1];//*pnt2 = *(pnt2-1);
436
 
437
                        work2_pt=work2[label_pixel-1];
438
                        work2_pt[0] ++;//work2[((*pnt2)-1)*7+0] ++;
439
                        work2_pt[1] += i;//work2[((*pnt2)-1)*7+1] += i;
440
                        work2_pt[2] += j;//work2[((*pnt2)-1)*7+2] += j;
441
                        if(work2_pt[4] < i ){//if( work2[((*pnt2)-1)*7+4] < i ){
442
                            work2_pt[4] = i;//  work2[((*pnt2)-1)*7+4] = i;
443
                        }
444
                    }else{
445
                        //現在地までの領域を予約
446
                        this.work_holder.reserv(wk_max);
447
                        wk_max++;
448
                        work[wk_max-1] = wk_max;
449
                        label_pixel=wk_max;//work[wk_max-1] = *pnt2 = wk_max;
450
                        work2_pt=work2[wk_max-1];
451
                        work2_pt[0] = 1;
452
                        work2_pt[1] = i;
453
                        work2_pt[2] = j;
454
                        work2_pt[3] = i;
455
                        work2_pt[4] = i;
456
                        work2_pt[5] = j;
457
                        work2_pt[6] = j;
458
                    }
459
                    label_img_pt0[i]=label_pixel;
460
                }else {
461
                    label_img_pt0[i]=0;//*pnt2 = 0;
462
                }
463
 
464
            }
465
        }
466
        j = 1;
467
        for(i = 0; i < wk_max; i++){//for(int i = 1; i <= wk_max; i++, wk++) {
468
            work[i]=(work[i]==i+1)? j++: work[work[i]-1];//*wk = (*wk==i)? j++: work[(*wk)-1];
469
        }
470
 
471
        int wlabel_num=j - 1;//*label_num = *wlabel_num = j - 1;
472
 
473
        if(wlabel_num==0){//if( *label_num == 0 ) {
474
            //発見数0
475
            return;
476
        }
477
 
478
 
479
 
480
        //ラベルバッファを予約&初期化
481
        this.label_holder.init(wlabel_num, lxsize, lysize);
482
//      
483
//      putZero(warea,wlabel_num);//put_zero( (ARUint8 *)warea, *label_num *     sizeof(int) );
484
//      for(i=0;i<wlabel_num;i++){
485
//          wpos[i*2+0]=0;
486
//          wpos[i*2+1]=0;
487
//      }
488
//      for(i = 0; i < wlabel_num; i++) {//for(i = 0; i < *label_num; i++) {
489
//          wclip[i][0] = lxsize;//wclip[i*4+0] = lxsize;
490
//          wclip[i][1] = 0;//wclip[i*4+1] = 0;
491
//          wclip[i][2] = lysize;//wclip[i*4+2] = lysize;
492
//          wclip[i][3] = 0;//wclip[i*4+3] = 0;
493
//      }
494
        NyARLabel label_pt;
495
        NyARLabel[] labels=this.label_holder.labels;
496
 
497
        for(i = 0; i < wk_max; i++){
498
            label_pt=labels[work[i] - 1];
499
            work2_pt=work2[i];
500
            label_pt.area  += work2_pt[0];
501
            label_pt.pos_x += work2_pt[1];
502
            label_pt.pos_y += work2_pt[2];
503
            if( label_pt.clip0 > work2_pt[3] ){
504
                label_pt.clip0 = work2_pt[3];
505
            }
506
            if( label_pt.clip1 < work2_pt[4] ){
507
                label_pt.clip1 = work2_pt[4];
508
            }
509
            if(label_pt.clip2 > work2_pt[5] ){
510
                label_pt.clip2 = work2_pt[5];
511
            }
512
            if( label_pt.clip3 < work2_pt[6] ){
513
                label_pt.clip3 = work2_pt[6];
514
            }
515
        }
516
 
517
        for(i = 0; i < wlabel_num; i++ ) {//for(int i = 0; i < *label_num; i++ ) {
518
            label_pt=labels[i];
519
            label_pt.pos_x /= label_pt.area;
520
            label_pt.pos_y /= label_pt.area;
521
        }
522
 
523
        label_num=wlabel_num;
524
        return;
525
    }
526
}
527