Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

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