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 | |||
| 35 | |||
| 36 | |||
| 37 | import jp.nyatla.nyartoolkit.NyARException; |
||
| 38 | |||
| 39 | |||
| 40 | |||
| 41 | |||
| 42 | /** |
||
| 43 | * イメージからマーカー情報を検出するクラス。 |
||
| 44 | * このクラスは、arDetectMarker2.cとの置き換えになります。 |
||
| 45 | * ラベリング済みのラスタデータからマーカー位置を検出して、結果を保持します。 |
||
| 46 | * |
||
| 47 | */ |
||
| 48 | public class NyARDetectMarker { |
||
| 49 | private static final int AR_AREA_MAX=100000;//#define AR_AREA_MAX 100000 |
||
| 50 | private static final int AR_AREA_MIN=70;//#define AR_AREA_MIN 70 |
||
| 51 | |||
| 52 | // private final NyARMarker[] marker_holder; //マーカーデータの保持配列 |
||
| 53 | // private final NyARMarker[] marker_info2_array;//マーカーデータのインデックス配列 |
||
| 54 | // private int marker_num; |
||
| 55 | private int width,height; |
||
| 56 | /** |
||
| 57 | * 最大i_squre_max個のマーカーを検出するクラスを作成する。 |
||
| 58 | * @param i_width |
||
| 59 | * @param i_height |
||
| 60 | */ |
||
| 61 | public NyARDetectMarker(int i_width,int i_height) |
||
| 62 | { |
||
| 63 | this.width =i_width; |
||
| 64 | this.height=i_height; |
||
| 65 | |||
| 66 | // this.marker_holder=new NyARMarker[i_squre_max]; |
||
| 67 | // this.marker_info2_array=new NyARMarker[i_squre_max]; |
||
| 68 | // //先にマーカーホルダにオブジェクトを作っておく |
||
| 69 | // for(int i=0;i<i_squre_max;i++){ |
||
| 70 | // this.marker_holder[i]=new NyARMarker(); |
||
| 71 | // } |
||
| 72 | } |
||
| 73 | private static final int AR_CHAIN_MAX=10000; |
||
| 74 | private final int[] wk_arGetContour_xdir={0, 1, 1, 1, 0,-1,-1,-1}; |
||
| 75 | private final int[] wk_arGetContour_ydir={-1,-1, 0, 1, 1, 1, 0,-1}; |
||
| 76 | private final int[] wk_arGetContour_xcoord=new int[AR_CHAIN_MAX]; |
||
| 77 | private final int[] wk_arGetContour_ycoord=new int[AR_CHAIN_MAX]; |
||
| 78 | /** |
||
| 79 | * int arGetContour( ARInt16 *limage, int *label_ref,int label, int clip[4], ARMarkerInfo2 *marker_info2 ) |
||
| 80 | * 関数の代替品 |
||
| 81 | * detectMarker関数から使う関数です。o_markerにlabelとclipで示される1個のマーカーを格納します。 |
||
| 82 | * marker_holder[i_holder_num]にオブジェクトが無ければまず新規に作成し、もし |
||
| 83 | * 既に存在すればそこにマーカー情報を上書きして記録します。 |
||
| 84 | * Optimize:STEP[369->336] |
||
| 85 | * @param o_marker |
||
| 86 | * @param limage |
||
| 87 | * @param label_ref |
||
| 88 | * @param label |
||
| 89 | * @param clip |
||
| 90 | * @throws NyARException |
||
| 91 | */ |
||
| 92 | private final void arGetContour(NyARMarker o_marker,int[][] limage, int[] label_ref,int i_labelnum, NyARLabel i_label) throws NyARException |
||
| 93 | { |
||
| 94 | final int[] xcoord=wk_arGetContour_xcoord; |
||
| 95 | final int[] ycoord=wk_arGetContour_ycoord; |
||
| 96 | final int[] xdir=wk_arGetContour_xdir; //static int xdir[8] = { 0, 1, 1, 1, 0,-1,-1,-1}; |
||
| 97 | final int[] ydir=wk_arGetContour_ydir;//static int ydir[8] = {-1,-1, 0, 1, 1, 1, 0,-1}; |
||
| 98 | //ShortPointer p1;//ARInt16 *p1; |
||
| 99 | int coord_num; |
||
| 100 | int sx=0, sy=0, dir; |
||
| 101 | int dmax, d, v1=0; |
||
| 102 | int i, j,w; |
||
| 103 | |||
| 104 | int[] limage_j; |
||
| 105 | j = i_label.clip2; |
||
| 106 | limage_j=limage[j]; |
||
| 107 | final int clip1=i_label.clip1; |
||
| 108 | //p1=ShortPointer.wrap(limage,j*xsize+clip.get());//p1 = &(limage[j*xsize+clip[0]]); |
||
| 109 | for( i = i_label.clip0; i <= clip1; i++){//for( i = clip[0]; i <= clip[1]; i++, p1++ ) { |
||
| 110 | w=limage_j[i]; |
||
| 111 | if(w > 0 && label_ref[w-1] == i_labelnum ) {//if( *p1 > 0 && label_ref[(*p1)-1] == label ) { |
||
| 112 | sx = i; |
||
| 113 | sy = j; |
||
| 114 | break; |
||
| 115 | } |
||
| 116 | } |
||
| 117 | if(i>clip1){//if( i > clip[1] ) { |
||
| 118 | System.out.println("??? 1");//printf(); |
||
| 119 | throw new NyARException();//return(-1); |
||
| 120 | } |
||
| 121 | |||
| 122 | // //マーカーホルダが既に確保済みかを調べる |
||
| 123 | // if(marker_holder[i_holder_num]==null){ |
||
| 124 | // //確保していなければ確保 |
||
| 125 | // marker_holder[i_holder_num]=new NyARMarker(); |
||
| 126 | // } |
||
| 127 | |||
| 128 | |||
| 129 | coord_num=1;//marker_info2->coord_num = 1; |
||
| 130 | xcoord[0]=sx;//marker_info2->x_coord[0] = sx; |
||
| 131 | ycoord[0]=sy;//marker_info2->y_coord[0] = sy; |
||
| 132 | dir = 5; |
||
| 133 | |||
| 134 | int r,c; |
||
| 135 | c=xcoord[0]; |
||
| 136 | r=ycoord[0]; |
||
| 137 | dmax=0; |
||
| 138 | //本家はdmaxの作成とxcoordの作成を別のループでやってるけど、非効率なので統合 |
||
| 139 | for(;;){ |
||
| 140 | //xcoord[1]-xcoord[n]までのデータを作る。 |
||
| 141 | |||
| 142 | // 1個前のxcoordとycoordはループ後半で格納される。 |
||
| 143 | // c=xcoord[coord_num-1]; |
||
| 144 | // r=ycoord[coord_num-1]; |
||
| 145 | //p1 = &(limage[marker_info2->y_coord[marker_info2->coord_num-1] * xsize+ marker_info2->x_coord[marker_info2->coord_num-1]]); |
||
| 146 | dir = (dir+5)%8; |
||
| 147 | for(i=0;i<8;i++) { |
||
| 148 | if(limage[r+ydir[dir]][c+xdir[dir]]>0){//if( p1[ydir[dir]*xsize+xdir[dir]] > 0 ){ |
||
| 149 | break; |
||
| 150 | } |
||
| 151 | dir = (dir+1)%8; |
||
| 152 | } |
||
| 153 | if( i == 8 ){ |
||
| 154 | System.out.println("??? 2");//printf("??? 2\n"); |
||
| 155 | throw new NyARException();//return(-1); |
||
| 156 | } |
||
| 157 | // xcoordとycoordをc,rにも保存 |
||
| 158 | c= c + xdir[dir];//marker_info2->x_coord[marker_info2->coord_num]= marker_info2->x_coord[marker_info2->coord_num-1] + xdir[dir]; |
||
| 159 | r= r + ydir[dir];//marker_info2->y_coord[marker_info2->coord_num]= marker_info2->y_coord[marker_info2->coord_num-1] + ydir[dir]; |
||
| 160 | xcoord[coord_num]=c;//marker_info2->x_coord[marker_info2->coord_num]= marker_info2->x_coord[marker_info2->coord_num-1] + xdir[dir]; |
||
| 161 | ycoord[coord_num]=r;//marker_info2->y_coord[marker_info2->coord_num]= marker_info2->y_coord[marker_info2->coord_num-1] + ydir[dir]; |
||
| 162 | if(c == sx && r == sy ){ |
||
| 163 | break; |
||
| 164 | } |
||
| 165 | //dmaxの計算 |
||
| 166 | d=(c-sx)*(c-sx)+(r-sy)*(r-sy); |
||
| 167 | if( d > dmax ) { |
||
| 168 | dmax = d; |
||
| 169 | v1 = coord_num; |
||
| 170 | } |
||
| 171 | //終了条件判定 |
||
| 172 | coord_num++; |
||
| 173 | if(coord_num == AR_CHAIN_MAX-1){//if( marker_info2.coord_num == Config.AR_CHAIN_MAX-1 ){ |
||
| 174 | System.out.println("??? 3");//printf("??? 3\n"); |
||
| 175 | throw new NyARException();//return(-1); |
||
| 176 | } |
||
| 177 | } |
||
| 178 | // |
||
| 179 | // dmax = 0; |
||
| 180 | // for(i=1;i<coord_num;i++) {// for(i=1;i<marker_info2->coord_num;i++) { |
||
| 181 | // d = (xcoord[i]-sx)*(xcoord[i]-sx)+ (ycoord[i]-sy)*(ycoord[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); |
||
| 182 | // if( d > dmax ) { |
||
| 183 | // dmax = d; |
||
| 184 | // v1 = i; |
||
| 185 | // } |
||
| 186 | // } |
||
| 187 | //NyARMarkerへcoord情報をセット |
||
| 188 | //coordの並び替えと保存はNyARMarkerへ移動 |
||
| 189 | o_marker.setCoordXY(v1,coord_num,xcoord,ycoord); |
||
| 190 | return; |
||
| 191 | } |
||
| 192 | |||
| 193 | /** |
||
| 194 | * 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 ) |
||
| 195 | * 関数の代替品 |
||
| 196 | * ラベリング情報からマーカー一覧を作成してo_marker_listを更新します。 |
||
| 197 | * 関数はo_marker_listに重なりを除外したマーカーリストを作成します。 |
||
| 198 | * |
||
| 199 | * @param i_labeling |
||
| 200 | * ラベリング済みの情報を持つラベリングオブジェクト |
||
| 201 | * @param i_factor |
||
| 202 | * 何かの閾値? |
||
| 203 | * @param o_marker_list |
||
| 204 | * 抽出したマーカーを格納するリスト |
||
| 205 | * @throws NyARException |
||
| 206 | */ |
||
| 207 | public final void detectMarker(NyARLabeling i_labeling,double i_factor,NyARMarkerList o_marker_list) throws NyARException |
||
| 208 | { |
||
| 209 | int label_area; |
||
| 210 | int i; |
||
| 211 | int xsize, ysize; |
||
| 212 | NyARLabel[] labels=i_labeling.getLabel(); |
||
| 213 | // int[] warea =i_labeling.getArea(); |
||
| 214 | int label_num =i_labeling.getLabelNum(); |
||
| 215 | // int[][] wclip =i_labeling.getClip(); |
||
| 216 | // double[] wpos =i_labeling.getPos(); |
||
| 217 | int[][] limage=i_labeling.getLabelImg(); |
||
| 218 | int[] label_ref =i_labeling.getLabelRef(); |
||
| 219 | |||
| 220 | //マーカーホルダをリセット |
||
| 221 | o_marker_list.reset(); |
||
| 222 | // marker_num=0; |
||
| 223 | xsize =width; |
||
| 224 | ysize =height; |
||
| 225 | // マーカーをmarker_holderに蓄積する。 |
||
| 226 | NyARMarker current_marker=o_marker_list.getCurrentHolder(); |
||
| 227 | NyARLabel label_pt; |
||
| 228 | for(i=0; i<label_num; i++ ){ |
||
| 229 | label_pt=labels[i]; |
||
| 230 | label_area=label_pt.area; |
||
| 231 | if(label_area < AR_AREA_MIN || label_area > AR_AREA_MAX ){ |
||
| 232 | continue; |
||
| 233 | } |
||
| 234 | if( label_pt.clip0 == 1 || label_pt.clip1 == xsize-2 ){//if( wclip[i*4+0] == 1 || wclip[i*4+1] == xsize-2 ){ |
||
| 235 | continue; |
||
| 236 | } |
||
| 237 | if( label_pt.clip2 == 1 || label_pt.clip3 == ysize-2 ){//if( wclip[i*4+2] == 1 || wclip[i*4+3] == ysize-2 ){ |
||
| 238 | continue; |
||
| 239 | } |
||
| 240 | //ret = arGetContour( limage, label_ref, i+1,&(wclip[i*4]), &(marker_info2[marker_num2])); |
||
| 241 | arGetContour(current_marker,limage, label_ref, i+1,label_pt); |
||
| 242 | |||
| 243 | if(!current_marker.checkSquare(label_area,i_factor,label_pt.pos_x,label_pt.pos_y)){ |
||
| 244 | //後半で整理するからここはいらない。// marker_holder[marker_num2]=null; |
||
| 245 | continue; |
||
| 246 | } |
||
| 247 | // この3行はcheckSquareの最終段に含める。 |
||
| 248 | // marker_holder[marker_num2].area = warea[i]; |
||
| 249 | // marker_holder[marker_num2].pos[0] = wpos[i*2+0]; |
||
| 250 | // marker_holder[marker_num2].pos[1] = wpos[i*2+1]; |
||
| 251 | //マーカー検出→次のホルダを取得 |
||
| 252 | current_marker=o_marker_list.getNextHolder(); |
||
| 253 | //マーカーリストが上限に達したか確認 |
||
| 254 | if(current_marker==null){ |
||
| 255 | break; |
||
| 256 | } |
||
| 257 | } |
||
| 258 | //マーカーリストを整理(重なり処理とかはマーカーリストに責務押し付け) |
||
| 259 | o_marker_list.updateMarkerArray(); |
||
| 260 | // 重なり処理かな? |
||
| 261 | // double[] pos_j,pos_i; |
||
| 262 | // for(i=0; i < marker_num2; i++ ){ |
||
| 263 | // pos_i=marker_holder[i].pos; |
||
| 264 | // for(j=i+1; j < marker_num2; j++ ) { |
||
| 265 | // pos_j=marker_holder[j].pos; |
||
| 266 | // d = (pos_i[0] - pos_j[0])*(pos_i[0] - pos_j[0])+ |
||
| 267 | // (pos_i[1] - pos_j[1])*(pos_i[1] - pos_j[1]); |
||
| 268 | // if(marker_holder[i].area >marker_holder[j].area ) { |
||
| 269 | // if( d <marker_holder[i].area / 4 ) { |
||
| 270 | // marker_holder[j].area = 0; |
||
| 271 | // } |
||
| 272 | // }else{ |
||
| 273 | // if( d < marker_holder[j].area / 4 ) { |
||
| 274 | // marker_holder[i].area = 0; |
||
| 275 | // } |
||
| 276 | // } |
||
| 277 | // } |
||
| 278 | // } |
||
| 279 | // みつかったマーカーを整理する。 |
||
| 280 | // エリアが0のマーカーを外した配列を作って、その数もついでに計算 |
||
| 281 | // for(i=0;i<marker_num2;i++){ |
||
| 282 | // if(marker_holder[i].area==0.0){ |
||
| 283 | // continue; |
||
| 284 | // } |
||
| 285 | // marker_info2_array[marker_num]=marker_holder[i]; |
||
| 286 | // marker_num++; |
||
| 287 | // } |
||
| 288 | // for( i=0; i < marker_num2; i++ ) { |
||
| 289 | // if( marker_info2_array[i].area == 0.0 ) { |
||
| 290 | // for( j=i+1; j < marker_num2; j++ ){ |
||
| 291 | // marker_info2_array[j-1] = marker_info2_array[j]; |
||
| 292 | // } |
||
| 293 | // marker_num2--; |
||
| 294 | // } |
||
| 295 | // } |
||
| 296 | // 発見したマーカー数をセット |
||
| 297 | // marker_num=marker_num2;//*marker_num = marker_num2; |
||
| 298 | // return( &(marker_info2[0]) ); |
||
| 299 | return; |
||
| 300 | } |
||
| 301 | |||
| 302 | } |