OSDN Git Service

[Backup]NyARToolkit for Java
[nyartoolkit-and/nyartoolkit-and.git] / src / jp / nyatla / nyartoolkit / processor / SingleNyIdMarkerProcesser.java
1 /* \r
2  * Capture Test NyARToolkitサンプルプログラム\r
3  * --------------------------------------------------------------------------------\r
4  * The NyARToolkit is Java edition ARToolKit class library.\r
5  * Copyright (C)2008-2009 Ryo Iizuka\r
6  *\r
7  * This program is free software: you can redistribute it and/or modify\r
8  * it under the terms of the GNU General Public License as published by\r
9  * the Free Software Foundation, either version 3 of the License, or\r
10  * (at your option) any later version.\r
11  * \r
12  * This program is distributed in the hope that it will be useful,\r
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15  * GNU General Public License for more details.\r
16  *\r
17  * You should have received a copy of the GNU General Public License\r
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
19  * \r
20  * For further information please contact.\r
21  *      http://nyatla.jp/nyatoolkit/\r
22  *      <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>\r
23  * \r
24  */\r
25 package jp.nyatla.nyartoolkit.processor;\r
26 \r
27 import jp.nyatla.nyartoolkit.NyARException;\r
28 import jp.nyatla.nyartoolkit.core.param.*;\r
29 import jp.nyatla.nyartoolkit.core.raster.*;\r
30 import jp.nyatla.nyartoolkit.core.raster.rgb.*;\r
31 import jp.nyatla.nyartoolkit.core.transmat.*;\r
32 import jp.nyatla.nyartoolkit.core.rasterfilter.rgb2bin.*;\r
33 import jp.nyatla.nyartoolkit.core.types.*;\r
34 import jp.nyatla.nyartoolkit.nyidmarker.*;\r
35 import jp.nyatla.nyartoolkit.nyidmarker.data.*;\r
36 import jp.nyatla.nyartoolkit.core2.rasteranalyzer.threshold.*;\r
37 import jp.nyatla.nyartoolkit.core.squaredetect.*;\r
38 \r
39 public abstract class SingleNyIdMarkerProcesser\r
40 {\r
41         /**\r
42          * オーナーが自由に使えるタグ変数です。\r
43          */\r
44         public Object tag;\r
45 \r
46         /**\r
47          * ロスト遅延の管理\r
48          */\r
49         private int _lost_delay_count = 0;\r
50         private int _lost_delay = 5;\r
51 \r
52         private NyARSquareDetector_Rle _square_detect;\r
53         protected INyARTransMat _transmat;\r
54         private double _marker_width=100;\r
55 \r
56         private NyARSquareStack _square_list = new NyARSquareStack(100);\r
57         private INyIdMarkerDataEncoder _encoder;\r
58         private boolean _is_active;\r
59         private INyIdMarkerData _data_temp;\r
60         private INyIdMarkerData _data_current;\r
61 \r
62         private int _current_threshold=110;\r
63         // [AR]検出結果の保存用\r
64         private NyARBinRaster _bin_raster;\r
65 \r
66         private NyARRasterFilter_ARToolkitThreshold _tobin_filter;\r
67 \r
68         private NyIdMarkerPickup _id_pickup = new NyIdMarkerPickup();\r
69 \r
70 \r
71         protected SingleNyIdMarkerProcesser()\r
72         {\r
73                 return;\r
74         }\r
75         protected void initInstance(NyARParam i_param,INyIdMarkerDataEncoder i_encoder,int i_raster_format) throws NyARException\r
76         {\r
77                 NyARIntSize scr_size = i_param.getScreenSize();\r
78                 // 解析オブジェクトを作る\r
79                 this._square_detect = new NyARSquareDetector_Rle(i_param.getDistortionFactor(), scr_size);\r
80                 this._transmat = new NyARTransMat(i_param);\r
81                 this._encoder=i_encoder;\r
82 \r
83                 // 2値画像バッファを作る\r
84                 this._bin_raster = new NyARBinRaster(scr_size.w, scr_size.h);\r
85                 //ワーク用のデータオブジェクトを2個作る\r
86                 this._is_active=false;\r
87                 this._data_temp=i_encoder.createDataInstance();\r
88                 this._data_current=i_encoder.createDataInstance();\r
89                 this._tobin_filter = new NyARRasterFilter_ARToolkitThreshold(110,i_raster_format);\r
90                 this._threshold_detect=new NyARRasterThresholdAnalyzer_SlidePTile(15,i_raster_format,4);\r
91                 return;\r
92                 \r
93         }\r
94 \r
95         public void setMarkerWidth(int i_width)\r
96         {\r
97                 this._marker_width=i_width;\r
98                 return;\r
99         }\r
100 \r
101         public void reset(boolean i_is_force)\r
102         {\r
103                 if (this._data_current!=null && i_is_force == false) {\r
104                         // 強制書き換えでなければイベントコール\r
105                         this.onLeaveHandler();\r
106                 }\r
107                 // カレントマーカをリセット\r
108                 this._data_current = null;\r
109                 return;\r
110         }\r
111 \r
112         public void detectMarker(INyARRgbRaster i_raster) throws NyARException\r
113         {\r
114                 // サイズチェック\r
115                 if (!this._bin_raster.getSize().isEqualSize(i_raster.getSize().w, i_raster.getSize().h)) {\r
116                         throw new NyARException();\r
117                 }\r
118                 // ラスタを2値イメージに変換する.\r
119                 this._tobin_filter.setThreshold(this._current_threshold);\r
120                 this._tobin_filter.doFilter(i_raster, this._bin_raster);\r
121 \r
122                 NyARSquareStack square_stack = this._square_list;\r
123                 // スクエアコードを探す\r
124                 this._square_detect.detectMarker(this._bin_raster, square_stack);\r
125                 // 認識処理\r
126                 if (!this._is_active) {\r
127                         // マーカ未認識→新規認識\r
128                         detectNewMarker(i_raster, square_stack);\r
129                 } else {\r
130                         // マーカ認識依頼→継続認識\r
131                         detectExistMarker(i_raster, square_stack);\r
132                 }\r
133                 return;\r
134         }\r
135 \r
136         \r
137         private final NyIdMarkerPattern _marker_data=new NyIdMarkerPattern();\r
138         private final NyIdMarkerParam _marker_param=new NyIdMarkerParam();\r
139         private NyARRasterThresholdAnalyzer_SlidePTile _threshold_detect;\r
140         \r
141         /**新規マーカ検索 現在認識中のマーカがないものとして、最も認識しやすいマーカを1個認識します。\r
142          */\r
143         private void detectNewMarker(INyARRgbRaster i_raster, NyARSquareStack i_stack) throws NyARException\r
144         {\r
145                 NyIdMarkerParam param=this._marker_param;\r
146                 NyIdMarkerPattern patt_data  =this._marker_data;\r
147                 int number_of_square = i_stack.getLength();\r
148                 NyARSquare current_square=null;\r
149                 INyIdMarkerData marker_id=null;\r
150                 for (int i = 0; i < number_of_square; i++) {\r
151                         // 評価基準になるパターンをイメージから切り出す\r
152                         current_square=i_stack.getItem(i);\r
153                         if (!this._id_pickup.pickFromRaster(i_raster,current_square, patt_data, param)) {\r
154                                 continue;\r
155                         }\r
156                         //エンコード\r
157                         if(!this._encoder.encode(patt_data,this._data_temp)){\r
158                                 continue;\r
159                         }\r
160                         //認識率が一番高いもの(占有面積が一番大きいもの)を選択する(省略)\r
161                         //id認識が成功したら終了\r
162                         marker_id=this._data_temp;\r
163                         break;\r
164                 }\r
165                 \r
166                 // 認識状態を更新\r
167                 final boolean is_id_found=updateStatus(current_square,marker_id, param);\r
168 \r
169                 //閾値フィードバック(detectExistMarkerにもあるよ)\r
170                 if(is_id_found){\r
171                         //マーカがあれば、マーカの周辺閾値を反映\r
172                         this._current_threshold=(this._current_threshold+param.threshold)/2;\r
173                 }else{\r
174                         //マーカがなければ、探索+DualPTailで基準輝度検索\r
175                         this._threshold_detect.analyzeRaster(i_raster);\r
176                         this._current_threshold=(this._current_threshold+this._threshold_detect.getThreshold())/2;\r
177                 }\r
178                 return;\r
179         }\r
180 \r
181         /**マーカの継続認識 現在認識中のマーカを優先して認識します。 \r
182          * (注)この機能はたぶん今後いろいろ発展するからNewと混ぜないこと。\r
183          */\r
184         private void detectExistMarker(INyARRgbRaster i_raster, NyARSquareStack i_stack) throws NyARException\r
185         {\r
186                 NyIdMarkerParam param=this._marker_param;\r
187                 NyIdMarkerPattern patt_data  =this._marker_data;\r
188                 int number_of_square = i_stack.getLength();\r
189                 NyARSquare current_square=null;\r
190                 INyIdMarkerData marker_id=null;\r
191                 for (int i = 0; i < number_of_square; i++){\r
192                         //idマーカを認識\r
193                         current_square=i_stack.getItem(i);\r
194                         if (!this._id_pickup.pickFromRaster(i_raster, current_square, patt_data, param)) {\r
195                                 continue;\r
196                         }\r
197                         if(!this._encoder.encode(patt_data,this._data_temp)){\r
198                                 continue;\r
199                         }\r
200                         //現在認識中のidか確認\r
201                         if(!this._data_current.isEqual((this._data_temp))){\r
202                                 continue;\r
203                         }\r
204                         //現在認識中のものであれば、終了\r
205                         marker_id=this._data_temp;\r
206                         break;\r
207                 }\r
208                 // 認識状態を更新\r
209                 final boolean is_id_found=updateStatus(current_square,marker_id,param);\r
210 \r
211                 //閾値フィードバック(detectExistMarkerにもあるよ)\r
212                 if(is_id_found){\r
213                         //マーカがあれば、マーカの周辺閾値を反映\r
214                         this._current_threshold=(this._current_threshold+param.threshold)/2;\r
215                 }else{\r
216                         //マーカがなければ、探索+DualPTailで基準輝度検索\r
217                         this._threshold_detect.analyzeRaster(i_raster);\r
218                         this._current_threshold=(this._current_threshold+this._threshold_detect.getThreshold())/2;\r
219                 }\r
220                 return;\r
221         }\r
222 \r
223         private NyARTransMatResult __NyARSquare_result = new NyARTransMatResult();\r
224 \r
225         /**オブジェクトのステータスを更新し、必要に応じてハンドル関数を駆動します。\r
226          */\r
227         private boolean updateStatus(NyARSquare i_square, INyIdMarkerData i_marker_data,NyIdMarkerParam i_param)  throws NyARException\r
228         {\r
229                 boolean is_id_found=false;\r
230                 NyARTransMatResult result = this.__NyARSquare_result;\r
231                 if (!this._is_active) {// 未認識中\r
232                         if (i_marker_data==null) {// 未認識から未認識の遷移\r
233                                 // なにもしないよーん。\r
234                                 this._is_active=false;\r
235                         } else {// 未認識から認識の遷移\r
236                                 this._data_current.copyFrom(i_marker_data);\r
237                                 // イベント生成\r
238                                 // OnEnter\r
239                                 this.onEnterHandler(this._data_current);\r
240                                 // 変換行列を作成\r
241                                 this._transmat.transMat(i_square,i_param.direction, this._marker_width, result);\r
242                                 // OnUpdate\r
243                                 this.onUpdateHandler(i_square, result);\r
244                                 this._lost_delay_count = 0;\r
245                                 this._is_active=true;\r
246                                 is_id_found=true;\r
247                         }\r
248                 } else {// 認識中\r
249                         if (i_marker_data==null) {\r
250                                 // 認識から未認識の遷移\r
251                                 this._lost_delay_count++;\r
252                                 if (this._lost_delay < this._lost_delay_count) {\r
253                                         // OnLeave\r
254                                         this.onLeaveHandler();\r
255                                         this._is_active=false;\r
256                                 }\r
257                         } else if(this._data_current.isEqual(i_marker_data)) {\r
258                                 //同じidの再認識\r
259                                 this._transmat.transMat(i_square, i_param.direction, this._marker_width, result);\r
260                                 // OnUpdate\r
261                                 this.onUpdateHandler(i_square, result);\r
262                                 this._lost_delay_count = 0;\r
263                                 is_id_found=true;\r
264                         } else {// 異なるコードの認識→今はサポートしない。\r
265                                 throw new  NyARException();\r
266                         }\r
267                 }\r
268                 return is_id_found;\r
269         }       \r
270         //通知ハンドラ\r
271         protected abstract void onEnterHandler(INyIdMarkerData i_code);\r
272         protected abstract void onLeaveHandler();\r
273         protected abstract void onUpdateHandler(NyARSquare i_square, NyARTransMatResult result);\r
274 }\r