Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
204 chris 1
#include <math.h>
2
#include <stdio.h>
3
#include <AR/ar.h>
4
#include <AR/param.h>
5
#include <AR/matrix.h>
6
#include "calib_camera.h"
7
 
8
static int calc_inp2( CALIB_PATT_T *patt, CALIB_COORD_T *screen, double *pos2d, double *pos3d,
9
                      double dist_factor[4], double x0, double y0, double f[2], double *err );
10
static void get_cpara( CALIB_COORD_T *world, CALIB_COORD_T *screen, int num, double para[3][3] );
11
static int  get_fl( double *p , double *q, int num, double f[2] );
12
static int  check_rotation( double rot[2][3] );
13
 
14
int calc_inp( CALIB_PATT_T *patt, double dist_factor[4], int xsize, int ysize, double mat[3][4] )
15
{
16
    CALIB_COORD_T  *screen, *sp;
17
    double         *pos2d, *pos3d, *pp;
18
    double         f[2];
19
    double         x0, y0;
20
    double         err, minerr;
21
    int            res;
22
    int            i, j, k;
23
 
24
    sp = screen = (CALIB_COORD_T *)malloc(sizeof(CALIB_COORD_T) * patt->h_num * patt->v_num * patt->loop_num);
25
    pp = pos2d = (double *)malloc(sizeof(double) * patt->h_num * patt->v_num * patt->loop_num * 2);
26
    pos3d = (double *)malloc(sizeof(double) * patt->h_num * patt->v_num * 2);
27
    for( k = 0; k < patt->loop_num; k++ ) {
28
        for( j = 0; j < patt->v_num; j++ ) {
29
            for( i = 0; i < patt->h_num; i++ ) {
30
                arParamObserv2Ideal( dist_factor,
31
                                     patt->point[k][j*patt->h_num+i].x_coord,
32
                                     patt->point[k][j*patt->h_num+i].y_coord,
33
                                     &(sp->x_coord), &(sp->y_coord) );
34
                *(pp++) = sp->x_coord;
35
                *(pp++) = sp->y_coord;
36
                sp++;
37
            }
38
        }
39
    }
40
    pp = pos3d;
41
    for( j = 0; j < patt->v_num; j++ ) {
42
        for( i = 0; i < patt->h_num; i++ ) {
43
            *(pp++) = patt->world_coord[j*patt->h_num+i].x_coord;
44
            *(pp++) = patt->world_coord[j*patt->h_num+i].y_coord;
45
        }
46
    }
47
 
48
    minerr = 100000000000000000000000.0;
49
    for( j = -50; j <= 50; j++ ) {
50
        printf("-- loop:%d --\n", j);
51
        y0 = dist_factor[1] + j;
52
/*      y0 = ysize/2 + j;   */
53
        if( y0 < 0 || y0 >= ysize ) continue;
54
 
55
        for( i = -50; i <= 50; i++ ) {
56
            x0 = dist_factor[0] + i;
57
/*          x0 = xsize/2 + i;  */
58
            if( x0 < 0 || x0 >= xsize ) continue;
59
 
60
            res = calc_inp2( patt, screen, pos2d, pos3d, dist_factor, x0, y0, f, &err );
61
            if( res < 0 ) continue;
62
            if( err < minerr ) {
63
                printf("F = (%f,%f), Center = (%f,%f): err = %f\n", f[0], f[1], x0, y0, err);
64
                minerr = err;
65
 
66
                mat[0][0] = f[0];
67
                mat[0][1] = 0.0;
68
                mat[0][2] = x0;
69
                mat[0][3] = 0.0;
70
                mat[1][0] = 0.0;
71
                mat[1][1] = f[1];
72
                mat[1][2] = y0;
73
                mat[1][3] = 0.0;
74
                mat[2][0] = 0.0;
75
                mat[2][1] = 0.0;
76
                mat[2][2] = 1.0;
77
                mat[2][3] = 0.0;
78
            }
79
        }
80
    }
81
 
82
    free( screen );
83
    free( pos2d );
84
    free( pos3d );
85
 
86
    if( minerr >= 100.0 ) return -1;
87
    return 0;
88
}
89
 
90
 
91
static int calc_inp2 ( CALIB_PATT_T *patt, CALIB_COORD_T *screen, double *pos2d, double *pos3d,
92
                      double dist_factor[4], double x0, double y0, double f[2], double *err )
93
{
94
    double  x1, y1, x2, y2;
95
    double  p[LOOP_MAX], q[LOOP_MAX];
96
    double  para[3][3];
97
    double  rot[3][3], rot2[3][3];
98
    double  cpara[3][4], conv[3][4];
99
    double  ppos2d[4][2], ppos3d[4][2];
100
    double  d, werr, werr2;
101
    int     i, j, k, l;
102
 
103
    for( i =  0; i < patt->loop_num; i++ ) {
104
        get_cpara( patt->world_coord, &(screen[i*patt->h_num*patt->v_num]),
105
                   patt->h_num*patt->v_num, para );
106
        x1 = para[0][0] / para[2][0];
107
        y1 = para[1][0] / para[2][0];
108
        x2 = para[0][1] / para[2][1];
109
        y2 = para[1][1] / para[2][1];
110
 
111
        p[i] = (x1 - x0)*(x2 - x0);
112
        q[i] = (y1 - y0)*(y2 - y0);
113
    }
114
    if( get_fl(p, q, patt->loop_num, f) < 0 ) return -1;
115
 
116
    cpara[0][0] = f[0];
117
    cpara[0][1] = 0.0;
118
    cpara[0][2] = x0;
119
    cpara[0][3] = 0.0;
120
    cpara[1][0] = 0.0;
121
    cpara[1][1] = f[1];
122
    cpara[1][2] = y0;
123
    cpara[1][3] = 0.0;
124
    cpara[2][0] = 0.0;
125
    cpara[2][1] = 0.0;
126
    cpara[2][2] = 1.0;
127
    cpara[2][3] = 0.0;
128
 
129
    werr = 0.0;
130
    for( i =  0; i < patt->loop_num; i++ ) {
131
        get_cpara( patt->world_coord, &(screen[i*patt->h_num*patt->v_num]),
132
                   patt->h_num*patt->v_num, para );
133
        rot[0][0] = (para[0][0] - x0*para[2][0]) / f[0];
134
        rot[0][1] = (para[1][0] - y0*para[2][0]) / f[1];
135
        rot[0][2] = para[2][0];
136
        d = sqrt( rot[0][0]*rot[0][0] + rot[0][1]*rot[0][1] + rot[0][2]*rot[0][2] );
137
        rot[0][0] /= d;
138
        rot[0][1] /= d;
139
        rot[0][2] /= d;
140
        rot[1][0] = (para[0][1] - x0*para[2][1]) / f[0];
141
        rot[1][1] = (para[1][1] - y0*para[2][1]) / f[1];
142
        rot[1][2] = para[2][1];
143
        d = sqrt( rot[1][0]*rot[1][0] + rot[1][1]*rot[1][1] + rot[1][2]*rot[1][2] );
144
        rot[1][0] /= d;
145
        rot[1][1] /= d;
146
        rot[1][2] /= d;
147
        check_rotation( rot );
148
        rot[2][0] = rot[0][1]*rot[1][2] - rot[0][2]*rot[1][1];
149
        rot[2][1] = rot[0][2]*rot[1][0] - rot[0][0]*rot[1][2];
150
        rot[2][2] = rot[0][0]*rot[1][1] - rot[0][1]*rot[1][0];
151
        d = sqrt( rot[2][0]*rot[2][0] + rot[2][1]*rot[2][1] + rot[2][2]*rot[2][2] );
152
        rot[2][0] /= d;
153
        rot[2][1] /= d;
154
        rot[2][2] /= d;
155
        rot2[0][0] = rot[0][0];
156
        rot2[1][0] = rot[0][1];
157
        rot2[2][0] = rot[0][2];
158
        rot2[0][1] = rot[1][0];
159
        rot2[1][1] = rot[1][1];
160
        rot2[2][1] = rot[1][2];
161
        rot2[0][2] = rot[2][0];
162
        rot2[1][2] = rot[2][1];
163
        rot2[2][2] = rot[2][2];
164
 
165
        ppos2d[0][0] = pos2d[i*patt->h_num*patt->v_num*2 + 0];
166
        ppos2d[0][1] = pos2d[i*patt->h_num*patt->v_num*2 + 1];
167
        ppos2d[1][0] = pos2d[i*patt->h_num*patt->v_num*2 + (patt->h_num-1)*2 + 0];
168
        ppos2d[1][1] = pos2d[i*patt->h_num*patt->v_num*2 + (patt->h_num-1)*2 + 1];
169
        ppos2d[2][0] = pos2d[i*patt->h_num*patt->v_num*2 + (patt->h_num*(patt->v_num-1))*2 + 0];
170
        ppos2d[2][1] = pos2d[i*patt->h_num*patt->v_num*2 + (patt->h_num*(patt->v_num-1))*2 + 1];
171
        ppos2d[3][0] = pos2d[i*patt->h_num*patt->v_num*2 + (patt->h_num*patt->v_num-1)*2 + 0];
172
        ppos2d[3][1] = pos2d[i*patt->h_num*patt->v_num*2 + (patt->h_num*patt->v_num-1)*2 + 1];
173
        ppos3d[0][0] = pos3d[0];
174
        ppos3d[0][1] = pos3d[1];
175
        ppos3d[1][0] = pos3d[(patt->h_num-1)*2 + 0];
176
        ppos3d[1][1] = pos3d[(patt->h_num-1)*2 + 1];
177
        ppos3d[2][0] = pos3d[(patt->h_num*(patt->v_num-1))*2 + 0];
178
        ppos3d[2][1] = pos3d[(patt->h_num*(patt->v_num-1))*2 + 1];
179
        ppos3d[3][0] = pos3d[(patt->h_num*patt->v_num-1)*2 + 0];
180
        ppos3d[3][1] = pos3d[(patt->h_num*patt->v_num-1)*2 + 1];
181
 
182
        for( j = 0; j < 5; j++ ) {
183
            arFittingMode = AR_FITTING_TO_IDEAL;
184
            werr2 = arGetTransMat3( rot2, ppos2d, ppos3d, 4, conv, dist_factor, cpara );
185
            for( k = 0; k < 3; k++ ) {
186
            for( l = 0; l < 3; l++ ) {
187
                rot2[k][l] = conv[k][l];
188
            }}
189
        }
190
        werr += werr2;
191
 
192
    }
193
    *err = sqrt( werr / patt->loop_num );
194
 
195
    return 0;
196
}
197
 
198
static void get_cpara( CALIB_COORD_T *world, CALIB_COORD_T *screen, int num, double para[3][3] )
199
{
200
    ARMat   *a, *b, *c;
201
    ARMat   *at, *aa, res;
202
    int     i;
203
 
204
    a = arMatrixAlloc( num*2, 8 );
205
    b = arMatrixAlloc( num*2, 1 );
206
    c = arMatrixAlloc( 8, num*2 );
207
    at = arMatrixAlloc( 8, num*2 );
208
    aa = arMatrixAlloc( 8, 8 );
209
    for( i = 0; i < num; i++ ) {
210
        a->m[i*16+0]  = world[i].x_coord;
211
        a->m[i*16+1]  = world[i].y_coord;
212
        a->m[i*16+2]  = 1.0;
213
        a->m[i*16+3]  = 0.0;
214
        a->m[i*16+4]  = 0.0;
215
        a->m[i*16+5]  = 0.0;
216
        a->m[i*16+6]  = -world[i].x_coord * screen[i].x_coord;
217
        a->m[i*16+7]  = -world[i].y_coord * screen[i].x_coord;
218
        a->m[i*16+8]  = 0.0;
219
        a->m[i*16+9]  = 0.0;
220
        a->m[i*16+10] = 0.0;
221
        a->m[i*16+11] = world[i].x_coord;
222
        a->m[i*16+12] = world[i].y_coord;
223
        a->m[i*16+13] = 1.0;
224
        a->m[i*16+14] = -world[i].x_coord * screen[i].y_coord;
225
        a->m[i*16+15] = -world[i].y_coord * screen[i].y_coord;
226
        b->m[i*2+0] = screen[i].x_coord;
227
        b->m[i*2+1] = screen[i].y_coord;
228
    }
229
    arMatrixTrans( at, a );
230
    arMatrixMul( aa, at, a );
231
    arMatrixSelfInv( aa );
232
    arMatrixMul( c, aa, at );
233
    res.row = 8;
234
    res.clm = 1;
235
    res.m = &(para[0][0]);
236
    arMatrixMul( &res, c, b );
237
    para[2][2] = 1.0;
238
 
239
    arMatrixFree( a );
240
    arMatrixFree( b );
241
    arMatrixFree( c );
242
    arMatrixFree( at );
243
    arMatrixFree( aa );
244
}
245
 
246
static int get_fl( double *p , double *q, int num, double f[2] )
247
{
248
    ARMat   *a, *b, *c;
249
    ARMat   *at, *aa, *res;
250
    int     i;
251
 
252
#if 1
253
    a = arMatrixAlloc( num, 2 );
254
    b = arMatrixAlloc( num, 1 );
255
    c = arMatrixAlloc( 2, num );
256
    at = arMatrixAlloc( 2, num );
257
    aa = arMatrixAlloc( 2, 2 );
258
    res = arMatrixAlloc( 2, 1 );
259
    for( i = 0; i < num; i++ ) {
260
        a->m[i*2+0] = *(p++);
261
        a->m[i*2+1] = *(q++);
262
        b->m[i]     = -1.0;
263
    }
264
#else
265
    a = arMatrixAlloc( num-1, 2 );
266
    b = arMatrixAlloc( num-1, 1 );
267
    c = arMatrixAlloc( 2, num-1 );
268
    at = arMatrixAlloc( 2, num-1 );
269
    aa = arMatrixAlloc( 2, 2 );
270
    res = arMatrixAlloc( 2, 1 );
271
    p++; q++;
272
    for( i = 0; i < num-1; i++ ) {
273
        a->m[i*2+0] = *(p++);
274
        a->m[i*2+1] = *(q++);
275
        b->m[i]     = -1.0;
276
    }
277
#endif
278
    arMatrixTrans( at, a );
279
    arMatrixMul( aa, at, a );
280
    arMatrixSelfInv( aa );
281
    arMatrixMul( c, aa, at );
282
    arMatrixMul( res, c, b );
283
 
284
    if( res->m[0] < 0 || res->m[1] < 0 ) return -1;
285
 
286
    f[0] = sqrt( 1.0 / res->m[0] );
287
    f[1] = sqrt( 1.0 / res->m[1] );
288
 
289
    arMatrixFree( a );
290
    arMatrixFree( b );
291
    arMatrixFree( c );
292
    arMatrixFree( at );
293
    arMatrixFree( aa );
294
    arMatrixFree( res );
295
 
296
    return 0;
297
}
298
 
299
static int check_rotation( double rot[2][3] )
300
{
301
    double  v1[3], v2[3], v3[3];
302
    double  ca, cb, k1, k2, k3, k4;
303
    double  a, b, c, d;
304
    double  p1, q1, r1;
305
    double  p2, q2, r2;
306
    double  p3, q3, r3;
307
    double  p4, q4, r4;
308
    double  w;
309
    double  e1, e2, e3, e4;
310
    int     f;
311
 
312
    v1[0] = rot[0][0];
313
    v1[1] = rot[0][1];
314
    v1[2] = rot[0][2];
315
    v2[0] = rot[1][0];
316
    v2[1] = rot[1][1];
317
    v2[2] = rot[1][2];
318
    v3[0] = v1[1]*v2[2] - v1[2]*v2[1];
319
    v3[1] = v1[2]*v2[0] - v1[0]*v2[2];
320
    v3[2] = v1[0]*v2[1] - v1[1]*v2[0];
321
    w = sqrt( v3[0]*v3[0]+v3[1]*v3[1]+v3[2]*v3[2] );
322
    if( w == 0.0 ) return -1;
323
    v3[0] /= w;
324
    v3[1] /= w;
325
    v3[2] /= w;
326
 
327
    cb = v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
328
    if( cb < 0 ) cb *= -1.0;
329
    ca = (sqrt(cb+1.0) + sqrt(1.0-cb)) * 0.5;
330
 
331
    if( v3[1]*v1[0] - v1[1]*v3[0] != 0.0 ) {
332
        f = 0;
333
    }
334
    else {
335
        if( v3[2]*v1[0] - v1[2]*v3[0] != 0.0 ) {
336
            w = v1[1]; v1[1] = v1[2]; v1[2] = w;
337
            w = v3[1]; v3[1] = v3[2]; v3[2] = w;
338
            f = 1;
339
        }
340
        else {
341
            w = v1[0]; v1[0] = v1[2]; v1[2] = w;
342
            w = v3[0]; v3[0] = v3[2]; v3[2] = w;
343
            f = 2;
344
        }
345
    }
346
    if( v3[1]*v1[0] - v1[1]*v3[0] == 0.0 ) return -1;
347
    k1 = (v1[1]*v3[2] - v3[1]*v1[2]) / (v3[1]*v1[0] - v1[1]*v3[0]);
348
    k2 = (v3[1] * ca) / (v3[1]*v1[0] - v1[1]*v3[0]);
349
    k3 = (v1[0]*v3[2] - v3[0]*v1[2]) / (v3[0]*v1[1] - v1[0]*v3[1]);
350
    k4 = (v3[0] * ca) / (v3[0]*v1[1] - v1[0]*v3[1]);
351
 
352
    a = k1*k1 + k3*k3 + 1;
353
    b = k1*k2 + k3*k4;
354
    c = k2*k2 + k4*k4 - 1;
355
 
356
    d = b*b - a*c;
357
    if( d < 0 ) return -1;
358
    r1 = (-b + sqrt(d))/a;
359
    p1 = k1*r1 + k2;
360
    q1 = k3*r1 + k4;
361
    r2 = (-b - sqrt(d))/a;
362
    p2 = k1*r2 + k2;
363
    q2 = k3*r2 + k4;
364
    if( f == 1 ) {
365
        w = q1; q1 = r1; r1 = w;
366
        w = q2; q2 = r2; r2 = w;
367
        w = v1[1]; v1[1] = v1[2]; v1[2] = w;
368
        w = v3[1]; v3[1] = v3[2]; v3[2] = w;
369
        f = 0;
370
    }
371
    if( f == 2 ) {
372
        w = p1; p1 = r1; r1 = w;
373
        w = p2; p2 = r2; r2 = w;
374
        w = v1[0]; v1[0] = v1[2]; v1[2] = w;
375
        w = v3[0]; v3[0] = v3[2]; v3[2] = w;
376
        f = 0;
377
    }
378
 
379
    if( v3[1]*v2[0] - v2[1]*v3[0] != 0.0 ) {
380
        f = 0;
381
    }
382
    else {
383
        if( v3[2]*v2[0] - v2[2]*v3[0] != 0.0 ) {
384
            w = v2[1]; v2[1] = v2[2]; v2[2] = w;
385
            w = v3[1]; v3[1] = v3[2]; v3[2] = w;
386
            f = 1;
387
        }
388
        else {
389
            w = v2[0]; v2[0] = v2[2]; v2[2] = w;
390
            w = v3[0]; v3[0] = v3[2]; v3[2] = w;
391
            f = 2;
392
        }
393
    }
394
    if( v3[1]*v2[0] - v2[1]*v3[0] == 0.0 ) return -1;
395
    k1 = (v2[1]*v3[2] - v3[1]*v2[2]) / (v3[1]*v2[0] - v2[1]*v3[0]);
396
    k2 = (v3[1] * ca) / (v3[1]*v2[0] - v2[1]*v3[0]);
397
    k3 = (v2[0]*v3[2] - v3[0]*v2[2]) / (v3[0]*v2[1] - v2[0]*v3[1]);
398
    k4 = (v3[0] * ca) / (v3[0]*v2[1] - v2[0]*v3[1]);
399
 
400
    a = k1*k1 + k3*k3 + 1;
401
    b = k1*k2 + k3*k4;
402
    c = k2*k2 + k4*k4 - 1;
403
 
404
    d = b*b - a*c;
405
    if( d < 0 ) return -1;
406
    r3 = (-b + sqrt(d))/a;
407
    p3 = k1*r3 + k2;
408
    q3 = k3*r3 + k4;
409
    r4 = (-b - sqrt(d))/a;
410
    p4 = k1*r4 + k2;
411
    q4 = k3*r4 + k4;
412
    if( f == 1 ) {
413
        w = q3; q3 = r3; r3 = w;
414
        w = q4; q4 = r4; r4 = w;
415
        w = v2[1]; v2[1] = v2[2]; v2[2] = w;
416
        w = v3[1]; v3[1] = v3[2]; v3[2] = w;
417
        f = 0;
418
    }
419
    if( f == 2 ) {
420
        w = p3; p3 = r3; r3 = w;
421
        w = p4; p4 = r4; r4 = w;
422
        w = v2[0]; v2[0] = v2[2]; v2[2] = w;
423
        w = v3[0]; v3[0] = v3[2]; v3[2] = w;
424
        f = 0;
425
    }
426
 
427
    e1 = p1*p3+q1*q3+r1*r3; if( e1 < 0 ) e1 = -e1;
428
    e2 = p1*p4+q1*q4+r1*r4; if( e2 < 0 ) e2 = -e2;
429
    e3 = p2*p3+q2*q3+r2*r3; if( e3 < 0 ) e3 = -e3;
430
    e4 = p2*p4+q2*q4+r2*r4; if( e4 < 0 ) e4 = -e4;
431
    if( e1 < e2 ) {
432
        if( e1 < e3 ) {
433
            if( e1 < e4 ) {
434
                rot[0][0] = p1;
435
                rot[0][1] = q1;
436
                rot[0][2] = r1;
437
                rot[1][0] = p3;
438
                rot[1][1] = q3;
439
                rot[1][2] = r3;
440
            }
441
            else {
442
                rot[0][0] = p2;
443
                rot[0][1] = q2;
444
                rot[0][2] = r2;
445
                rot[1][0] = p4;
446
                rot[1][1] = q4;
447
                rot[1][2] = r4;
448
            }
449
        }
450
        else {
451
            if( e3 < e4 ) {
452
                rot[0][0] = p2;
453
                rot[0][1] = q2;
454
                rot[0][2] = r2;
455
                rot[1][0] = p3;
456
                rot[1][1] = q3;
457
                rot[1][2] = r3;
458
            }
459
            else {
460
                rot[0][0] = p2;
461
                rot[0][1] = q2;
462
                rot[0][2] = r2;
463
                rot[1][0] = p4;
464
                rot[1][1] = q4;
465
                rot[1][2] = r4;
466
            }
467
        }
468
    }
469
    else {
470
        if( e2 < e3 ) {
471
            if( e2 < e4 ) {
472
                rot[0][0] = p1;
473
                rot[0][1] = q1;
474
                rot[0][2] = r1;
475
                rot[1][0] = p4;
476
                rot[1][1] = q4;
477
                rot[1][2] = r4;
478
            }
479
            else {
480
                rot[0][0] = p2;
481
                rot[0][1] = q2;
482
                rot[0][2] = r2;
483
                rot[1][0] = p4;
484
                rot[1][1] = q4;
485
                rot[1][2] = r4;
486
            }
487
        }
488
        else {
489
            if( e3 < e4 ) {
490
                rot[0][0] = p2;
491
                rot[0][1] = q2;
492
                rot[0][2] = r2;
493
                rot[1][0] = p3;
494
                rot[1][1] = q3;
495
                rot[1][2] = r3;
496
            }
497
            else {
498
                rot[0][0] = p2;
499
                rot[0][1] = q2;
500
                rot[0][2] = r2;
501
                rot[1][0] = p4;
502
                rot[1][1] = q4;
503
                rot[1][2] = r4;
504
            }
505
        }
506
    }
507
 
508
    return 0;
509
}