Subversion Repositories AndroidProjects

Rev

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.detector;
33
 
34
import jp.nyatla.nyartoolkit.NyARException;
35
import jp.nyatla.nyartoolkit.core.*;
36
import jp.nyatla.nyartoolkit.core.match.NyARMatchPatt_Color_WITHOUT_PCA;
37
import jp.nyatla.nyartoolkit.core.raster.*;
38
 
39
 
40
 
41
class NyARDetectMarkerResult
42
{
43
    public int arcode_id;
44
    public int direction;
45
    public double confidence;
46
    public NyARSquare ref_square;
47
}
48
class NyARDetectMarkerResultHolder
49
{
50
    public NyARDetectMarkerResult[] result_array=new NyARDetectMarkerResult[1];
51
    /**
52
     * result_holderを最大i_reserve_size個の要素を格納できるように予約します。
53
     * @param i_reserve_size
54
     */
55
    public void reservHolder(int i_reserve_size)
56
    {
57
        if(i_reserve_size>=result_array.length){
58
            int new_size=i_reserve_size+5;
59
            result_array=new NyARDetectMarkerResult[new_size];
60
            for(int i=0;i<new_size;i++){
61
                result_array[i]=new NyARDetectMarkerResult();
62
            }
63
        }
64
    }
65
}
66
/**
67
 * 複数のマーカーを検出し、それぞれに最も一致するARコードを、コンストラクタで登録したARコードから
68
 * 探すクラスです。最大300個を認識しますが、ゴミラベルを認識したりするので100個程度が限界です。
69
 *
70
 */
71
public class NyARDetectMarker{
72
    private static final int AR_SQUARE_MAX=300;
73
    private boolean is_continue=false;
74
    private NyARMatchPatt_Color_WITHOUT_PCA match_patt;
75
    private NyARDetectSquare square;
76
    private final NyARSquareList square_list=new NyARSquareList(AR_SQUARE_MAX);
77
    private NyARCode[] codes;
78
    protected NyARTransMat transmat;
79
    private double[] marker_width;
80
    private int number_of_code;
81
    //検出結果の保存用
82
    private NyARColorPatt patt;
83
 
84
    private NyARDetectMarkerResultHolder result_holder=new NyARDetectMarkerResultHolder();
85
 
86
    /**
87
     * 複数のマーカーを検出し、最も一致するARCodeをi_codeから検索するオブジェクトを作ります。
88
     * @param i_param
89
     * カメラパラメータを指定します。
90
     * @param i_code
91
     * 検出するマーカーのARCode配列を指定します。配列要素のインデックス番号が、そのままgetARCodeIndex関数で
92
     * 得られるARCodeインデックスになります。
93
     * 例えば、要素[1]のARCodeに一致したマーカーである場合は、getARCodeIndexは1を返します。
94
     * 先頭からi_number_of_code個の要素には、有効な値を指定する必要があります。
95
     * @param i_marker_width
96
     * i_codeのマーカーサイズをミリメートルで指定した配列を指定します。
97
     * 先頭からi_number_of_code個の要素には、有効な値を指定する必要があります。
98
     * @param i_number_of_code
99
     * i_codeに含まれる、ARCodeの数を指定します。
100
     * @throws NyARException
101
     */
102
    public NyARDetectMarker(NyARParam i_param,NyARCode[] i_code,double[] i_marker_width,int i_number_of_code) throws NyARException
103
    {
104
        //解析オブジェクトを作る
105
        this.square=new NyARDetectSquare(i_param);
106
        this.transmat=new NyARTransMat_O2(i_param);
107
        //比較コードを保存
108
        this.codes=i_code;
109
        //比較コードの解像度は全部同じかな?(違うとパターンを複数種つくらないといけないから)
110
        int cw=i_code[0].getWidth();
111
        int ch=i_code[0].getHeight();
112
        for(int i=1;i<i_number_of_code;i++){
113
            if(cw!=i_code[i].getWidth() || ch!=i_code[i].getHeight()){
114
                //違う解像度のが混ざっている。
115
                throw new NyARException();
116
            }
117
        }      
118
        //評価パターンのホルダを作る
119
        this.patt=new NyARColorPatt_O3(cw,ch);
120
        this.number_of_code=i_number_of_code;
121
 
122
        this.marker_width=i_marker_width;
123
        //評価器を作る。
124
        this.match_patt=new NyARMatchPatt_Color_WITHOUT_PCA(); 
125
    }
126
    /**
127
     * i_imageにマーカー検出処理を実行し、結果を記録します。
128
     * @param i_image
129
     * マーカーを検出するイメージを指定します。
130
     * @param i_thresh
131
     * 検出閾値を指定します。0~255の範囲で指定してください。
132
     * 通常は100~130くらいを指定します。
133
     * @return
134
     * 見つかったマーカーの数を返します。
135
     * マーカーが見つからない場合は0を返します。
136
     * @throws NyARException
137
     */
138
    public int detectMarkerLite(NyARRaster i_image,int i_thresh) throws NyARException
139
    {
140
        NyARSquareList l_square_list=this.square_list;
141
        //スクエアコードを探す
142
        square.detectSquare(i_image, i_thresh,l_square_list);
143
 
144
        final int number_of_square=l_square_list.getSquareNum();
145
        //コードは見つかった?
146
        if(number_of_square<1){
147
            //ないや。おしまい。
148
            return 0;
149
        }
150
        //保持リストのサイズを調整
151
        this.result_holder.reservHolder(number_of_square);     
152
 
153
        //1スクエア毎に、一致するコードを決定していく
154
        for(int i=0;i<number_of_square;i++)
155
        {
156
            NyARSquare square=l_square_list.getSquare(i);
157
            //評価基準になるパターンをイメージから切り出す
158
            if(!this.patt.pickFromRaster(i_image,square)){
159
                //イメージの切り出しは失敗することもある。
160
                continue;
161
            }
162
            //パターンを評価器にセット
163
            if(!this.match_patt.setPatt(this.patt)){
164
                //計算に失敗した。      
165
                throw new NyARException();
166
            }
167
            //コードと順番に比較していく
168
            int code_index=0;
169
            match_patt.evaluate(codes[0]);
170
            double confidence=match_patt.getConfidence();
171
            int direction=match_patt.getDirection();
172
            for(int i2=1;i2<this.number_of_code;i2++)
173
            {
174
                //コードと比較する
175
                match_patt.evaluate(codes[i2]);
176
                double c2=match_patt.getConfidence();
177
                if(confidence>c2){
178
                    continue;
179
                }
180
                //より一致するARCodeの情報を保存
181
                code_index  =i2;
182
                direction   =match_patt.getDirection();
183
                confidence  =c2;
184
            }
185
            //i番目のパターン情報を保存する。
186
            final NyARDetectMarkerResult result=this.result_holder.result_array[i];
187
            result.arcode_id =code_index;
188
            result.confidence=confidence;
189
            result.direction =direction;
190
            result.ref_square=square;
191
        }
192
        return number_of_square;
193
    }
194
    /**
195
     * i_indexのマーカーに対する変換行列を計算し、結果値をo_resultへ格納します。
196
     * 直前に実行したdetectMarkerLiteが成功していないと使えません。
197
     * @param i_index
198
     * マーカーのインデックス番号を指定します。
199
     * 直前に実行したdetectMarkerLiteの戻り値未満かつ0以上である必要があります。
200
     * @param o_result
201
     * 結果値を受け取るオブジェクトを指定してください。
202
     * @throws NyARException
203
     */
204
    public void getTransmationMatrix(int i_index,NyARTransMatResult o_result) throws NyARException
205
    {
206
        final NyARDetectMarkerResult result=this.result_holder.result_array[i_index];
207
        //一番一致したマーカーの位置とかその辺を計算
208
        if(is_continue){
209
            transmat.transMatContinue(result.ref_square,result.direction,marker_width[result.arcode_id],o_result);
210
        }else{
211
            transmat.transMat(result.ref_square,result.direction,marker_width[result.arcode_id],o_result);
212
        }
213
        return;
214
    }
215
    /**
216
     * i_indexのマーカーの一致度を返します。
217
     * @param i_index
218
     * マーカーのインデックス番号を指定します。
219
     * 直前に実行したdetectMarkerLiteの戻り値未満かつ0以上である必要があります。
220
     * @return
221
     * マーカーの一致度を返します。0~1までの値をとります。
222
     * 一致度が低い場合には、誤認識の可能性が高くなります。
223
     * @throws NyARException
224
     */
225
    public double getConfidence(int i_index)
226
    {
227
        return this.result_holder.result_array[i_index].confidence;
228
    }
229
    /**
230
     * i_indexのマーカーの方位を返します。
231
     * @param i_index
232
     * マーカーのインデックス番号を指定します。
233
     * 直前に実行したdetectMarkerLiteの戻り値未満かつ0以上である必要があります。
234
     * @return
235
     * 0,1,2,3の何れかを返します。
236
     */    
237
    public int getDirection(int i_index)
238
    {
239
        return this.result_holder.result_array[i_index].direction;
240
    }
241
    /**
242
     * i_indexのマーカーのARCodeインデックスを返します。
243
     * @param i_index
244
     * マーカーのインデックス番号を指定します。
245
     * 直前に実行したdetectMarkerLiteの戻り値未満かつ0以上である必要があります。
246
     * @return
247
     */    
248
    public int getARCodeIndex(int i_index)
249
    {
250
        return this.result_holder.result_array[i_index].arcode_id;
251
    }    
252
    /**
253
     * getTransmationMatrixの計算モードを設定します。
254
     * @param i_is_continue
255
     * TRUEなら、transMatContinueを使用します。
256
     * FALSEなら、transMatを使用します。
257
     */
258
    public void setContinueMode(boolean i_is_continue)
259
    {
260
        this.is_continue=i_is_continue;
261
    }
262
 
263
}
264
 
265
 
266
 
267
 
268
 
269
 
270
 
271
 
272
 
273
 
274
 
275
 
276
 
277
 
278