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.core.labeling.processor;
\r
34 import jp.nyatla.nyartoolkit.NyARException;
\r
35 import jp.nyatla.nyartoolkit.core.raster.*;
\r
36 import jp.nyatla.nyartoolkit.core.labeling.*;
\r
37 import jp.nyatla.nyartoolkit.core.types.*;
\r
48 * ARToolKit互換のラベリングクラスです。
\r
49 * ARToolKitと同一な評価結果を返します。
\r
52 public class NyARLabeling implements INyLabeling
\r
54 private static final int WORK_SIZE=1024*32;//#define WORK_SIZE 1024*32
\r
55 private final NyARWorkHolder work_holder=new NyARWorkHolder(WORK_SIZE);
\r
56 private int _thresh;
\r
57 private TNyIntSize _dest_size;
\r
58 private NyLabelingImage _out_image;
\r
59 public NyARLabeling()
\r
63 public void setThresh(int i_thresh)
\r
65 this._thresh=i_thresh;
\r
68 private int[] wk_reservLineBuffer_buf;
\r
69 public void attachDestination(NyLabelingImage i_destination_image) throws NyARException
\r
72 TNyIntSize size=i_destination_image.getSize();
\r
73 this._out_image=i_destination_image;
\r
76 if(this.wk_reservLineBuffer_buf==null){
\r
77 this.wk_reservLineBuffer_buf=new int[size.w];
\r
78 }else if(this.wk_reservLineBuffer_buf.length<size.w){
\r
79 this.wk_reservLineBuffer_buf=new int[size.w];
\r
82 //NyLabelingImageのイメージ初期化(枠書き)
\r
83 int[][] img=i_destination_image.getImage();
\r
84 for(int i = 0; i < size.w; i++){
\r
88 for(int i = 0; i < size.h; i++) {
\r
90 img[i][size.w-1]=0;
\r
94 this._dest_size=size;
\r
99 * static ARInt16 *labeling2( ARUint8 *image, int thresh,int *label_num, int **area, double **pos, int **clip,int **label_ref, int LorR )
\r
101 * ラスタimageをラベリングして、結果を保存します。
\r
102 * Optimize:STEP[1514->1493]
\r
105 * @throws NyARException
\r
107 public void labeling(INyARRaster i_input_raster) throws NyARException
\r
109 int wk_max; /* work */
\r
110 int m,n; /* work */
\r
111 int thresht3 = this._thresh * 3;
\r
113 NyLabelingImage out_image=this._out_image;
\r
116 TNyIntSize in_size=i_input_raster.getSize();
\r
117 this._dest_size.isEqualSize(in_size);
\r
119 int lxsize=in_size.w;//lxsize = arUtil_c.arImXsize;
\r
120 int lysize=in_size.h;//lysize = arUtil_c.arImYsize;
\r
121 int[][] label_img=out_image.getImage();
\r
124 //枠作成はインスタンスを作った直後にやってしまう。
\r
131 int[] work=this.work_holder.work;
\r
132 int[][] work2=this.work_holder.work2;
\r
133 int[] line_bufferr=this.wk_reservLineBuffer_buf;
\r
135 int[] label_img_pt0,label_img_pt1;
\r
136 for(j = 1; j < lysize - 1; j++) {//for (int j = 1; j < lysize - 1; j++, pnt += poff*2, pnt2 += 2) {
\r
137 label_img_pt0=label_img[j];
\r
138 label_img_pt1=label_img[j-1];
\r
139 i_input_raster.getPixelTotalRowLine(j,line_bufferr);
\r
141 for(i = 1; i < lxsize-1; i++) {//for(int i = 1; i < lxsize-1; i++, pnt+=poff, pnt2++) {
\r
142 //RGBの合計値が閾値より小さいかな?
\r
143 if(line_bufferr[i]<=thresht3){
\r
144 //pnt1 = ShortPointer.wrap(pnt2, -lxsize);//pnt1 = &(pnt2[-lxsize]);
\r
145 if(label_img_pt1[i]>0){//if( *pnt1 > 0 ) {
\r
146 label_pixel=label_img_pt1[i];//*pnt2 = *pnt1;
\r
149 work2_pt=work2[label_pixel-1];
\r
150 work2_pt[0]++;//work2[((*pnt2)-1)*7+0] ++;
\r
151 work2_pt[1]+=i;//work2[((*pnt2)-1)*7+1] += i;
\r
152 work2_pt[2]+=j;//work2[((*pnt2)-1)*7+2] += j;
\r
153 work2_pt[6]=j;//work2[((*pnt2)-1)*7+6] = j;
\r
154 }else if(label_img_pt1[i+1]> 0 ) {//}else if( *(pnt1+1) > 0 ) {
\r
155 if(label_img_pt1[i-1] > 0 ) {//if( *(pnt1-1) > 0 ) {
\r
156 m = work[label_img_pt1[i+1]-1];//m = work[*(pnt1+1)-1];
\r
157 n = work[label_img_pt1[i-1]-1];//n = work[*(pnt1-1)-1];
\r
159 label_pixel=n;//*pnt2 = n;
\r
160 //wk=IntPointer.wrap(work, 0);//wk = &(work[0]);
\r
161 for(k = 0; k < wk_max; k++) {
\r
162 if(work[k] == m ){//if( *wk == m )
\r
163 work[k]=n;//*wk = n;
\r
166 }else if( m < n ) {
\r
167 label_pixel=m;//*pnt2 = m;
\r
168 //wk=IntPointer.wrap(work,0);//wk = &(work[0]);
\r
169 for(k = 0; k < wk_max; k++){
\r
170 if(work[k]==n){//if( *wk == n ){
\r
171 work[k]=m;//*wk = m;
\r
175 label_pixel=m;//*pnt2 = m;
\r
177 work2_pt=work2[label_pixel-1];
\r
182 }else if( (label_img_pt0[i-1]) > 0 ) {//}else if( *(pnt2-1) > 0 ) {
\r
183 m = work[(label_img_pt1[i+1])-1];//m = work[*(pnt1+1)-1];
\r
184 n = work[label_img_pt0[i-1]-1];//n = work[*(pnt2-1)-1];
\r
187 label_pixel=n;//*pnt2 = n;
\r
188 for(k = 0; k < wk_max; k++) {
\r
189 if(work[k]==m){//if( *wk == m ){
\r
190 work[k]=n;//*wk = n;
\r
193 }else if( m < n ) {
\r
194 label_pixel=m;//*pnt2 = m;
\r
195 for(k = 0; k < wk_max; k++) {
\r
196 if(work[k]==n){//if( *wk == n ){
\r
197 work[k]=m;//*wk = m;
\r
201 label_pixel=m;//*pnt2 = m;
\r
203 work2_pt=work2[label_pixel-1];
\r
204 work2_pt[0] ++;//work2[((*pnt2)-1)*7+0] ++;
\r
205 work2_pt[1] += i;//work2[((*pnt2)-1)*7+1] += i;
\r
206 work2_pt[2] += j;//work2[((*pnt2)-1)*7+2] += j;
\r
209 label_pixel=label_img_pt1[i+1];//*pnt2 = *(pnt1+1);
\r
211 work2_pt=work2[label_pixel-1];
\r
212 work2_pt[0] ++;//work2[((*pnt2)-1)*7+0] ++;
\r
213 work2_pt[1] += i;//work2[((*pnt2)-1)*7+1] += i;
\r
214 work2_pt[2] += j;//work2[((*pnt2)-1)*7+2] += j;
\r
215 if( work2_pt[3] > i ){//if( work2[((*pnt2)-1)*7+3] > i ){
\r
216 work2_pt[3] = i;// work2[((*pnt2)-1)*7+3] = i;
\r
218 work2_pt[6] = j;//work2[((*pnt2)-1)*7+6] = j;
\r
220 }else if( (label_img_pt1[i-1]) > 0 ) {//}else if( *(pnt1-1) > 0 ) {
\r
221 label_pixel=label_img_pt1[i-1];//*pnt2 = *(pnt1-1);
\r
223 work2_pt=work2[label_pixel-1];
\r
224 work2_pt[0] ++;//work2[((*pnt2)-1)*7+0] ++;
\r
225 work2_pt[1] += i;//work2[((*pnt2)-1)*7+1] += i;
\r
226 work2_pt[2] += j;//work2[((*pnt2)-1)*7+2] += j;
\r
227 if( work2_pt[4] < i ){//if( work2[((*pnt2)-1)*7+4] < i ){
\r
228 work2_pt[4] = i;// work2[((*pnt2)-1)*7+4] = i;
\r
230 work2_pt[6] = j;//work2[((*pnt2)-1)*7+6] = j;
\r
231 }else if(label_img_pt0[i-1] > 0) {//}else if( *(pnt2-1) > 0) {
\r
232 label_pixel=label_img_pt0[i-1];//*pnt2 = *(pnt2-1);
\r
234 work2_pt=work2[label_pixel-1];
\r
235 work2_pt[0] ++;//work2[((*pnt2)-1)*7+0] ++;
\r
236 work2_pt[1] += i;//work2[((*pnt2)-1)*7+1] += i;
\r
237 work2_pt[2] += j;//work2[((*pnt2)-1)*7+2] += j;
\r
238 if(work2_pt[4] < i ){//if( work2[((*pnt2)-1)*7+4] < i ){
\r
239 work2_pt[4] = i;// work2[((*pnt2)-1)*7+4] = i;
\r
243 this.work_holder.reserv(wk_max);
\r
245 work[wk_max-1] = wk_max;
\r
246 label_pixel=wk_max;//work[wk_max-1] = *pnt2 = wk_max;
\r
247 work2_pt=work2[wk_max-1];
\r
256 label_img_pt0[i]=label_pixel;
\r
258 label_img_pt0[i]=0;//*pnt2 = 0;
\r
263 int wlabel_num=1;//*label_num = *wlabel_num = j - 1;
\r
265 for(i = 0; i < wk_max; i++){//for(int i = 1; i <= wk_max; i++, wk++) {
\r
266 work[i]=(work[i]==i+1)? wlabel_num++: work[work[i]-1];//*wk = (*wk==i)? j++: work[(*wk)-1];
\r
268 wlabel_num-=1;//*label_num = *wlabel_num = j - 1;
\r
269 if(wlabel_num==0){//if( *label_num == 0 ) {
\r
271 out_image.getLabelList().setLength(0);
\r
278 l1=lxsize & 0xfffffffc;
\r
279 for(i=lysize-1;i>=0;i--)
\r
287 line[i2]=work[pix-1];
\r
293 line[i2]=work[pix-1];
\r
299 line[i2]=work[pix-1];
\r
305 line[i2]=work[pix-1];
\r
309 for(;i2<lxsize;i2++){
\r
314 line[i2]=work[pix-1];
\r
321 NyLabelingLabelList label_list=out_image.getLabelList();
\r
324 label_list.reserv(wlabel_num);
\r
327 NyLabelingLabel label_pt;
\r
328 NyLabelingLabel[] labels=label_list.getArray();
\r
329 for(i=0;i<wlabel_num;i++)
\r
331 label_pt=labels[i];
\r
335 label_pt.clip_l= lxsize;//wclip[i*4+0] = lxsize;
\r
336 label_pt.clip_r= 0;//wclip[i*4+0] = lxsize;
\r
337 label_pt.clip_t= lysize;//wclip[i*4+2] = lysize;
\r
338 label_pt.clip_b= 0;//wclip[i*4+3] = 0;
\r
342 for(i = 0; i < wk_max; i++){
\r
343 label_pt=labels[work[i] - 1];
\r
345 label_pt.area += work2_pt[0];
\r
346 label_pt.pos_x += work2_pt[1];
\r
347 label_pt.pos_y += work2_pt[2];
\r
348 if( label_pt.clip_l > work2_pt[3] ){
\r
349 label_pt.clip_l = work2_pt[3];
\r
351 if( label_pt.clip_r < work2_pt[4] ){
\r
352 label_pt.clip_r = work2_pt[4];
\r
354 if(label_pt.clip_t > work2_pt[5] ){
\r
355 label_pt.clip_t = work2_pt[5];
\r
357 if( label_pt.clip_b < work2_pt[6] ){
\r
358 label_pt.clip_b = work2_pt[6];
\r
362 for(i = 0; i < wlabel_num; i++ ) {//for(int i = 0; i < *label_num; i++ ) {
\r
363 label_pt=labels[i];
\r
364 label_pt.pos_x /= label_pt.area;
\r
365 label_pt.pos_y /= label_pt.area;
\r
368 label_list.setLength(wlabel_num);
\r
374 * NyARLabeling_O2のworkとwork2を可変長にするためのクラス
\r
378 class NyARWorkHolder
\r
380 private final static int ARRAY_APPEND_STEP=256;
\r
381 public final int[] work;
\r
382 public final int[][] work2;
\r
383 private int allocate_size;
\r
385 * 最大i_holder_size個の動的割り当てバッファを準備する。
\r
386 * @param i_holder_size
\r
388 public NyARWorkHolder(int i_holder_size)
\r
390 //ポインタだけははじめに確保しておく
\r
391 this.work=new int[i_holder_size];
\r
392 this.work2=new int[i_holder_size][];
\r
393 this.allocate_size=0;
\r
396 * i_indexで指定した番号までのバッファを準備する。
\r
399 public final void reserv(int i_index) throws NyARException
\r
402 if(this.allocate_size>i_index){
\r
406 if(i_index>=this.work.length){
\r
407 throw new NyARException();
\r
410 int range=i_index+ARRAY_APPEND_STEP;
\r
411 if(range>=this.work.length){
\r
412 range=this.work.length;
\r
415 for(int i=this.allocate_size;i<range;i++)
\r
417 this.work2[i]=new int[7];
\r
419 this.allocate_size=range;
\r