OSDN Git Service

Merge branch 'git-svn'
[nyartoolkit-and/nyartoolkit-and.git] / branches / 1.2.0-last / src / jp / nyatla / nyartoolkit / core / NyARParam.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 import java.io.*;\r
36 import java.nio.*;\r
37 \r
38 import jp.nyatla.nyartoolkit.NyARException;\r
39 import jp.nyatla.util.DoubleValue;\r
40 \r
41 /*typedef struct {\r
42     int      xsize, ysize;\r
43     double   mat[3][4];\r
44     double   dist_factor[4];\r
45 } ARParam;*/\r
46 public class NyARParam{\r
47     private static final int SIZE_OF_PARAM_SET=4+4+(3*4*8)+(4*8);\r
48     private static final int PD_LOOP = 3;\r
49     protected int               xsize, ysize;\r
50     private double[]    array34=new double[3*4];//Double2dArray mat=new Double2dArray(3,4);\r
51     private double[]  dist_factor=new double[4];\r
52     public int getX()\r
53     {\r
54         return xsize;\r
55     }\r
56     public int getY()\r
57     {\r
58         return ysize;\r
59     }\r
60     public double[] getDistFactor()\r
61     {\r
62         return dist_factor;\r
63     }\r
64     /**\r
65      * パラメタを格納した[4x3]配列を返します。\r
66      * @return\r
67      */\r
68     public final double[] get34Array()\r
69     {\r
70         return array34;\r
71     }\r
72     /**\r
73      * ARToolKit標準ファイルから1個目の設定をロードする。\r
74      * @param i_filename\r
75      * @throws NyARException\r
76      */\r
77     public void loadFromARFile(String i_filename) throws NyARException\r
78     {\r
79         try {\r
80             loadFromARFile(new FileInputStream(i_filename));\r
81         } catch (Exception e) {\r
82             throw new NyARException(e);\r
83         }\r
84     }\r
85     public void loadFromARFile(InputStream i_stream) throws NyARException\r
86     {\r
87         try {\r
88             NyARParam new_inst[] = arParamLoad(i_stream, 1);\r
89             i_stream.close();\r
90             xsize = new_inst[0].xsize;\r
91             ysize = new_inst[0].ysize;\r
92             array34 = new_inst[0].array34;\r
93             dist_factor = new_inst[0].dist_factor;\r
94         } catch (Exception e) {\r
95             throw new NyARException(e);\r
96         }\r
97     }\r
98     /*static double dot( double a1, double a2, double a3,double b1, double b2, double b3 )*/\r
99     private final static double dot( double a1, double a2, double a3,double b1, double b2, double b3 )\r
100     {\r
101         return( a1 * b1 + a2 * b2 + a3 * b3 );\r
102     }\r
103     /*  static double norm( double a, double b, double c )*/\r
104     private final static double norm( double a, double b, double c )\r
105     {\r
106         return Math.sqrt( a*a + b*b + c*c );\r
107     }\r
108     /**\r
109      * int  arParamDecompMat( double source[3][4], double cpara[3][4], double trans[3][4] );\r
110      * 関数の置き換え\r
111      * Optimize STEP[754->665]\r
112      * @param o_cpara\r
113      * 戻り引数。3x4のマトリクスを指定すること。\r
114      * @param o_trans\r
115      * 戻り引数。3x4のマトリクスを指定すること。\r
116      * @return\r
117      */\r
118     public void decompMat(NyARMat o_cpara, NyARMat o_trans)\r
119     {\r
120         double[] source=array34;\r
121         double[] Cpara=new double[3*4];//double    Cpara[3][4];\r
122         double    rem1, rem2, rem3;\r
123         int i;\r
124         if(source[2*4+3]>= 0 ){//if( source[2][3] >= 0 ) {\r
125             //<Optimize>\r
126             //for(int r = 0; r < 3; r++ ){\r
127             //    for(int c = 0; c < 4; c++ ){\r
128             //        Cpara[r][c]=source[r][c];//Cpara[r][c] = source[r][c];\r
129             //    }\r
130             //}\r
131             for(i=0;i<12;i++){\r
132                 Cpara[i]=source[i];//Cpara[r][c] = source[r][c];\r
133             }\r
134             //</Optimize>\r
135         }else {\r
136             //<Optimize>\r
137             //for(int r = 0; r < 3; r++ ){\r
138             //  for(int c = 0; c < 4; c++ ){\r
139             //        Cpara[r][c]=-source[r][c];//Cpara[r][c] = -(source[r][c]);\r
140             //    }\r
141             //}\r
142             for(i=0;i<12;i++){\r
143                 Cpara[i]=source[i];//Cpara[r][c] = source[r][c];\r
144             }\r
145             //</Optimize>\r
146         }\r
147     \r
148         double[][] cpara=o_cpara.getArray();\r
149         double[][] trans=o_trans.getArray();\r
150         for(int r = 0; r < 3; r++ ){\r
151             for(int c = 0; c < 4; c++ ){\r
152                 cpara[r][c]=0.0;//cpara[r][c] = 0.0;\r
153             }\r
154         }\r
155         cpara[2][2]=norm(Cpara[2*4+0],Cpara[2*4+1], Cpara[2*4+2]);//cpara[2][2] = norm( Cpara[2][0], Cpara[2][1], Cpara[2][2] );\r
156         trans[2][0]=Cpara[2*4+0] / cpara[2][2];//trans[2][0] = Cpara[2][0] / cpara[2][2];\r
157         trans[2][1]=Cpara[2*4+1]/ cpara[2][2];//trans[2][1] = Cpara[2][1] / cpara[2][2];\r
158         trans[2][2]=Cpara[2*4+2]/ cpara[2][2];//trans[2][2] = Cpara[2][2] / cpara[2][2];\r
159         trans[2][3]=Cpara[2*4+3] / cpara[2][2];//trans[2][3] = Cpara[2][3] / cpara[2][2];\r
160         \r
161         cpara[1][2]=dot(trans[2][0], trans[2][1], trans[2][2],Cpara[1*4+0], Cpara[1*4+1], Cpara[1*4+2]);//cpara[1][2] = dot( trans[2][0], trans[2][1], trans[2][2],Cpara[1][0], Cpara[1][1], Cpara[1][2] );\r
162         rem1=Cpara[1*4+0]- cpara[1][2] * trans[2][0];//rem1 = Cpara[1][0] - cpara[1][2] * trans[2][0];\r
163         rem2=Cpara[1*4+1] - cpara[1][2] * trans[2][1];//rem2 = Cpara[1][1] - cpara[1][2] * trans[2][1];\r
164         rem3=Cpara[1*4+2] - cpara[1][2] * trans[2][2];//rem3 = Cpara[1][2] - cpara[1][2] * trans[2][2];\r
165         cpara[1][1]=norm(rem1, rem2, rem3 );//cpara[1][1] = norm( rem1, rem2, rem3 );\r
166         trans[1][0]= rem1/cpara[1][1];//trans[1][0] = rem1 / cpara[1][1];\r
167         trans[1][1]=rem2/cpara[1][1];//trans[1][1] = rem2 / cpara[1][1];\r
168         trans[1][2]=rem3 / cpara[1][1];//trans[1][2] = rem3 / cpara[1][1];\r
169     \r
170         cpara[0][2]=dot(trans[2][0],trans[2][1], trans[2][2],Cpara[0*4+0], Cpara[0*4+1], Cpara[0*4+2] );//cpara[0][2] = dot( trans[2][0], trans[2][1], trans[2][2],Cpara[0][0], Cpara[0][1], Cpara[0][2] );\r
171         cpara[0][1]=dot(trans[1][0],trans[1][1], trans[1][2],Cpara[0*4+0], Cpara[0*4+1], Cpara[0*4+2]);//cpara[0][1] = dot( trans[1][0], trans[1][1], trans[1][2],Cpara[0][0], Cpara[0][1], Cpara[0][2] );\r
172         rem1=Cpara[0*4+0]- cpara[0][1]*trans[1][0] - cpara[0][2]*trans[2][0];//rem1 = Cpara[0][0] - cpara[0][1]*trans[1][0] - cpara[0][2]*trans[2][0];\r
173         rem2 = Cpara[0*4+1] - cpara[0][1]*trans[1][1] - cpara[0][2]*trans[2][1];//rem2 = Cpara[0][1] - cpara[0][1]*trans[1][1] - cpara[0][2]*trans[2][1];\r
174         rem3 = Cpara[0*4+2] - cpara[0][1]*trans[1][2] - cpara[0][2]*trans[2][2];//rem3 = Cpara[0][2] - cpara[0][1]*trans[1][2] - cpara[0][2]*trans[2][2];\r
175         cpara[0][0]=norm(rem1, rem2, rem3);//cpara[0][0] = norm( rem1, rem2, rem3 );\r
176         trans[0][0]=rem1 / cpara[0][0];//trans[0][0] = rem1 / cpara[0][0];\r
177         trans[0][1]= rem2 / cpara[0][0];//trans[0][1] = rem2 / cpara[0][0];\r
178         trans[0][2]= rem3 / cpara[0][0];//trans[0][2] = rem3 / cpara[0][0];\r
179     \r
180         trans[1][3]=(Cpara[1*4+3] - cpara[1][2]*trans[2][3]) / cpara[1][1];//trans[1][3] = (Cpara[1][3] - cpara[1][2]*trans[2][3]) / cpara[1][1];\r
181         trans[0][3]=(Cpara[0*4+3] - cpara[0][1]*trans[1][3]- cpara[0][2]*trans[2][3]) / cpara[0][0];//trans[0][3] = (Cpara[0][3] - cpara[0][1]*trans[1][3]- cpara[0][2]*trans[2][3]) / cpara[0][0];\r
182     \r
183         for(int  r = 0; r < 3; r++ ){\r
184             for(int c = 0; c < 3; c++ ){\r
185                 cpara[r][c]/=cpara[2][2];//cpara[r][c] /= cpara[2][2];\r
186             }\r
187         }\r
188     }\r
189 \r
190 \r
191     /*int    arParamDisp( ARParam *param );*/\r
192     public int paramDisp()\r
193     {\r
194         System.out.println("--------------------------------------");//printf("--------------------------------------\n");\r
195         System.out.print("SIZE = "+xsize+", "+ysize);//printf("SIZE = %d, %d\n", param->xsize, param->ysize);\r
196         System.out.println("Distortion factor = "+dist_factor[0]+" "+dist_factor[1]+" "+dist_factor[2]+" "+dist_factor[3]);//printf("Distortion factor = %f %f %f %f\n", param->dist_factor[0],param->dist_factor[1], param->dist_factor[2], param->dist_factor[3] );\r
197         for(int j = 0; j < 3; j++ ) {//for(j = 0; j < 3; j++ ) {\r
198             for(int i = 0; i < 4; i++ ){\r
199                 System.out.print(array34[j*4+i]+" ");//printf("%7.5f ", param->mat[j][i]);\r
200             }\r
201             System.out.println();//    printf("\n");\r
202         }//}\r
203         System.out.println("--------------------------------------");//printf("--------------------------------------\n");\r
204         return 0;\r
205     }\r
206 //    /*int  arParamDecomp( ARParam *source, ARParam *icpara, double trans[3][4] );*/\r
207 //    private static int arParamDecomp( NyARParam source, NyARParam icpara, double[][] trans)\r
208 //    {\r
209 //        icpara.xsize          = source.xsize;//icpara->xsize          = source->xsize;\r
210 //        icpara.ysize          = source.ysize;//icpara->ysize          = source->ysize;\r
211 //        icpara.dist_factor[0] = source.dist_factor[0];//icpara->dist_factor[0] = source->dist_factor[0];\r
212 //        icpara.dist_factor[1] = source.dist_factor[1];// icpara->dist_factor[1] = source->dist_factor[1];\r
213 //        icpara.dist_factor[2] = source.dist_factor[2];//icpara->dist_factor[2] = source->dist_factor[2];\r
214 //        icpara.dist_factor[3] = source.dist_factor[3];//icpara->dist_factor[3] = source->dist_factor[3];\r
215 //        return arParamDecompMat(source.mat, icpara.mat, trans );\r
216 //    }\r
217     /**\r
218      * int arParamChangeSize( ARParam *source, int xsize, int ysize, ARParam *newparam );\r
219      * 関数の代替関数\r
220      * サイズプロパティをi_xsize,i_ysizeに変更します。\r
221      * @param xsize\r
222      * @param ysize\r
223      * @param newparam\r
224      * @return\r
225      * \r
226      */\r
227     public void changeSize(int i_xsize, int i_ysize)\r
228     {\r
229         double  scale;    \r
230         scale = (double)i_xsize / (double)(xsize);//scale = (double)xsize / (double)(source->xsize);\r
231     \r
232         for(int i = 0; i < 4; i++ ) {\r
233             array34[0*4+i]=array34[0*4+i]*scale;//newparam->mat[0][i] = source->mat[0][i] * scale;\r
234             array34[1*4+i]=array34[1*4+i]*scale;//newparam->mat[1][i] = source->mat[1][i] * scale;\r
235             array34[2*4+i]=array34[2*4+i];//newparam->mat[2][i] = source->mat[2][i];\r
236         }\r
237     \r
238         dist_factor[0] = dist_factor[0] * scale;//newparam->dist_factor[0] = source->dist_factor[0] * scale;\r
239         dist_factor[1] = dist_factor[1] * scale;//newparam->dist_factor[1] = source->dist_factor[1] * scale;\r
240         dist_factor[2] = dist_factor[2] / (scale*scale);//newparam->dist_factor[2] = source->dist_factor[2] / (scale*scale);\r
241         dist_factor[3] = dist_factor[3];//newparam->dist_factor[3] = source->dist_factor[3];\r
242     \r
243         xsize = i_xsize;//newparam->xsize = xsize;\r
244         ysize = i_ysize;//newparam->ysize = ysize;\r
245     }\r
246     /**\r
247      * int arParamIdeal2Observ( const double dist_factor[4], const double ix, const double iy,double *ox, double *oy )\r
248      * 関数の代替関数\r
249      * @param ix\r
250      * @param iy\r
251      * @param ox\r
252      * @param oy\r
253      */\r
254     public void ideal2Observ(double ix,double iy,DoubleValue ox, DoubleValue oy)\r
255     {\r
256 \r
257         double    x, y, d;\r
258         final double d0,d1,d3;\r
259         final double df[]=this.dist_factor;\r
260         d0=df[0];\r
261         d1=df[1];\r
262         d3=df[3];\r
263         x = (ix - d0) * d3;\r
264         y = (iy - d1) * d3;\r
265         if( x == 0.0 && y == 0.0 ) {\r
266             ox.value=d0;\r
267             oy.value=d1;\r
268         }else{\r
269             d = 1.0 - df[2]/100000000.0 * (x*x+y*y);\r
270             ox.value=x * d + d0;\r
271             oy.value=y * d + d1;\r
272         }\r
273     }\r
274     /**\r
275      * ideal2Observをまとめて実行します。\r
276      * @param i_in\r
277      * double[][2]\r
278      * @param o_out\r
279      * double[][2]\r
280      */\r
281     public void ideal2ObservBatch(double[][] i_in,double[][] o_out,int i_size)\r
282     {\r
283 \r
284         double    x, y, d;\r
285         final double d0,d1,d3,d2_w;\r
286         final double df[]=this.dist_factor;\r
287         d0=df[0];\r
288         d1=df[1];\r
289         d3=df[3];\r
290         d2_w=df[2]/100000000.0;\r
291         for(int i=0;i<i_size;i++){\r
292             x = (i_in[i][0] - d0) * d3;\r
293             y = (i_in[i][1] - d1) * d3;\r
294             if( x == 0.0 && y == 0.0 ) {\r
295                 o_out[i][0]=d0;\r
296                 o_out[i][1]=d1;\r
297             }else{\r
298                 d = 1.0 - d2_w * (x*x+y*y);\r
299                 o_out[i][0]=x * d + d0;\r
300                 o_out[i][1]=y * d + d1;\r
301             }\r
302         }\r
303         return;\r
304     }    \r
305     \r
306     \r
307     \r
308     \r
309     /**\r
310      * int arParamObserv2Ideal( const double dist_factor[4], const double ox, const double oy,double *ix, double *iy );\r
311      * \r
312      * @param ox\r
313      * @param oy\r
314      * @param ix\r
315      * @param iy\r
316      * @return\r
317      */\r
318     public int observ2Ideal(double ox,double oy,DoubleValue ix,DoubleValue iy)\r
319     {\r
320         double  z02, z0, p, q, z, px, py,opttmp_1;\r
321         final double d0,d1,d3;\r
322         final double df[]=this.dist_factor;\r
323         d0=df[0];\r
324         d1=df[1];\r
325         \r
326         px = ox - d0;\r
327         py = oy - d1;\r
328         p = df[2]/100000000.0;\r
329         z02 = px*px+py*py;\r
330         q = z0 = Math.sqrt(z02);//Optimize//q = z0 = Math.sqrt(px*px+ py*py);\r
331         \r
332         for(int i = 1; ; i++ ) {\r
333             if( z0 != 0.0 ) {\r
334                 //Optimize opttmp_1\r
335                 opttmp_1=p*z02;\r
336                 z = z0 - ((1.0 - opttmp_1)*z0 - q) / (1.0 - 3.0*opttmp_1);\r
337                 px = px*z/z0;\r
338                 py = py*z/z0;\r
339             }else {\r
340                 px = 0.0;\r
341                 py = 0.0;\r
342                 break;\r
343             }\r
344             if( i == PD_LOOP ){\r
345                 break;\r
346             }\r
347             z02 = px*px+ py*py;\r
348             z0 = Math.sqrt(z02);//Optimize//z0 = Math.sqrt(px*px+ py*py);\r
349         }\r
350         d3=df[3];\r
351         ix.value=px / d3 + d0;\r
352         iy.value=py / d3 + d1;\r
353         return 0;\r
354     }\r
355     /**\r
356      * 指定範囲のobserv2Idealをまとめて実行して、結果をo_idealに格納します。\r
357      * @param i_x_coord\r
358      * @param i_y_coord\r
359      * @param i_start\r
360      * coord開始点\r
361      * @param i_num\r
362      * 計算数\r
363      * @param o_ideal\r
364      * 出力バッファ[i_num][2]であること。\r
365      */\r
366     public void observ2IdealBatch(int[] i_x_coord,int[] i_y_coord,int i_start,int i_num,double[][] o_ideal)\r
367     {\r
368         double  z02, z0,q, z, px, py,opttmp_1;\r
369         final double df[]=this.dist_factor;\r
370         final double d0=df[0];\r
371         final double d1=df[1];\r
372         final double d3=df[3];\r
373         final double p = df[2]/100000000.0;\r
374         for(int j = 0; j < i_num; j++ ){\r
375 \r
376             px = i_x_coord[i_start+j] - d0;\r
377             py = i_y_coord[i_start+j] - d1;\r
378 \r
379             z02 = px*px+py*py;\r
380             q = z0 = Math.sqrt(z02);//Optimize//q = z0 = Math.sqrt(px*px+ py*py);\r
381 \r
382             for(int i = 1; ; i++ ) {\r
383                 if( z0 != 0.0 ) {\r
384                     //Optimize opttmp_1\r
385                     opttmp_1=p*z02;\r
386                     z = z0 - ((1.0 - opttmp_1)*z0 - q) / (1.0 - 3.0*opttmp_1);\r
387                     px = px*z/z0;\r
388                     py = py*z/z0;\r
389                 }else {\r
390                     px = 0.0;\r
391                     py = 0.0;\r
392                     break;\r
393                 }\r
394                 if( i == PD_LOOP ){\r
395                     break;\r
396                 }\r
397                 z02 = px*px+ py*py;\r
398                 z0 = Math.sqrt(z02);//Optimize//z0 = Math.sqrt(px*px+ py*py);\r
399             }\r
400             o_ideal[j][0]=px / d3 + d0;\r
401             o_ideal[j][1]=py / d3 + d1;\r
402         }       \r
403     }    \r
404     \r
405     \r
406     \r
407     \r
408     /**\r
409      * int    arParamLoad( const char *filename, int num, ARParam *param, ...);\r
410      * i_streamの入力ストリームからi_num個の設定を読み込み、パラメタを配列にして返します。\r
411      * @param filename\r
412      * @param num\r
413      * @param param\r
414      * @return\r
415      *  設定を格納した配列を返します。\r
416      * @throws Exception\r
417      * i_num個の設定が読み出せない場合、JartkExceptionを発生します。\r
418      */\r
419     private static NyARParam[] arParamLoad(InputStream i_stream, int i_num) throws NyARException\r
420     {\r
421         try{\r
422             int read_size=SIZE_OF_PARAM_SET*i_num;\r
423             byte[] buf=new byte[read_size];\r
424             i_stream.read(buf);\r
425             //返却配列を確保\r
426             NyARParam[] result=new NyARParam[i_num];\r
427             \r
428             //バッファを加工\r
429             ByteBuffer bb = ByteBuffer.wrap(buf);\r
430             bb.order(ByteOrder.BIG_ENDIAN);\r
431     \r
432             //固定回数パースして配列に格納\r
433             for(int i=0;i<i_num;i++){\r
434                 NyARParam new_param=new NyARParam();;\r
435                 new_param.xsize=bb.getInt();\r
436                 new_param.ysize=bb.getInt();\r
437                 for(int i2=0;i2<3;i2++){\r
438                     for(int i3=0;i3<4;i3++){\r
439                         new_param.array34[i2*4+i3]=bb.getDouble();\r
440                     }\r
441                 }\r
442                 for(int i2=0;i2<4;i2++){\r
443                     new_param.dist_factor[i2]=bb.getDouble();\r
444                 }\r
445                 result[i]=new_param;\r
446             }\r
447             return result;\r
448         }catch(Exception e){\r
449             throw new NyARException(e);\r
450         }\r
451     }\r
452     public static int arParamSave(String filename,int num, NyARParam param[]) throws Exception\r
453     {\r
454         NyARException.trap("未チェックの関数");\r
455         byte buf[]=new byte[SIZE_OF_PARAM_SET*param.length];\r
456         //バッファをラップ\r
457         ByteBuffer bb = ByteBuffer.wrap(buf);\r
458         bb.order(ByteOrder.BIG_ENDIAN);\r
459 \r
460         //書き込み\r
461         for(int i=0;i<param.length;i++){\r
462             bb.putInt(param[i].xsize);\r
463             bb.putInt(param[i].ysize);\r
464             for(int i2=0;i2<3;i2++){\r
465                 for(int i3=0;i3<4;i3++){\r
466                     bb.putDouble(param[i].array34[i2*4+i3]);\r
467                 }\r
468             }\r
469                 for(int i2=0;i2<4;i2++){\r
470                     bb.putDouble(param[i].dist_factor[i2]);\r
471                 }\r
472             }\r
473         //ファイルに保存\r
474         FileOutputStream fs=new FileOutputStream(filename);\r
475         fs.write(buf);\r
476         fs.close();\r
477 \r
478         return 0;\r
479     }\r
480 }\r