/*
* PROJECT: NyARToolkit
* --------------------------------------------------------------------------------
* This work is based on the original ARToolKit developed by
* Hirokazu Kato
* Mark Billinghurst
* HITLab, University of Washington, Seattle
* http://www.hitl.washington.edu/artoolkit/
*
* The NyARToolkit is Java version ARToolkit class library.
* Copyright (C)2008 R.Iizuka
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this framework; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* For further information please contact.
* http://nyatla.jp/nyatoolkit/
* <airmail(at)ebony.plala.or.jp>
*
*/
package jp.nyatla.nyartoolkit.core;
import jp.nyatla.nyartoolkit.NyARException;
/**
* イメージからマーカー情報を検出するクラス。
* このクラスは、arDetectMarker2.cとの置き換えになります。
* ラベリング済みのラスタデータからマーカー位置を検出して、結果を保持します。
*
*/
public class NyARDetectMarker
{
private static final int AR_AREA_MAX=
100000;//#define AR_AREA_MAX 100000
private static final int AR_AREA_MIN=
70;//#define AR_AREA_MIN 70
// private final NyARMarker[] marker_holder; //マーカーデータの保持配列
// private final NyARMarker[] marker_info2_array;//マーカーデータのインデックス配列
// private int marker_num;
private int width,height
;
/**
* 最大i_squre_max個のマーカーを検出するクラスを作成する。
* @param i_width
* @param i_height
*/
public NyARDetectMarker
(int i_width,
int i_height
)
{
this.
width =i_width
;
this.
height=i_height
;
// this.marker_holder=new NyARMarker[i_squre_max];
// this.marker_info2_array=new NyARMarker[i_squre_max];
// //先にマーカーホルダにオブジェクトを作っておく
// for(int i=0;i<i_squre_max;i++){
// this.marker_holder[i]=new NyARMarker();
// }
}
private static final int AR_CHAIN_MAX=
10000;
private final int[] wk_arGetContour_xdir=
{0,
1,
1,
1,
0,-
1,-
1,-
1};
private final int[] wk_arGetContour_ydir=
{-
1,-
1,
0,
1,
1,
1,
0,-
1};
private final int[] wk_arGetContour_xcoord=
new int[AR_CHAIN_MAX
];
private final int[] wk_arGetContour_ycoord=
new int[AR_CHAIN_MAX
];
/**
* int arGetContour( ARInt16 *limage, int *label_ref,int label, int clip[4], ARMarkerInfo2 *marker_info2 )
* 関数の代替品
* detectMarker関数から使う関数です。o_markerにlabelとclipで示される1個のマーカーを格納します。
* marker_holder[i_holder_num]にオブジェクトが無ければまず新規に作成し、もし
* 既に存在すればそこにマーカー情報を上書きして記録します。
* Optimize:STEP[369->336]
* @param o_marker
* @param limage
* @param label_ref
* @param label
* @param clip
* @throws NyARException
*/
private final void arGetContour
(NyARMarker o_marker,
int[][] limage,
int[] label_ref,
int i_labelnum, NyARLabel i_label
) throws NyARException
{
final int[] xcoord=wk_arGetContour_xcoord
;
final int[] ycoord=wk_arGetContour_ycoord
;
final int[] xdir=wk_arGetContour_xdir
; //static int xdir[8] = { 0, 1, 1, 1, 0,-1,-1,-1};
final int[] ydir=wk_arGetContour_ydir
;//static int ydir[8] = {-1,-1, 0, 1, 1, 1, 0,-1};
//ShortPointer p1;//ARInt16 *p1;
int coord_num
;
int sx=
0, sy=
0, dir
;
int dmax, d, v1=
0;
int i, j,w
;
int[] limage_j
;
j = i_label.
clip2;
limage_j=limage
[j
];
final int clip1=i_label.
clip1;
//p1=ShortPointer.wrap(limage,j*xsize+clip.get());//p1 = &(limage[j*xsize+clip[0]]);
for( i = i_label.
clip0; i
<= clip1
; i++
){//for( i = clip[0]; i <= clip[1]; i++, p1++ ) {
w=limage_j
[i
];
if(w
> 0 && label_ref
[w-
1] == i_labelnum
) {//if( *p1 > 0 && label_ref[(*p1)-1] == label ) {
sx = i
;
sy = j
;
break;
}
}
if(i
>clip1
){//if( i > clip[1] ) {
System.
out.
println("??? 1");//printf();
throw new NyARException
();//return(-1);
}
// //マーカーホルダが既に確保済みかを調べる
// if(marker_holder[i_holder_num]==null){
// //確保していなければ確保
// marker_holder[i_holder_num]=new NyARMarker();
// }
coord_num=
1;//marker_info2->coord_num = 1;
xcoord
[0]=sx
;//marker_info2->x_coord[0] = sx;
ycoord
[0]=sy
;//marker_info2->y_coord[0] = sy;
dir =
5;
int r,c
;
c=xcoord
[0];
r=ycoord
[0];
dmax=
0;
//本家はdmaxの作成とxcoordの作成を別のループでやってるけど、非効率なので統合
for(;;){
//xcoord[1]-xcoord[n]までのデータを作る。
// 1個前のxcoordとycoordはループ後半で格納される。
// c=xcoord[coord_num-1];
// r=ycoord[coord_num-1];
//p1 = &(limage[marker_info2->y_coord[marker_info2->coord_num-1] * xsize+ marker_info2->x_coord[marker_info2->coord_num-1]]);
dir =
(dir+
5)%8
;
for(i=
0;i
<8;i++
) {
if(limage
[r+ydir
[dir
]][c+xdir
[dir
]]>0){//if( p1[ydir[dir]*xsize+xdir[dir]] > 0 ){
break;
}
dir =
(dir+
1)%8
;
}
if( i ==
8 ){
System.
out.
println("??? 2");//printf("??? 2\n");
throw new NyARException
();//return(-1);
}
// xcoordとycoordをc,rにも保存
c= c + xdir
[dir
];//marker_info2->x_coord[marker_info2->coord_num]= marker_info2->x_coord[marker_info2->coord_num-1] + xdir[dir];
r= r + ydir
[dir
];//marker_info2->y_coord[marker_info2->coord_num]= marker_info2->y_coord[marker_info2->coord_num-1] + ydir[dir];
xcoord
[coord_num
]=c
;//marker_info2->x_coord[marker_info2->coord_num]= marker_info2->x_coord[marker_info2->coord_num-1] + xdir[dir];
ycoord
[coord_num
]=r
;//marker_info2->y_coord[marker_info2->coord_num]= marker_info2->y_coord[marker_info2->coord_num-1] + ydir[dir];
if(c == sx
&& r == sy
){
break;
}
//dmaxの計算
d=
(c-sx
)*(c-sx
)+
(r-sy
)*(r-sy
);
if( d
> dmax
) {
dmax = d
;
v1 = coord_num
;
}
//終了条件判定
coord_num++
;
if(coord_num == AR_CHAIN_MAX-
1){//if( marker_info2.coord_num == Config.AR_CHAIN_MAX-1 ){
System.
out.
println("??? 3");//printf("??? 3\n");
throw new NyARException
();//return(-1);
}
}
//
// dmax = 0;
// for(i=1;i<coord_num;i++) {// for(i=1;i<marker_info2->coord_num;i++) {
// 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);
// if( d > dmax ) {
// dmax = d;
// v1 = i;
// }
// }
//NyARMarkerへcoord情報をセット
//coordの並び替えと保存はNyARMarkerへ移動
o_marker.
setCoordXY(v1,coord_num,xcoord,ycoord
);
return;
}
/**
* 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 )
* 関数の代替品
* ラベリング情報からマーカー一覧を作成してo_marker_listを更新します。
* 関数はo_marker_listに重なりを除外したマーカーリストを作成します。
*
* @param i_labeling
* ラベリング済みの情報を持つラベリングオブジェクト
* @param i_factor
* 何かの閾値?
* @param o_marker_list
* 抽出したマーカーを格納するリスト
* @throws NyARException
*/
public final void detectMarker
(NyARLabeling i_labeling,
double i_factor,NyARMarkerList o_marker_list
) throws NyARException
{
int label_area
;
int i
;
int xsize, ysize
;
NyARLabel
[] labels=i_labeling.
getLabel();
// int[] warea =i_labeling.getArea();
int label_num =i_labeling.
getLabelNum();
// int[][] wclip =i_labeling.getClip();
// double[] wpos =i_labeling.getPos();
int[][] limage=i_labeling.
getLabelImg();
int[] label_ref =i_labeling.
getLabelRef();
//マーカーホルダをリセット
o_marker_list.
reset();
// marker_num=0;
xsize =width
;
ysize =height
;
// マーカーをmarker_holderに蓄積する。
NyARMarker current_marker=o_marker_list.
getCurrentHolder();
NyARLabel label_pt
;
for(i=
0; i
<label_num
; i++
){
label_pt=labels
[i
];
label_area=label_pt.
area;
if(label_area
< AR_AREA_MIN || label_area
> AR_AREA_MAX
){
continue;
}
if( label_pt.
clip0 ==
1 || label_pt.
clip1 == xsize-
2 ){//if( wclip[i*4+0] == 1 || wclip[i*4+1] == xsize-2 ){
continue;
}
if( label_pt.
clip2 ==
1 || label_pt.
clip3 == ysize-
2 ){//if( wclip[i*4+2] == 1 || wclip[i*4+3] == ysize-2 ){
continue;
}
//ret = arGetContour( limage, label_ref, i+1,&(wclip[i*4]), &(marker_info2[marker_num2]));
arGetContour
(current_marker,limage, label_ref, i+
1,label_pt
);
if(!current_marker.
checkSquare(label_area,i_factor,label_pt.
pos_x,label_pt.
pos_y)){
//後半で整理するからここはいらない。// marker_holder[marker_num2]=null;
continue;
}
// この3行はcheckSquareの最終段に含める。
// marker_holder[marker_num2].area = warea[i];
// marker_holder[marker_num2].pos[0] = wpos[i*2+0];
// marker_holder[marker_num2].pos[1] = wpos[i*2+1];
//マーカー検出→次のホルダを取得
current_marker=o_marker_list.
getNextHolder();
//マーカーリストが上限に達したか確認
if(current_marker==
null){
break;
}
}
//マーカーリストを整理(重なり処理とかはマーカーリストに責務押し付け)
o_marker_list.
updateMarkerArray();
// 重なり処理かな?
// double[] pos_j,pos_i;
// for(i=0; i < marker_num2; i++ ){
// pos_i=marker_holder[i].pos;
// for(j=i+1; j < marker_num2; j++ ) {
// pos_j=marker_holder[j].pos;
// d = (pos_i[0] - pos_j[0])*(pos_i[0] - pos_j[0])+
// (pos_i[1] - pos_j[1])*(pos_i[1] - pos_j[1]);
// if(marker_holder[i].area >marker_holder[j].area ) {
// if( d <marker_holder[i].area / 4 ) {
// marker_holder[j].area = 0;
// }
// }else{
// if( d < marker_holder[j].area / 4 ) {
// marker_holder[i].area = 0;
// }
// }
// }
// }
// みつかったマーカーを整理する。
// エリアが0のマーカーを外した配列を作って、その数もついでに計算
// for(i=0;i<marker_num2;i++){
// if(marker_holder[i].area==0.0){
// continue;
// }
// marker_info2_array[marker_num]=marker_holder[i];
// marker_num++;
// }
// for( i=0; i < marker_num2; i++ ) {
// if( marker_info2_array[i].area == 0.0 ) {
// for( j=i+1; j < marker_num2; j++ ){
// marker_info2_array[j-1] = marker_info2_array[j];
// }
// marker_num2--;
// }
// }
// 発見したマーカー数をセット
// marker_num=marker_num2;//*marker_num = marker_num2;
// return( &(marker_info2[0]) );
return;
}
}