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;
\r
37 import jp.nyatla.nyartoolkit.NyARException;
\r
38 import jp.nyatla.util.IntValue;
\r
40 * イメージからマーカー情報を検出するクラス。
\r
41 * このクラスは、arDetectMarker2.cとの置き換えになります。
\r
42 * ラベリング済みのラスタデータからマーカー位置を検出して、結果を保持します。
\r
45 public class NyARDetectMarker {
\r
46 private static final int AR_AREA_MAX=100000;//#define AR_AREA_MAX 100000
\r
47 private static final int AR_AREA_MIN=70;//#define AR_AREA_MIN 70
\r
49 private int area_max=AR_AREA_MAX;
\r
50 private int area_min=AR_AREA_MIN;
\r
51 private NyARMarker[] marker_holder; //マーカーデータの保持配列
\r
52 private NyARMarker[] marker_info2_array; //マーカーデータのインデックス配列
\r
53 private int marker_num;
\r
54 private int width,height;
\r
56 * 最大i_squre_max個のマーカーを検出するクラスを作成する。
\r
59 * @param i_squre_max
\r
61 public NyARDetectMarker(int i_width,int i_height,int i_squre_max)
\r
65 marker_holder=new NyARMarker[i_squre_max];
\r
66 marker_info2_array=new NyARMarker[i_squre_max];
\r
68 public int getMarkerNum()
\r
72 public NyARMarker getMarker(int idx) throws NyARException
\r
74 if(idx>=marker_num){
\r
75 throw new NyARException();
\r
77 return marker_info2_array[idx];
\r
80 * static int get_vertex( int x_coord[], int y_coord[], int st, int ed,double thresh, int vertex[], int *vnum)
\r
91 private static boolean get_vertex( int[] x_coord, int[] y_coord, int st, int ed,double thresh, int vertex[],IntValue vnum)
\r
97 a = y_coord[ed] - y_coord[st];
\r
98 b = x_coord[st] - x_coord[ed];
\r
99 c = x_coord[ed]*y_coord[st] - y_coord[ed]*x_coord[st];
\r
101 for(i=st+1;i<ed;i++) {
\r
102 d = a*x_coord[i] + b*y_coord[i] + c;
\r
108 if( dmax/(a*a+b*b) > thresh ) {
\r
109 if(!get_vertex(x_coord, y_coord, st, v1, thresh, vertex, vnum)){
\r
112 if( vnum.get() > 5 ){
\r
115 vertex[vnum.get()] = v1;//vertex[(*vnum)] = v1;
\r
116 vnum.inc();//(*vnum)++;
\r
118 if(!get_vertex(x_coord, y_coord, v1, ed, thresh, vertex, vnum)){
\r
125 * static int arDetectMarker2_check_square( int area, ARMarkerInfo2 *marker_info2, double factor )
\r
128 * @param i_marker_info2
\r
132 private static boolean check_square( int area, NyARMarker i_marker_info2, double factor )
\r
136 int[] vertex=new int[10];//int vertex[10]
\r
137 int[] wv1=new int[10],wv2=new int[10];//int wv1[10],wv2[10];
\r
138 int v2;// int wvnum1,wvnum2,v2;
\r
141 IntValue wvnum1=new IntValue(),wvnum2=new IntValue();
\r
146 sx = i_marker_info2.x_coord[0];//sx = marker_info2->x_coord[0];
\r
147 sy = i_marker_info2.y_coord[0];//sy = marker_info2->y_coord[0];
\r
148 for(i=1;i<i_marker_info2.coord_num-1;i++){//for(i=1;i<marker_info2->coord_num-1;i++) {
\r
149 d = (i_marker_info2.x_coord[i]-sx)*(i_marker_info2.x_coord[i]-sx)+ (i_marker_info2.y_coord[i]-sy)*(i_marker_info2.y_coord[i]-sy);
\r
156 thresh = (area/0.75) * 0.01 * factor;
\r
159 wvnum1.set(0);// wvnum1 = 0;
\r
160 wvnum2.set(0);// wvnum2 = 0;
\r
162 if(!get_vertex(i_marker_info2.x_coord, i_marker_info2.y_coord, 0, v1,thresh, wv1, wvnum1)){ //if( get_vertex(marker_info2->x_coord, marker_info2->y_coord, 0, v1,thresh, wv1, &wvnum1) < 0 ) {
\r
165 if(!get_vertex(i_marker_info2.x_coord, i_marker_info2.y_coord,v1, i_marker_info2.coord_num-1, thresh, wv2, wvnum2)) {//if(get_vertex(marker_info2->x_coord, marker_info2->y_coord,v1, marker_info2->coord_num-1, thresh, wv2, &wvnum2) < 0 ) {
\r
169 if( wvnum1.get() == 1 && wvnum2.get() == 1 ) {//if( wvnum1 == 1 && wvnum2 == 1 ) {
\r
170 vertex[1] = wv1[0];
\r
172 vertex[3] = wv2[0];
\r
173 }else if( wvnum1.get() > 1 && wvnum2.get() == 0 ) {//}else if( wvnum1 > 1 && wvnum2 == 0 ) {
\r
175 wvnum1.set(0);wvnum2.set(0);//wvnum1 = wvnum2 = 0;
\r
176 if(!get_vertex(i_marker_info2.x_coord, i_marker_info2.y_coord,0, v2, thresh, wv1, wvnum1)) {
\r
179 if(!get_vertex(i_marker_info2.x_coord, i_marker_info2.y_coord,v2, v1, thresh, wv2, wvnum2)) {
\r
182 if( wvnum1.get() == 1 && wvnum2.get() == 1 ) {
\r
183 vertex[1] = wv1[0];
\r
184 vertex[2] = wv2[0];
\r
189 }else if( wvnum1.get() == 0 && wvnum2.get() > 1 ) {
\r
190 v2 = (v1 + i_marker_info2.coord_num-1) / 2;
\r
192 wvnum1.set(0);wvnum2.set(0);//wvnum1 = wvnum2 = 0;
\r
193 if(!get_vertex(i_marker_info2.x_coord, i_marker_info2.y_coord,v1, v2, thresh, wv1,wvnum1)) {
\r
196 if(!get_vertex(i_marker_info2.x_coord, i_marker_info2.y_coord,v2, i_marker_info2.coord_num-1, thresh, wv2, wvnum2)) {
\r
199 if( wvnum1.get() == 1 && wvnum2.get() == 1 ) {
\r
201 vertex[2] = wv1[0];
\r
202 vertex[3] = wv2[0];
\r
212 i_marker_info2.vertex[0] = vertex[0];
\r
213 i_marker_info2.vertex[1] = vertex[1];
\r
214 i_marker_info2.vertex[2] = vertex[2];
\r
215 i_marker_info2.vertex[3] = vertex[3];
\r
216 i_marker_info2.vertex[4] = i_marker_info2.coord_num-1;
\r
221 * int arGetContour( ARInt16 *limage, int *label_ref,int label, int clip[4], ARMarkerInfo2 *marker_info2 )
\r
223 * detectMarker関数から使う関数です。marker_holder[i_holder_num]にオブジェクトが無ければまず新規に作成し、もし
\r
224 * 既に存在すればそこにマーカー情報を上書きして記録します。
\r
230 * 検出したマーカーからマーカーオブジェクトを生成して返す。
\r
231 * @throws NyARException
\r
233 private NyARMarker arGetContour(int i_holder_num,short[][] limage, int[] label_ref,int label, int[] clip) throws NyARException
\r
235 final int[] xdir={0, 1, 1, 1, 0,-1,-1,-1}; //static int xdir[8] = { 0, 1, 1, 1, 0,-1,-1,-1};
\r
236 final int[] ydir={-1,-1, 0, 1, 1, 1, 0,-1};//static int ydir[8] = {-1,-1, 0, 1, 1, 1, 0,-1};
\r
237 //ShortPointer p1;//ARInt16 *p1;
\r
238 int sx=0, sy=0, dir;
\r
243 //p1=ShortPointer.wrap(limage,j*xsize+clip.get());//p1 = &(limage[j*xsize+clip[0]]);
\r
244 for( i = clip[0]; i <= clip[1]; i++){//for( i = clip[0]; i <= clip[1]; i++, p1++ ) {
\r
245 if(limage[j][i] > 0 && label_ref[(limage[j][i])-1] == label ) {//if( *p1 > 0 && label_ref[(*p1)-1] == label ) {
\r
250 if(i> clip[1]){//if( i > clip[1] ) {
\r
251 System.out.println("??? 1");//printf();
\r
252 throw new NyARException();//return(-1);
\r
255 //マーカーホルダが既に確保済みかを調べる
\r
256 if(marker_holder[i_holder_num]==null){
\r
258 marker_holder[i_holder_num]=new NyARMarker();
\r
260 NyARMarker marker_ref=marker_holder[i_holder_num];
\r
263 marker_ref.coord_num=1;//marker_info2->coord_num = 1;
\r
264 marker_ref.x_coord[0]=sx;//marker_info2->x_coord[0] = sx;
\r
265 marker_ref.y_coord[0]=sy;//marker_info2->y_coord[0] = sy;
\r
269 int r=marker_ref.y_coord[marker_ref.coord_num-1];
\r
270 int c=marker_ref.x_coord[marker_ref.coord_num-1];
\r
271 //p1 = &(limage[marker_info2->y_coord[marker_info2->coord_num-1] * xsize+ marker_info2->x_coord[marker_info2->coord_num-1]]);
\r
274 if(limage[r+ydir[dir]][c+xdir[dir]]>0){//if( p1[ydir[dir]*xsize+xdir[dir]] > 0 ){
\r
280 System.out.println("??? 2");//printf("??? 2\n");
\r
281 throw new NyARException();//return(-1);
\r
283 marker_ref.x_coord[marker_ref.coord_num]= marker_ref.x_coord[marker_ref.coord_num-1] + xdir[dir];//marker_info2->x_coord[marker_info2->coord_num]= marker_info2->x_coord[marker_info2->coord_num-1] + xdir[dir];
\r
284 marker_ref.y_coord[marker_ref.coord_num]= marker_ref.y_coord[marker_ref.coord_num-1] + ydir[dir];//marker_info2->y_coord[marker_info2->coord_num]= marker_info2->y_coord[marker_info2->coord_num-1] + ydir[dir];
\r
285 if( marker_ref.x_coord[marker_ref.coord_num] == sx && marker_ref.y_coord[marker_ref.coord_num] == sy ){
\r
288 marker_ref.coord_num++;
\r
289 if( marker_ref.coord_num == marker_ref.x_coord.length-1){//if( marker_info2.coord_num == Config.AR_CHAIN_MAX-1 ){
\r
290 System.out.println("??? 3");//printf("??? 3\n");
\r
291 throw new NyARException();//return(-1);
\r
296 for(i=1;i<marker_ref.coord_num;i++) {// for(i=1;i<marker_info2->coord_num;i++) {
\r
297 d = (marker_ref.x_coord[i]-sx)*(marker_ref.x_coord[i]-sx)+ (marker_ref.y_coord[i]-sy)*(marker_ref.y_coord[i]-sy);// d = (marker_info2->x_coord[i]-sx)*(marker_info2->x_coord[i]-sx)+ (marker_info2->y_coord[i]-sy)*(marker_info2->y_coord[i]-sy);
\r
304 int[] wx=new int[v1];//new int[Config.AR_CHAIN_MAX];
\r
305 int[] wy=new int[v1]; //new int[Config.AR_CHAIN_MAX];
\r
306 for(i=0;i<v1;i++) {
\r
307 wx[i] = marker_ref.x_coord[i];//wx[i] = marker_info2->x_coord[i];
\r
308 wy[i] = marker_ref.y_coord[i];//wy[i] = marker_info2->y_coord[i];
\r
310 for(i=v1;i<marker_ref.coord_num;i++) {//for(i=v1;i<marker_info2->coord_num;i++) {
\r
311 marker_ref.x_coord[i-v1] = marker_ref.x_coord[i];//marker_info2->x_coord[i-v1] = marker_info2->x_coord[i];
\r
312 marker_ref.y_coord[i-v1] = marker_ref.y_coord[i];//marker_info2->y_coord[i-v1] = marker_info2->y_coord[i];
\r
314 for(i=0;i<v1;i++) {
\r
315 marker_ref.x_coord[i-v1+marker_ref.coord_num] = wx[i];//marker_info2->x_coord[i-v1+marker_info2->coord_num] = wx[i];
\r
316 marker_ref.y_coord[i-v1+marker_ref.coord_num] = wy[i];//marker_info2->y_coord[i-v1+marker_info2->coord_num] = wy[i];
\r
318 marker_ref.x_coord[marker_ref.coord_num] = marker_ref.x_coord[0];//marker_info2->x_coord[marker_info2->coord_num] = marker_info2->x_coord[0];
\r
319 marker_ref.y_coord[marker_ref.coord_num] = marker_ref.y_coord[0];//marker_info2->y_coord[marker_info2->coord_num] = marker_info2->y_coord[0];
\r
320 marker_ref.coord_num++;//marker_info2->coord_num++;
\r
325 * ARMarkerInfo2 *arDetectMarker2( ARInt16 *limage, int label_num, int *label_ref,int *warea, double *wpos, int *wclip,int area_max, int area_min, double factor, int *marker_num )
\r
327 * ラベリング情報からマーカー一覧を作成して保持します。
\r
328 * この関数を実行すると、前回のdetectMarker関数で計算した保持値は破壊されます。
\r
329 * @param i_labeling
\r
330 * ラベリング済みの情報を持つラベリングオブジェクト
\r
334 * @throws NyARException
\r
336 // public void detectMarker(short[][] limage,int label_num,int[] label_ref,int[] warea,double[] wpos,int[] wclip,int area_max, int area_min, double factor) throws JartkException
\r
337 public void detectMarker(NyARLabeling i_labeling,double factor) throws NyARException
\r
342 int[] warea =i_labeling.getArea();
\r
343 int label_num =i_labeling.getLabelNum();
\r
344 int[][] wclip =i_labeling.getClip();
\r
345 double[] wpos =i_labeling.getPos();
\r
346 short[][] limage =i_labeling.getLabelImg();
\r
347 int[] label_ref =i_labeling.getLabelRef();
\r
354 for(int i=0; i<label_num; i++ ) {
\r
355 if( warea[i] < area_min || warea[i] > area_max ){
\r
358 if( wclip[i][0] == 1 || wclip[i][1] == xsize-2 ){//if( wclip[i*4+0] == 1 || wclip[i*4+1] == xsize-2 ){
\r
361 if( wclip[i][2] == 1 || wclip[i][3] == ysize-2 ){//if( wclip[i*4+2] == 1 || wclip[i*4+3] == ysize-2 ){
\r
364 //ret = arGetContour( limage, label_ref, i+1,&(wclip[i*4]), &(marker_info2[marker_num2]));
\r
365 arGetContour(marker_num2,limage, label_ref, i+1,wclip[i]);
\r
367 boolean ret = check_square( warea[i], marker_holder[marker_num2], factor );//ret = check_square( warea[i], &(marker_info2[marker_num2]), factor );
\r
369 //後半で整理するからここはいらない。// marker_holder[marker_num2]=null;
\r
372 marker_holder[marker_num2].area = warea[i];
\r
373 marker_holder[marker_num2].pos[0] = wpos[i*2+0];
\r
374 marker_holder[marker_num2].pos[1] = wpos[i*2+1];
\r
377 if( marker_num2 == marker_holder.length){
\r
381 for(int i=0; i < marker_num2; i++ ) {
\r
382 for(int j=i+1; j < marker_num2; j++ ) {
\r
383 d = (marker_holder[i].pos[0] - marker_holder[j].pos[0])*
\r
384 (marker_holder[i].pos[0] - marker_holder[j].pos[0])+
\r
385 (marker_holder[i].pos[1] - marker_holder[j].pos[1])*
\r
386 (marker_holder[i].pos[1] - marker_holder[j].pos[1]);
\r
387 if(marker_holder[i].area >marker_holder[j].area ) {
\r
388 if( d <marker_holder[i].area / 4 ) {
\r
389 marker_holder[j].area = 0;
\r
392 if( d < marker_holder[j].area / 4 ) {
\r
393 marker_holder[i].area = 0;
\r
399 //エリアが0のマーカーを外した配列を作って、その数もついでに計算
\r
400 for(int i=0;i<marker_num2;i++){
\r
401 if(marker_holder[i].area==0.0){
\r
404 marker_info2_array[marker_num]=marker_holder[i];
\r
407 // for( i=0; i < marker_num2; i++ ) {
\r
408 // if( marker_info2_array[i].area == 0.0 ) {
\r
409 // for( j=i+1; j < marker_num2; j++ ){
\r
410 // marker_info2_array[j-1] = marker_info2_array[j];
\r
416 // marker_num=marker_num2;//*marker_num = marker_num2;
\r
417 //return( &(marker_info2[0]) );
\r