OSDN Git Service

Merge branch 'git-svn'
[nyartoolkit-and/nyartoolkit-and.git] / tags / 1.1.1 / src / jp / nyatla / nyartoolkit / core / NyARColorPatt_O3.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 version ARToolkit class library.\r
11  * Copyright (C)2008 R.Iizuka\r
12  *\r
13  * This program is free software; you can redistribute it and/or\r
14  * modify it under the terms of the GNU General Public License\r
15  * as published by the Free Software Foundation; either version 2\r
16  * of the License, or (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 framework; if not, write to the Free Software\r
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
26  * \r
27  * For further information please contact.\r
28  *      http://nyatla.jp/nyatoolkit/\r
29  *      <airmail(at)ebony.plala.or.jp>\r
30  * \r
31  */\r
32 package jp.nyatla.nyartoolkit.core;\r
33 \r
34 \r
35 \r
36 import jp.nyatla.nyartoolkit.NyARException;\r
37 import jp.nyatla.nyartoolkit.core.raster.NyARRaster;\r
38 \r
39 /**\r
40  * 24ビットカラーのマーカーを保持するために使うクラスです。\r
41  * このクラスは、ARToolkitのパターンと、ラスタから取得したパターンを保持します。\r
42  * 演算順序を含む最適化をしたもの\r
43  *\r
44  */\r
45 public class NyARColorPatt_O3 implements NyARColorPatt\r
46 {\r
47     private static final int AR_PATT_SAMPLE_NUM=64;//#define   AR_PATT_SAMPLE_NUM   64\r
48     private int extpat[][][];\r
49     private int width;\r
50     private int height;\r
51     public NyARColorPatt_O3(int i_width,int i_height)\r
52     {\r
53         this.width=i_width;\r
54         this.height=i_height;\r
55         this.extpat=new int[i_height][i_width][3];\r
56     }\r
57     public int[][][] getPatArray()\r
58     {\r
59         return extpat;\r
60     }\r
61     public int getWidth()\r
62     {\r
63         return width;\r
64     }\r
65     public int getHeight()\r
66     {\r
67         return height;\r
68     }\r
69     private final NyARMat wk_get_cpara_a=new NyARMat(8,8);\r
70     private final NyARMat wk_get_cpara_b=new NyARMat(8,1);\r
71 \r
72     /**\r
73      * \r
74      * @param world\r
75      * @param vertex\r
76      * @param para\r
77      * [3x3]\r
78      * @throws NyARException\r
79      */\r
80     /**\r
81      * @param world\r
82      * @param vertex\r
83      * @param o_para\r
84      * @throws NyARException\r
85      */\r
86     private void get_cpara(double vertex_0[], double vertex_1[],NyARMat o_para) throws NyARException\r
87     {\r
88         double world[][]=this.wk_pickFromRaster_world;\r
89         NyARMat a =wk_get_cpara_a;//次処理で値を設定するので、初期化不要// new NyARMat( 8, 8 );\r
90         double[][] a_array=a.getArray();\r
91         NyARMat b =wk_get_cpara_b;//次処理で値を設定するので、初期化不要// new NyARMat( 8, 1 );\r
92         double[][] b_array=b.getArray();\r
93         double[] a_pt0,a_pt1,world_pti;\r
94             \r
95         for(int i = 0; i < 4; i++ ) {\r
96             a_pt0=a_array[i*2];\r
97             a_pt1=a_array[i*2+1];\r
98             world_pti=world[i];\r
99             \r
100             a_pt0[0]=world_pti[0];//a->m[i*16+0]  = world[i][0];\r
101             a_pt0[1]=world_pti[1];//a->m[i*16+1]  = world[i][1];\r
102             a_pt0[2]=1.0;//a->m[i*16+2]  = 1.0;\r
103             a_pt0[3]=0.0;//a->m[i*16+3]  = 0.0;\r
104             a_pt0[4]=0.0;//a->m[i*16+4]  = 0.0;\r
105             a_pt0[5]=0.0;//a->m[i*16+5]  = 0.0;\r
106             a_pt0[6]=-world_pti[0] * vertex_0[i];//a->m[i*16+6]  = -world[i][0] * vertex[i][0];\r
107             a_pt0[7]=-world_pti[1] * vertex_0[i];//a->m[i*16+7]  = -world[i][1] * vertex[i][0];\r
108             a_pt1[0]=0.0;//a->m[i*16+8]  = 0.0;\r
109             a_pt1[1]=0.0;//a->m[i*16+9]  = 0.0;\r
110             a_pt1[2]=0.0;//a->m[i*16+10] = 0.0;\r
111             a_pt1[3]=world_pti[0];//a->m[i*16+11] = world[i][0];\r
112             a_pt1[4]=world_pti[1];//a->m[i*16+12] = world[i][1];\r
113             a_pt1[5]=1.0;//a->m[i*16+13] = 1.0;\r
114             a_pt1[6]=-world_pti[0] * vertex_1[i];//a->m[i*16+14] = -world[i][0] * vertex[i][1];\r
115             a_pt1[7]=-world_pti[1] * vertex_1[i];//a->m[i*16+15] = -world[i][1] * vertex[i][1];\r
116             b_array[i*2+0][0]=vertex_0[i];//b->m[i*2+0] = vertex[i][0];\r
117             b_array[i*2+1][0]=vertex_1[i];//b->m[i*2+1] = vertex[i][1];\r
118         }\r
119         a.matrixSelfInv();\r
120             \r
121 \r
122         o_para.matrixMul(a, b);\r
123 \r
124         \r
125 \r
126     }\r
127 \r
128   //   private final double[] wk_pickFromRaster_para=new double[9];//[3][3];\r
129     private final double[][] wk_pickFromRaster_world={//double    world[4][2];\r
130             {100.0,     100.0},\r
131             {100.0+10.0,100.0},\r
132             {100.0+10.0,100.0 + 10.0},\r
133             {100.0,     100.0 + 10.0}\r
134     };\r
135     /**\r
136      * pickFromRaster関数から使う変数です。\r
137      *\r
138      */\r
139     private static void initValue_wk_pickFromRaster_ext_pat2(int[][][] i_ext_pat2,int i_width,int i_height)\r
140     {\r
141         int i,i2;\r
142         int[][] pt2;\r
143         int[]   pt1;\r
144         for(i=i_height-1;i>=0;i--){\r
145             pt2=i_ext_pat2[i];\r
146             for(i2=i_width-1;i2>=0;i2--){\r
147                 pt1=pt2[i2];\r
148                 pt1[0]=0;\r
149                 pt1[1]=0;\r
150                 pt1[2]=0;\r
151             }\r
152         }\r
153     }\r
154     private final double[][] wk_pickFromRaster_local=new double[2][4];\r
155     private final NyARMat wk_pickFromRaster_cpara=new NyARMat(8,1);\r
156     /**\r
157      * imageから、i_markerの位置にあるパターンを切り出して、保持します。\r
158      * Optimize:STEP[769->750]\r
159      * @param image\r
160      * @param i_marker\r
161      * @throws Exception\r
162      */\r
163     public void pickFromRaster(NyARRaster image, NyARMarker i_marker) throws NyARException\r
164     {\r
165         NyARMat cpara=this.wk_pickFromRaster_cpara;\r
166         //localの計算\r
167         int[] x_coord=i_marker.x_coord;\r
168         int[] y_coord=i_marker.y_coord;\r
169         int[] vertex=i_marker.mkvertex;\r
170         double[] local_0=wk_pickFromRaster_local[0];//double    local[4][2];    \r
171         double[] local_1=wk_pickFromRaster_local[1];//double    local[4][2];    \r
172         for(int i = 0; i < 4; i++ ) {\r
173             local_0[i] = x_coord[vertex[i]];\r
174             local_1[i] = y_coord[vertex[i]];\r
175         }\r
176         //xdiv2,ydiv2の計算\r
177         int xdiv2, ydiv2;\r
178         int l1,l2;\r
179         double w1,w2;\r
180 \r
181         //x計算\r
182         w1=local_0[0] - local_0[1];\r
183         w2=local_1[0] - local_1[1];\r
184         l1 = (int)(w1*w1+w2*w2);\r
185         w1=local_0[2] - local_0[3];\r
186         w2=local_1[2] - local_1[3];\r
187         l2 = (int)(w1*w1+w2*w2);\r
188         if( l2 > l1 ){\r
189             l1 = l2;\r
190         }\r
191         l1=l1/4;\r
192         xdiv2 =this.width;\r
193         while( xdiv2*xdiv2 < l1 ){\r
194             xdiv2*=2;\r
195         }\r
196         if( xdiv2 > AR_PATT_SAMPLE_NUM)\r
197         {\r
198             xdiv2 =AR_PATT_SAMPLE_NUM;\r
199         }\r
200         \r
201         //y計算\r
202         w1=local_0[1] - local_0[2];\r
203         w2=local_1[1] - local_1[2];\r
204         l1 = (int)(w1*w1+ w2*w2);\r
205         w1=local_0[3] - local_0[0];\r
206         w2=local_1[3] - local_1[0];\r
207         l2 = (int)(w1*w1+ w2*w2);\r
208         if( l2 > l1 ){\r
209             l1 = l2;\r
210         }\r
211         ydiv2 =this.height;\r
212         l1=l1/4;\r
213         while( ydiv2*ydiv2 < l1 ){\r
214             ydiv2*=2;\r
215         }\r
216         if( ydiv2 >AR_PATT_SAMPLE_NUM)\r
217         {\r
218             ydiv2 = AR_PATT_SAMPLE_NUM;\r
219         }       \r
220         \r
221         //cparaの計算\r
222         get_cpara(local_0,local_1,cpara);\r
223         updateExtpat(image,cpara,xdiv2,ydiv2);\r
224 \r
225         return;\r
226     }\r
227     //かなり大きいワークバッファを取るな…。\r
228     private double[] wk_updateExtpat_para00_xw;\r
229     private double[] wk_updateExtpat_para10_xw;\r
230     private double[] wk_updateExtpat_para20_xw;\r
231     private int[] wk_updateExtpat_rgb_buf;\r
232     private int[] wk_updateExtpat_x_rgb_index;\r
233     private int[] wk_updateExtpat_y_rgb_index;\r
234     private int[] wk_updateExtpat_i_rgb_index;\r
235     private int wk_updateExtpat_buffer_size=0;\r
236 \r
237     /**\r
238      * ワークバッファを予約する\r
239      * @param i_xdiv2\r
240      */\r
241     private void reservWorkBuffers(int i_xdiv2)\r
242     {\r
243         if(this.wk_updateExtpat_buffer_size<i_xdiv2){\r
244             wk_updateExtpat_para00_xw=new double[i_xdiv2];\r
245             wk_updateExtpat_para10_xw=new double[i_xdiv2];\r
246             wk_updateExtpat_para20_xw=new double[i_xdiv2];\r
247             wk_updateExtpat_rgb_buf=new int[i_xdiv2*3];\r
248             wk_updateExtpat_x_rgb_index=new int[i_xdiv2];\r
249             wk_updateExtpat_y_rgb_index=new int[i_xdiv2];\r
250             wk_updateExtpat_i_rgb_index=new int[i_xdiv2];\r
251             this.wk_updateExtpat_buffer_size=i_xdiv2;\r
252         }\r
253         //十分なら何もしない。\r
254         return;\r
255     }\r
256     \r
257     private void updateExtpat(NyARRaster image,NyARMat i_cpara,int i_xdiv2,int i_ydiv2) throws NyARException\r
258     {\r
259         int img_x=image.getWidth();\r
260         int img_y=image.getHeight();\r
261         final int[][][] L_extpat=this.extpat;\r
262         final int L_WIDTH=this.width;\r
263         final int L_HEIGHT=this.height;\r
264         /*wk_pickFromRaster_ext_pat2ワーク変数を初期化する。*/\r
265         //int[][][] ext_pat2=wk_pickFromRaster_ext_pat2;//ARUint32  ext_pat2[AR_PATT_SIZE_Y][AR_PATT_SIZE_X][3];\r
266         int extpat_j[][],extpat_j_i[];\r
267         //int ext_pat2_j[][],ext_pat2_j_i[];\r
268 \r
269         initValue_wk_pickFromRaster_ext_pat2(L_extpat,L_WIDTH,L_HEIGHT);\r
270 \r
271         double[][] cpara_array=i_cpara.getArray();\r
272         double para21_x_yw,para01_x_yw,para11_x_yw;\r
273         double para00,para01,para02,para10,para11,para12,para20,para21;\r
274         para00 = cpara_array[0*3+0][0];//para[i][0] = c->m[i*3+0];\r
275         para01 = cpara_array[0*3+1][0];//para[i][1] = c->m[i*3+1];\r
276         para02 = cpara_array[0*3+2][0];//para[i][2] = c->m[i*3+2];\r
277         para10 = cpara_array[1*3+0][0];//para[i][0] = c->m[i*3+0];\r
278         para11 = cpara_array[1*3+1][0];//para[i][1] = c->m[i*3+1];\r
279         para12 = cpara_array[1*3+2][0];//para[i][2] = c->m[i*3+2];\r
280         para20 = cpara_array[2*3+0][0];//para[2][0] = c->m[2*3+0];\r
281         para21 = cpara_array[2*3+1][0];//para[2][1] = c->m[2*3+1];\r
282 \r
283         \r
284         double          d,yw;\r
285         int             xc, yc;\r
286         int i,j;\r
287         //      arGetCode_put_zero(ext_pat2);//put_zero( (ARUint8 *)ext_pat2, AR_PATT_SIZE_Y*AR_PATT_SIZE_X*3*sizeof(ARUint32) );\r
288         int xdiv = i_xdiv2/L_WIDTH;//xdiv = xdiv2/Config.AR_PATT_SIZE_X;\r
289         int ydiv = i_ydiv2/L_HEIGHT;//ydiv = ydiv2/Config.AR_PATT_SIZE_Y;\r
290         \r
291         //計算バッファを予約する\r
292         this.reservWorkBuffers(i_xdiv2);        \r
293         double[] para00_xw=this.wk_updateExtpat_para00_xw;\r
294         double[] para10_xw=this.wk_updateExtpat_para10_xw;\r
295         double[] para20_xw=this.wk_updateExtpat_para20_xw;\r
296         int[] x_rgb_index=this.wk_updateExtpat_x_rgb_index;\r
297         int[] y_rgb_index=this.wk_updateExtpat_y_rgb_index;\r
298         int[] i_rgb_index=this.wk_updateExtpat_i_rgb_index;\r
299         int[] rgb_buf=this.wk_updateExtpat_rgb_buf;\r
300         double xw;\r
301         for(i=0;i<i_xdiv2;i++){\r
302             xw= 102.5 + 5.0 * ((double)i+0.5) /i_xdiv2;\r
303             para20_xw[i]=para20*xw;\r
304             para00_xw[i]=para00*xw;\r
305             para10_xw[i]=para10*xw;\r
306         }\r
307 \r
308         int index_num;\r
309 \r
310         \r
311         for(j = 0; j < i_ydiv2; j++ ) {\r
312             yw = 102.5 + 5.0 * ((double)j+0.5) /i_ydiv2;\r
313             para21_x_yw=para21*yw+1.0;\r
314             para11_x_yw=para11*yw+para12;\r
315             para01_x_yw=para01*yw+para02;\r
316             extpat_j=L_extpat[j/ydiv];\r
317             index_num=0;\r
318             //ステップ1.RGB取得用のマップを作成\r
319             for(i = 0; i < i_xdiv2; i++ ) {\r
320                 d = para20_xw[i] + para21_x_yw;\r
321                 if( d == 0 ){\r
322                     throw new NyARException();\r
323                 }\r
324                 xc = (int)((para00_xw[i] + para01_x_yw)/d);\r
325                 yc = (int)((para10_xw[i] + para11_x_yw)/d);\r
326                 //範囲外は無視\r
327                 if(xc<0 || xc >=img_x || yc<0 || yc >=img_y){\r
328                     continue;\r
329                 }\r
330 //              ピクセル値の計算\r
331 //              image.getPixel(xc,yc,rgb_buf);\r
332 //                ext_pat2_j_i=ext_pat2_j[i/xdiv];\r
333 //                ext_pat2_j_i[0] += rgb_buf[0];//R\r
334 //                ext_pat2_j_i[1] += rgb_buf[1];//G\r
335 //                ext_pat2_j_i[2] += rgb_buf[2];//B\r
336 \r
337                 x_rgb_index[index_num]=xc;\r
338                 y_rgb_index[index_num]=yc;\r
339                 i_rgb_index[index_num]=i/xdiv;\r
340                 index_num++;\r
341             }\r
342 //          //ステップ2.ピクセル配列を取得\r
343             image.getPixelSet(x_rgb_index,y_rgb_index,index_num,rgb_buf);\r
344 //          //ピクセル値の計算\r
345             for(i=index_num-1;i>=0;i--){\r
346                 extpat_j_i=extpat_j[i_rgb_index[i]];\r
347                 extpat_j_i[0] += rgb_buf[i*3+0];//R\r
348                 extpat_j_i[1] += rgb_buf[i*3+1];//G\r
349                 extpat_j_i[2] += rgb_buf[i*3+2];//B\r
350             }\r
351         }\r
352         /*<Optimize>*/\r
353         int xdiv_x_ydiv=xdiv*ydiv;\r
354         for(j =L_HEIGHT-1; j>=0; j--){\r
355             extpat_j=L_extpat[j];\r
356             for(i = L_WIDTH-1; i>=0; i--){                              // PRL 2006-06-08.\r
357                 extpat_j_i=extpat_j[i];\r
358                 extpat_j_i[0]/=(xdiv_x_ydiv);//ext_pat[j][i][0] = (byte)(ext_pat2[j][i][0] / (xdiv*ydiv));\r
359                 extpat_j_i[1]/=(xdiv_x_ydiv);//ext_pat[j][i][1] = (byte)(ext_pat2[j][i][1] / (xdiv*ydiv));\r
360                 extpat_j_i[2]/=(xdiv_x_ydiv);//ext_pat[j][i][2] = (byte)(ext_pat2[j][i][2] / (xdiv*ydiv));\r
361             }\r
362         }\r
363         return; \r
364     }\r
365 }