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 edition ARToolKit class library.
\r
11 * Copyright (C)2008-2009 Ryo Iizuka
\r
13 * This program is free software: you can redistribute it and/or modify
\r
14 * it under the terms of the GNU General Public License as published by
\r
15 * the Free Software Foundation, either version 3 of the License, or
\r
16 * (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 program. If not, see <http://www.gnu.org/licenses/>.
\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
31 package jp.nyatla.nyartoolkit.core.labeling.artoolkit;
\r
33 import jp.nyatla.nyartoolkit.NyARException;
\r
34 import jp.nyatla.nyartoolkit.core.raster.*;
\r
35 import jp.nyatla.nyartoolkit.core.types.*;
\r
38 * ARToolKit互換のラベリングクラスです。 ARToolKitと同一な評価結果を返します。
\r
41 final public class NyARLabeling_ARToolKit
\r
43 private static final int WORK_SIZE = 1024 * 32;// #define WORK_SIZE 1024*32
\r
45 private final NyARWorkHolder work_holder = new NyARWorkHolder(WORK_SIZE);
\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
53 * @throws NyARException
\r
55 public int labeling(NyARBinRaster i_raster,NyARLabelingImage o_destination) throws NyARException
\r
57 assert(i_raster.getBufferType()==INyARRaster.BUFFERFORMAT_INT1D_BIN_8);
\r
58 int label_img_ptr1, label_pixel;
\r
60 int n, k; /* work */
\r
63 NyARIntSize in_size = i_raster.getSize();
\r
64 assert(o_destination.getSize().isEqualSize(in_size));
\r
66 final int lxsize = in_size.w;// lxsize = arUtil_c.arImXsize;
\r
67 final int lysize = in_size.h;// lysize = arUtil_c.arImYsize;
\r
68 final int[] label_img = (int[]) o_destination.getBuffer();
\r
70 // 枠作成はインスタンスを作った直後にやってしまう。
\r
72 // ラベリング情報のリセット(ラベリングインデックスを使用)
\r
73 o_destination.reset(true);
\r
75 int[] label_idxtbl = o_destination.getIndexArray();
\r
76 int[] raster_buf = (int[]) i_raster.getBuffer();
\r
82 int[][] work2 = this.work_holder.work2;
\r
84 // [1,1](ptr0)と、[0,1](ptr1)のインデクス値を計算する。
\r
85 for (j = 1; j < lysize - 1; j++) {// for (int j = 1; j < lysize - 1;j++, pnt += poff*2, pnt2 += 2) {
\r
86 pixel_index = j * lxsize + 1;
\r
87 label_img_ptr1 = pixel_index - lxsize;// label_img_pt1 = label_img[j - 1];
\r
88 for (i = 1; i < lxsize - 1; i++, pixel_index++, label_img_ptr1++) {// for(int i = 1; i < lxsize-1;i++, pnt+=poff, pnt2++) {
\r
89 // RGBの合計値が閾値より小さいかな?
\r
90 if (raster_buf[pixel_index] != 0) {
\r
91 label_img[pixel_index] = 0;// label_img_pt0[i] = 0;// *pnt2 = 0;
\r
93 // pnt1 = ShortPointer.wrap(pnt2, -lxsize);//pnt1 =&(pnt2[-lxsize]);
\r
94 if (label_img[label_img_ptr1] > 0) {// if (label_img_pt1[i] > 0) {// if( *pnt1 > 0 ) {
\r
95 label_pixel = label_img[label_img_ptr1];// label_pixel = label_img_pt1[i];// *pnt2 = *pnt1;
\r
97 work2_pt = work2[label_pixel - 1];
\r
98 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;
\r
99 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;
\r
100 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;
\r
101 work2_pt[6] = j;// work2[((*pnt2)-1)*7+6] = j;
\r
102 } else if (label_img[label_img_ptr1 + 1] > 0) {// } else if (label_img_pt1[i + 1] > 0) {// }else if(*(pnt1+1) > 0 ) {
\r
103 if (label_img[label_img_ptr1 - 1] > 0) {// if (label_img_pt1[i - 1] > 0) {// if( *(pnt1-1) > 0 ) {
\r
104 label_pixel = label_idxtbl[label_img[label_img_ptr1 + 1] - 1];// m = label_idxtbl[label_img_pt1[i + 1] - 1];// m
\r
105 // =work[*(pnt1+1)-1];
\r
106 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
107 if (label_pixel > n) {
\r
108 // wk=IntPointer.wrap(work, 0);//wk = &(work[0]);
\r
109 for (k = 0; k < wk_max; k++) {
\r
110 if (label_idxtbl[k] == label_pixel) {// if( *wk == m )
\r
111 label_idxtbl[k] = n;// *wk = n;
\r
114 label_pixel = n;// *pnt2 = n;
\r
115 } else if (label_pixel < n) {
\r
116 // wk=IntPointer.wrap(work,0);//wk = &(work[0]);
\r
117 for (k = 0; k < wk_max; k++) {
\r
118 if (label_idxtbl[k] == n) {// if( *wk == n ){
\r
119 label_idxtbl[k] = label_pixel;// *wk = m;
\r
123 work2_pt = work2[label_pixel - 1];
\r
128 } else if ((label_img[pixel_index - 1]) > 0) {// } else if ((label_img_pt0[i - 1]) > 0) {// }else if(*(pnt2-1) > 0) {
\r
129 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
130 n = label_idxtbl[label_img[pixel_index - 1] - 1];// n = label_idxtbl[label_img_pt0[i - 1] - 1];// n =work[*(pnt2-1)-1];
\r
131 if (label_pixel > n) {
\r
132 for (k = 0; k < wk_max; k++) {
\r
133 if (label_idxtbl[k] == label_pixel) {// if( *wk == m ){
\r
134 label_idxtbl[k] = n;// *wk = n;
\r
137 label_pixel = n;// *pnt2 = n;
\r
138 } else if (label_pixel < n) {
\r
139 for (k = 0; k < wk_max; k++) {
\r
140 if (label_idxtbl[k] == n) {// if( *wk == n ){
\r
141 label_idxtbl[k] = label_pixel;// *wk = m;
\r
145 work2_pt = work2[label_pixel - 1];
\r
146 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;
\r
147 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;
\r
148 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;
\r
151 label_pixel = label_img[label_img_ptr1 + 1];// label_pixel = label_img_pt1[i + 1];// *pnt2 =
\r
154 work2_pt = work2[label_pixel - 1];
\r
155 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;
\r
156 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;
\r
157 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;
\r
158 if (work2_pt[3] > i) {// if(work2[((*pnt2)-1)*7+3] > i ){
\r
159 work2_pt[3] = i;// work2[((*pnt2)-1)*7+3] = i;
\r
161 work2_pt[6] = j;// work2[((*pnt2)-1)*7+6] = j;
\r
163 } else if ((label_img[label_img_ptr1 - 1]) > 0) {// } else if ((label_img_pt1[i - 1]) > 0) {// }else if(
\r
164 // *(pnt1-1) > 0 ) {
\r
165 label_pixel = label_img[label_img_ptr1 - 1];// label_pixel = label_img_pt1[i - 1];// *pnt2 =
\r
168 work2_pt = work2[label_pixel - 1];
\r
169 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;
\r
170 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;
\r
171 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;
\r
172 if (work2_pt[4] < i) {// if( work2[((*pnt2)-1)*7+4] <i ){
\r
173 work2_pt[4] = i;// work2[((*pnt2)-1)*7+4] = i;
\r
175 work2_pt[6] = j;// work2[((*pnt2)-1)*7+6] = j;
\r
176 } else if (label_img[pixel_index - 1] > 0) {// } else if (label_img_pt0[i - 1] > 0) {// }else if(*(pnt2-1) > 0) {
\r
177 label_pixel = label_img[pixel_index - 1];// label_pixel = label_img_pt0[i - 1];// *pnt2 =*(pnt2-1);
\r
179 work2_pt = work2[label_pixel - 1];
\r
180 work2_pt[0]++;// work2[((*pnt2)-1)*7+0] ++;
\r
181 work2_pt[1] += i;// work2[((*pnt2)-1)*7+1] += i;
\r
182 work2_pt[2] += j;// work2[((*pnt2)-1)*7+2] += j;
\r
183 if (work2_pt[4] < i) {// if( work2[((*pnt2)-1)*7+4] <i ){
\r
184 work2_pt[4] = i;// work2[((*pnt2)-1)*7+4] = i;
\r
188 this.work_holder.reserv(wk_max);
\r
190 label_idxtbl[wk_max - 1] = wk_max;
\r
191 label_pixel = wk_max;// work[wk_max-1] = *pnt2 = wk_max;
\r
192 work2_pt = work2[wk_max - 1];
\r
201 label_img[pixel_index] = label_pixel;// label_img_pt0[i] = label_pixel;
\r
206 // インデックステーブルとラベル数の計算
\r
207 int wlabel_num = 1;// *label_num = *wlabel_num = j - 1;
\r
209 for (i = 0; i < wk_max; i++) {// for(int i = 1; i <= wk_max; i++,wk++) {
\r
210 label_idxtbl[i] = (label_idxtbl[i] == i + 1) ? wlabel_num++ : label_idxtbl[label_idxtbl[i] - 1];// *wk=(*wk==i)?j++:work[(*wk)-1];
\r
212 wlabel_num -= 1;// *label_num = *wlabel_num = j - 1;
\r
213 if (wlabel_num == 0) {// if( *label_num == 0 ) {
\r
215 o_destination.getLabelStack().clear();
\r
219 NyARLabelingLabelStack label_list = o_destination.getLabelStack();
\r
222 label_list.init(wlabel_num);
\r
224 // エリアと重心、クリップ領域を計算
\r
225 NyARLabelingLabel label_pt;
\r
226 NyARLabelingLabel[] labels =label_list.getArray();
\r
227 for (i = 0; i < wlabel_num; i++) {
\r
228 label_pt = labels[i];
\r
229 label_pt.id = (short)(i + 1);
\r
231 label_pt.pos_x = label_pt.pos_y = 0;
\r
232 label_pt.clip_l = lxsize;// wclip[i*4+0] = lxsize;
\r
233 label_pt.clip_t = lysize;// wclip[i*4+2] = lysize;
\r
234 label_pt.clip_r = label_pt.clip_b = 0;// wclip[i*4+3] = 0;
\r
237 for (i = 0; i < wk_max; i++) {
\r
238 label_pt = labels[label_idxtbl[i] - 1];
\r
239 work2_pt = work2[i];
\r
240 label_pt.area += work2_pt[0];
\r
241 label_pt.pos_x += work2_pt[1];
\r
242 label_pt.pos_y += work2_pt[2];
\r
243 if (label_pt.clip_l > work2_pt[3]) {
\r
244 label_pt.clip_l = work2_pt[3];
\r
246 if (label_pt.clip_r < work2_pt[4]) {
\r
247 label_pt.clip_r = work2_pt[4];
\r
249 if (label_pt.clip_t > work2_pt[5]) {
\r
250 label_pt.clip_t = work2_pt[5];
\r
252 if (label_pt.clip_b < work2_pt[6]) {
\r
253 label_pt.clip_b = work2_pt[6];
\r
257 for (i = 0; i < wlabel_num; i++) {// for(int i = 0; i < *label_num; i++ ) {
\r
258 label_pt = labels[i];
\r
259 label_pt.pos_x /= label_pt.area;
\r
260 label_pt.pos_y /= label_pt.area;
\r
268 * NyARLabeling_O2のworkとwork2を可変長にするためのクラス
\r
272 final class NyARWorkHolder
\r
274 private final static int ARRAY_APPEND_STEP = 256;
\r
276 public final int[][] work2;
\r
278 private int allocate_size;
\r
281 * 最大i_holder_size個の動的割り当てバッファを準備する。
\r
283 * @param i_holder_size
\r
285 public NyARWorkHolder(int i_holder_size)
\r
287 // ポインタだけははじめに確保しておく
\r
288 this.work2 = new int[i_holder_size][];
\r
289 this.allocate_size = 0;
\r
293 * i_indexで指定した番号までのバッファを準備する。
\r
297 public final void reserv(int i_index) throws NyARException
\r
300 if (this.allocate_size > i_index) {
\r
304 if (i_index >= this.work2.length) {
\r
305 throw new NyARException();
\r
308 int range = i_index + ARRAY_APPEND_STEP;
\r
309 if (range >= this.work2.length) {
\r
310 range = this.work2.length;
\r
313 for (int i = this.allocate_size; i < range; i++) {
\r
314 this.work2[i] = new int[7];
\r
316 this.allocate_size = range;
\r