OSDN Git Service

[backup]NyARToolkit
[nyartoolkit-and/nyartoolkit-and.git] / trunk / src / jp / nyatla / nyartoolkit / core / squaredetect / ContourPickup.java
1 /* \r
2  * PROJECT: NyARToolkit\r
3  * --------------------------------------------------------------------------------\r
4  * This work is based on the original ARToolKit developed by\r
5  *   Hirokazu Kato\r
6  *   Mark Billinghurst\r
7  *   HITLab, University of Washington, Seattle\r
8  * http://www.hitl.washington.edu/artoolkit/\r
9  *\r
10  * The NyARToolkit is Java edition ARToolKit class library.\r
11  * Copyright (C)2008-2009 Ryo Iizuka\r
12  *\r
13  * This program is free software: you can redistribute it and/or modify\r
14  * it under the terms of the GNU General Public License as published by\r
15  * the Free Software Foundation, either version 3 of the License, or\r
16  * (at your option) any later version.\r
17  * \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
22  *\r
23  * You should have received a copy of the GNU General Public License\r
24  * along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
25  * \r
26  * For further information please contact.\r
27  *      http://nyatla.jp/nyatoolkit/\r
28  *      <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>\r
29  * \r
30  */\r
31 package jp.nyatla.nyartoolkit.core.squaredetect;\r
32 \r
33 import jp.nyatla.nyartoolkit.NyARException;\r
34 import jp.nyatla.nyartoolkit.core.raster.*;\r
35 import jp.nyatla.nyartoolkit.core.labeling.artoolkit.*;\r
36 \r
37 /**\r
38  * 輪郭線を取得するクラスです。\r
39  *\r
40  */\r
41 public class ContourPickup\r
42 {\r
43         //巡回参照できるように、テーブルを二重化\r
44         //                                           0  1  2  3  4  5  6  7   0  1  2  3  4  5  6\r
45         protected final static int[] _getContour_xdir = { 0, 1, 1, 1, 0,-1,-1,-1 , 0, 1, 1, 1, 0,-1,-1};\r
46         protected final static int[] _getContour_ydir = {-1,-1, 0, 1, 1, 1, 0,-1 ,-1,-1, 0, 1, 1, 1, 0};\r
47         public int getContour(NyARBinRaster i_raster,int i_entry_x,int i_entry_y,int i_array_size,int[] o_coord_x,int[] o_coord_y) throws NyARException\r
48         {\r
49                 assert(i_raster.isEqualBufferType(INyARRaster.BUFFERFORMAT_INT1D_BIN_8));\r
50                 return impl_getContour(i_raster,0,i_entry_x,i_entry_y,i_array_size,o_coord_x,o_coord_y);\r
51         }\r
52         /**\r
53          * \r
54          * @param i_raster\r
55          * @param i_th\r
56          * 画像を2値化するための閾値。暗点<=i_th<明点となります。\r
57          * @param i_entry_x\r
58          * 輪郭の追跡開始点を指定します。\r
59          * @param i_entry_y\r
60          * @param i_array_size\r
61          * @param o_coord_x\r
62          * @param o_coord_y\r
63          * @return\r
64          * @throws NyARException\r
65          */\r
66         public int getContour(NyARGrayscaleRaster i_raster,int i_th,int i_entry_x,int i_entry_y,int i_array_size,int[] o_coord_x,int[] o_coord_y) throws NyARException\r
67         {\r
68                 assert(i_raster.isEqualBufferType(INyARRaster.BUFFERFORMAT_INT1D_GRAY_8));\r
69                 return impl_getContour(i_raster,i_th,i_entry_x,i_entry_y,i_array_size,o_coord_x,o_coord_y);\r
70         }\r
71 \r
72         /**\r
73          * ラスタのエントリポイントから辿れる輪郭線を配列に返します。\r
74          * @param i_raster\r
75          * @param i_th\r
76          * 暗点<=th<明点\r
77          * @param i_entry_x\r
78          * @param i_entry_y\r
79          * @param i_array_size\r
80          * @param o_coord_x\r
81          * @param o_coord_y\r
82          * @return\r
83          * 輪郭線の長さを返します。\r
84          * @throws NyARException\r
85          */\r
86         private int impl_getContour(INyARRaster i_raster,int i_th,int i_entry_x,int i_entry_y,int i_array_size,int[] o_coord_x,int[] o_coord_y) throws NyARException\r
87         {\r
88                 final int[] xdir = _getContour_xdir;// static int xdir[8] = { 0, 1, 1, 1, 0,-1,-1,-1};\r
89                 final int[] ydir = _getContour_ydir;// static int ydir[8] = {-1,-1, 0, 1, 1, 1, 0,-1};\r
90 \r
91                 final int[] i_buf=(int[])i_raster.getBuffer();\r
92                 final int width=i_raster.getWidth();\r
93                 final int height=i_raster.getHeight();\r
94                 //クリップ領域の上端に接しているポイントを得る。\r
95 \r
96 \r
97                 int coord_num = 1;\r
98                 o_coord_x[0] = i_entry_x;\r
99                 o_coord_y[0] = i_entry_y;\r
100                 int dir = 5;\r
101 \r
102                 int c = i_entry_x;\r
103                 int r = i_entry_y;\r
104                 for (;;) {\r
105                         dir = (dir + 5) % 8;//dirの正規化\r
106                         //ここは頑張ればもっと最適化できると思うよ。\r
107                         //4隅以外の境界接地の場合に、境界チェックを省略するとかね。\r
108                         if(c>=1 && c<width-1 && r>=1 && r<height-1){\r
109                                 for(;;){//gotoのエミュレート用のfor文\r
110                                         //境界に接していないとき(暗点判定)\r
111                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {\r
112                                                 break;\r
113                                         }\r
114                                         dir++;\r
115                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {\r
116                                                 break;\r
117                                         }\r
118                                         dir++;\r
119                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {\r
120                                                 break;\r
121                                         }\r
122                                         dir++;\r
123                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {\r
124                                                 break;\r
125                                         }\r
126                                         dir++;\r
127                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {\r
128                                                 break;\r
129                                         }\r
130                                         dir++;\r
131                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {\r
132                                                 break;\r
133                                         }\r
134                                         dir++;\r
135                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {\r
136                                                 break;\r
137                                         }\r
138                                         dir++;\r
139                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {\r
140                                                 break;\r
141                                         }\r
142 /*\r
143                                         try{\r
144                                                 BufferedImage b=new BufferedImage(width,height,ColorSpace.TYPE_RGB);\r
145                                                 NyARRasterImageIO.copy(i_raster, b);\r
146                                         ImageIO.write(b,"png",new File("bug.png"));\r
147                                         }catch(Exception e){\r
148                                                 \r
149                                         }*/\r
150                                         //8方向全て調べたけどラベルが無いよ?\r
151                                         throw new NyARException();                      \r
152                                 }\r
153                         }else{\r
154                                 //境界に接しているとき                                \r
155                                 int i;\r
156                                 for (i = 0; i < 8; i++){                                \r
157                                         final int x=c + xdir[dir];\r
158                                         final int y=r + ydir[dir];\r
159                                         //境界チェック\r
160                                         if(x>=0 && x<width && y>=0 && y<height){\r
161                                                 if (i_buf[(y)*width+(x)] <= i_th) {\r
162                                                         break;\r
163                                                 }\r
164                                         }\r
165                                         dir++;//倍長テーブルを参照するので問題なし\r
166                                 }\r
167                                 if (i == 8) {\r
168                                         //8方向全て調べたけどラベルが無いよ?\r
169                                         throw new NyARException();// return(-1);\r
170                                 }                               \r
171                         }\r
172                         \r
173                         dir=dir% 8;//dirの正規化\r
174 \r
175                         // xcoordとycoordをc,rにも保存\r
176                         c = c + xdir[dir];\r
177                         r = r + ydir[dir];\r
178                         o_coord_x[coord_num] = c;\r
179                         o_coord_y[coord_num] = r;\r
180                         // 終了条件判定\r
181                         if (c == i_entry_x && r == i_entry_y){\r
182                                 coord_num++;\r
183                                 break;\r
184                         }\r
185                         coord_num++;\r
186                         if (coord_num == i_array_size) {\r
187                                 //輪郭が末端に達した\r
188                                 return coord_num;\r
189                         }\r
190                 }\r
191                 return coord_num;\r
192         }\r
193         public int getContour(NyARLabelingImage i_raster,int i_entry_x,int i_entry_y,int i_array_size,int[] o_coord_x,int[] o_coord_y) throws NyARException\r
194         {       \r
195                 final int[] xdir = _getContour_xdir;// static int xdir[8] = { 0, 1, 1, 1, 0,-1,-1,-1};\r
196                 final int[] ydir = _getContour_ydir;// static int ydir[8] = {-1,-1, 0, 1, 1, 1, 0,-1};\r
197 \r
198                 final int[] i_buf=(int[])i_raster.getBuffer();\r
199                 final int width=i_raster.getWidth();\r
200                 final int height=i_raster.getHeight();\r
201                 //クリップ領域の上端に接しているポイントを得る。\r
202                 int sx=i_entry_x;\r
203                 int sy=i_entry_y;\r
204 \r
205                 int coord_num = 1;\r
206                 o_coord_x[0] = sx;\r
207                 o_coord_y[0] = sy;\r
208                 int dir = 5;\r
209 \r
210                 int c = o_coord_x[0];\r
211                 int r = o_coord_y[0];\r
212                 for (;;) {\r
213                         dir = (dir + 5) % 8;//dirの正規化\r
214                         //ここは頑張ればもっと最適化できると思うよ。\r
215                         //4隅以外の境界接地の場合に、境界チェックを省略するとかね。\r
216                         if(c>=1 && c<width-1 && r>=1 && r<height-1){\r
217                                 for(;;){//gotoのエミュレート用のfor文\r
218                                         //境界に接していないとき\r
219                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] > 0) {\r
220                                                 break;\r
221                                         }\r
222                                         dir++;\r
223                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] > 0) {\r
224                                                 break;\r
225                                         }\r
226                                         dir++;\r
227                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] > 0) {\r
228                                                 break;\r
229                                         }\r
230                                         dir++;\r
231                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] > 0) {\r
232                                                 break;\r
233                                         }\r
234                                         dir++;\r
235                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] > 0) {\r
236                                                 break;\r
237                                         }\r
238                                         dir++;\r
239                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] > 0) {\r
240                                                 break;\r
241                                         }\r
242                                         dir++;\r
243                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] > 0) {\r
244                                                 break;\r
245                                         }\r
246                                         dir++;\r
247                                         if (i_buf[(r + ydir[dir])*width+(c + xdir[dir])] > 0) {\r
248                                                 break;\r
249                                         }\r
250                                         //8方向全て調べたけどラベルが無いよ?\r
251                                         throw new NyARException();                      \r
252                                 }\r
253                         }else{\r
254                                 //境界に接しているとき\r
255                                 int i;\r
256                                 for (i = 0; i < 8; i++){                                \r
257                                         final int x=c + xdir[dir];\r
258                                         final int y=r + ydir[dir];\r
259                                         //境界チェック\r
260                                         if(x>=0 && x<width && y>=0 && y<height){\r
261                                                 if (i_buf[(y)*width+(x)] > 0) {\r
262                                                         break;\r
263                                                 }\r
264                                         }\r
265                                         dir++;//倍長テーブルを参照するので問題なし\r
266                                 }\r
267                                 if (i == 8) {\r
268                                         //8方向全て調べたけどラベルが無いよ?\r
269                                         throw new NyARException();// return(-1);\r
270                                 }                               \r
271                         }\r
272                         \r
273                         dir=dir% 8;//dirの正規化\r
274 \r
275                         // xcoordとycoordをc,rにも保存\r
276                         c = c + xdir[dir];\r
277                         r = r + ydir[dir];\r
278                         o_coord_x[coord_num] = c;\r
279                         o_coord_y[coord_num] = r;\r
280                         // 終了条件判定\r
281                         if (c == sx && r == sy){\r
282                                 coord_num++;\r
283                                 break;\r
284                         }\r
285                         coord_num++;\r
286                         if (coord_num == i_array_size) {\r
287                                 //輪郭が末端に達した\r
288                                 return coord_num;\r
289                         }\r
290                 }\r
291                 return coord_num;\r
292         }\r
293 \r
294 }\r