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 <stdlib.h>
4
#include <AR/param.h>
5
#include <AR/matrix.h>
6
#include "calib_camera.h"
7
 
8
static double   get_fitting_error( CALIB_PATT_T *patt, double dist_factor[4] );
9
static double   check_error( double *x, double *y, int num, double dist_factor[4] );
10
static double   calc_distortion2( CALIB_PATT_T *patt, double dist_factor[4] );
11
static double   get_size_factor( double dist_factor[4], int xsize, int ysize );
12
 
13
void calc_distortion( CALIB_PATT_T *patt, int xsize, int ysize, double dist_factor[4] )
14
{
15
    int     i, j;
16
    double  bx, by;
17
    double  bf[4];
18
    double  error, min;
19
    double  factor[4];
20
 
21
    bx = xsize / 2;
22
    by = ysize / 2;
23
    factor[0] = bx;
24
    factor[1] = by;
25
    factor[3] = 1.0;
26
    min = calc_distortion2( patt, factor );
27
    bf[0] = factor[0];
28
    bf[1] = factor[1];
29
    bf[2] = factor[2];
30
    bf[3] = 1.0;
31
printf("[%5.1f, %5.1f, %5.1f] %f\n", bf[0], bf[1], bf[2], min);
32
    for( j = -10; j <= 10; j++ ) {
33
        factor[1] = by + j*5;
34
        for( i = -10; i <= 10; i++ ) {
35
            factor[0] = bx + i*5;
36
            error = calc_distortion2( patt, factor );
37
            if( error < min ) { bf[0] = factor[0]; bf[1] = factor[1];
38
                                bf[2] = factor[2]; min = error; }
39
        }
40
printf("[%5.1f, %5.1f, %5.1f] %f\n", bf[0], bf[1], bf[2], min);
41
    }
42
 
43
    bx = bf[0];
44
    by = bf[1];
45
    for( j = -10; j <= 10; j++ ) {
46
        factor[1] = by + 0.5 * j;
47
        for( i = -10; i <= 10; i++ ) {
48
            factor[0] = bx + 0.5 * i;
49
            error = calc_distortion2( patt, factor );
50
            if( error < min ) { bf[0] = factor[0]; bf[1] = factor[1];
51
                                bf[2] = factor[2]; min = error; }
52
        }
53
printf("[%5.1f, %5.1f, %5.1f] %f\n", bf[0], bf[1], bf[2], min);
54
    }
55
 
56
    dist_factor[0] = bf[0];
57
    dist_factor[1] = bf[1];
58
    dist_factor[2] = bf[2];
59
    dist_factor[3] = get_size_factor( bf, xsize, ysize );
60
}
61
 
62
static double get_size_factor( double dist_factor[4], int xsize, int ysize )
63
{
64
    double  ox, oy, ix, iy;
65
    double  olen, ilen;
66
    double  sf, sf1;
67
 
68
    sf = 100.0;
69
 
70
    ox = 0.0;
71
    oy = dist_factor[1];
72
    olen = dist_factor[0];
73
    arParamObserv2Ideal( dist_factor, ox, oy, &ix, &iy );
74
    ilen = dist_factor[0] - ix;
75
printf("Olen = %f, Ilen = %f\n", olen, ilen);
76
    if( ilen > 0 ) {
77
        sf1 = ilen / olen;
78
        if( sf1 < sf ) sf = sf1;
79
    }
80
 
81
    ox = xsize;
82
    oy = dist_factor[1];
83
    olen = xsize - dist_factor[0];
84
    arParamObserv2Ideal( dist_factor, ox, oy, &ix, &iy );
85
    ilen = ix - dist_factor[0];
86
printf("Olen = %f, Ilen = %f\n", olen, ilen);
87
    if( ilen > 0 ) {
88
        sf1 = ilen / olen;
89
        if( sf1 < sf ) sf = sf1;
90
    }
91
 
92
    ox = dist_factor[0];
93
    oy = 0.0;
94
    olen = dist_factor[1];
95
    arParamObserv2Ideal( dist_factor, ox, oy, &ix, &iy );
96
    ilen = dist_factor[1] - iy;
97
printf("Olen = %f, Ilen = %f\n", olen, ilen);
98
    if( ilen > 0 ) {
99
        sf1 = ilen / olen;
100
        if( sf1 < sf ) sf = sf1;
101
    }
102
 
103
    ox = dist_factor[0];
104
    oy = ysize;
105
    olen = ysize - dist_factor[1];
106
    arParamObserv2Ideal( dist_factor, ox, oy, &ix, &iy );
107
    ilen = iy - dist_factor[1];
108
printf("Olen = %f, Ilen = %f\n", olen, ilen);
109
    if( ilen > 0 ) {
110
        sf1 = ilen / olen;
111
        if( sf1 < sf ) sf = sf1;
112
    }
113
 
114
    if( sf == 0.0 ) sf = 1.0;
115
 
116
    return sf;
117
}
118
 
119
static double calc_distortion2( CALIB_PATT_T *patt, double dist_factor[4] )
120
{
121
    double    min, err, f, fb;
122
    int       i;
123
 
124
    dist_factor[2] = 0.0;
125
    min = get_fitting_error( patt, dist_factor );
126
 
127
    f = dist_factor[2];
128
    for( i = -100; i < 200; i+=10 ) {
129
        dist_factor[2] = i;
130
        err = get_fitting_error( patt, dist_factor );
131
        if( err < min ) { min = err; f = dist_factor[2]; }
132
    }
133
 
134
    fb = f;
135
    for( i = -10; i <= 10; i++ ) {
136
        dist_factor[2] = fb + i;
137
/*
138
        if( dist_factor[2] < 0 ) continue;
139
*/
140
        err = get_fitting_error( patt, dist_factor );
141
        if( err < min ) { min = err; f = dist_factor[2]; }
142
    }
143
 
144
    fb = f;
145
    for( i = -10; i <= 10; i++ ) {
146
        dist_factor[2] = fb + 0.1 * i;
147
/*
148
        if( dist_factor[2] < 0 ) continue;
149
*/
150
        err = get_fitting_error( patt, dist_factor );
151
        if( err < min ) { min = err; f = dist_factor[2]; }
152
    }
153
 
154
    dist_factor[2] = f;
155
    return min;
156
}
157
 
158
static double get_fitting_error( CALIB_PATT_T *patt, double dist_factor[4] )
159
{
160
    double   *x, *y;
161
    double   error;
162
    int      max;
163
    int      i, j, k, l;
164
    int      p, c;
165
 
166
    max = (patt->v_num > patt->h_num)? patt->v_num: patt->h_num;
167
    x = (double *)malloc( sizeof(double)*max );
168
    y = (double *)malloc( sizeof(double)*max );
169
    if( x == NULL || y == NULL ) exit(0);
170
 
171
    error = 0.0;
172
    c = 0;
173
    for( i = 0; i < patt->loop_num; i++ ) {
174
        for( j = 0; j < patt->v_num; j++ ) {
175
            for( k = 0; k < patt->h_num; k++ ) {
176
                x[k] = patt->point[i][j*patt->h_num+k].x_coord;
177
                y[k] = patt->point[i][j*patt->h_num+k].y_coord;
178
            }
179
            error += check_error( x, y, patt->h_num, dist_factor );
180
            c += patt->h_num;
181
        }
182
 
183
        for( j = 0; j < patt->h_num; j++ ) {
184
            for( k = 0; k < patt->v_num; k++ ) {
185
                x[k] = patt->point[i][k*patt->h_num+j].x_coord;
186
                y[k] = patt->point[i][k*patt->h_num+j].y_coord;
187
            }
188
            error += check_error( x, y, patt->v_num, dist_factor );
189
            c += patt->v_num;
190
        }
191
 
192
        for( j = 3 - patt->v_num; j < patt->h_num - 2; j++ ) {
193
            p = 0;
194
            for( k = 0; k < patt->v_num; k++ ) {
195
                l = j+k;
196
                if( l < 0 || l >= patt->h_num ) continue;
197
                x[p] = patt->point[i][k*patt->h_num+l].x_coord;
198
                y[p] = patt->point[i][k*patt->h_num+l].y_coord;
199
                p++;
200
            }
201
            error += check_error( x, y, p, dist_factor );
202
            c += p;
203
        }
204
 
205
        for( j = 2; j < patt->h_num + patt->v_num - 3; j++ ) {
206
            p = 0;
207
            for( k = 0; k < patt->v_num; k++ ) {
208
                l = j-k;
209
                if( l < 0 || l >= patt->h_num ) continue;
210
                x[p] = patt->point[i][k*patt->h_num+l].x_coord;
211
                y[p] = patt->point[i][k*patt->h_num+l].y_coord;
212
                p++;
213
            }
214
            error += check_error( x, y, p, dist_factor );
215
            c += p;
216
        }
217
    }
218
 
219
    free( x );
220
    free( y );
221
 
222
    return sqrt(error/c);
223
}
224
 
225
static double check_error( double *x, double *y, int num, double dist_factor[4] )
226
{
227
    ARMat    *input, *evec;
228
    ARVec    *ev, *mean;
229
    double   a, b, c;
230
    double   error;
231
    int      i;
232
 
233
    ev     = arVecAlloc( 2 );
234
    mean   = arVecAlloc( 2 );
235
    evec   = arMatrixAlloc( 2, 2 );
236
 
237
    input  = arMatrixAlloc( num, 2 );
238
    for( i = 0; i < num; i++ ) {
239
        arParamObserv2Ideal( dist_factor, x[i], y[i],
240
                             &(input->m[i*2+0]), &(input->m[i*2+1]) );
241
    }
242
    if( arMatrixPCA(input, evec, ev, mean) < 0 ) exit(0);
243
    a =  evec->m[1];
244
    b = -evec->m[0];
245
    c = -(a*mean->v[0] + b*mean->v[1]);
246
 
247
    error = 0.0;
248
    for( i = 0; i < num; i++ ) {
249
        error += (a*input->m[i*2+0] + b*input->m[i*2+1] + c)
250
               * (a*input->m[i*2+0] + b*input->m[i*2+1] + c);
251
    }
252
    error /= (a*a + b*b);
253
 
254
    arMatrixFree( input );
255
    arMatrixFree( evec );
256
    arVecFree( mean );
257
    arVecFree( ev );
258
 
259
    return error;
260
}