Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/calib3d/src/posit.cpp
16354 views
1
/*M///////////////////////////////////////////////////////////////////////////////////////
2
//
3
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
//
5
// By downloading, copying, installing or using the software you agree to this license.
6
// If you do not agree to this license, do not download, install,
7
// copy or use the software.
8
//
9
//
10
// Intel License Agreement
11
// For Open Source Computer Vision Library
12
//
13
// Copyright (C) 2000, Intel Corporation, all rights reserved.
14
// Third party copyrights are property of their respective owners.
15
//
16
// Redistribution and use in source and binary forms, with or without modification,
17
// are permitted provided that the following conditions are met:
18
//
19
// * Redistribution's of source code must retain the above copyright notice,
20
// this list of conditions and the following disclaimer.
21
//
22
// * Redistribution's in binary form must reproduce the above copyright notice,
23
// this list of conditions and the following disclaimer in the documentation
24
// and/or other materials provided with the distribution.
25
//
26
// * The name of Intel Corporation may not be used to endorse or promote products
27
// derived from this software without specific prior written permission.
28
//
29
// This software is provided by the copyright holders and contributors "as is" and
30
// any express or implied warranties, including, but not limited to, the implied
31
// warranties of merchantability and fitness for a particular purpose are disclaimed.
32
// In no event shall the Intel Corporation or contributors be liable for any direct,
33
// indirect, incidental, special, exemplary, or consequential damages
34
// (including, but not limited to, procurement of substitute goods or services;
35
// loss of use, data, or profits; or business interruption) however caused
36
// and on any theory of liability, whether in contract, strict liability,
37
// or tort (including negligence or otherwise) arising in any way out of
38
// the use of this software, even if advised of the possibility of such damage.
39
//
40
//M*/
41
#include "precomp.hpp"
42
#include "opencv2/calib3d/calib3d_c.h"
43
44
/* POSIT structure */
45
struct CvPOSITObject
46
{
47
int N;
48
float* inv_matr;
49
float* obj_vecs;
50
float* img_vecs;
51
};
52
53
static void icvPseudoInverse3D( float *a, float *b, int n, int method );
54
55
static CvStatus icvCreatePOSITObject( CvPoint3D32f *points,
56
int numPoints,
57
CvPOSITObject **ppObject )
58
{
59
int i;
60
61
/* Compute size of required memory */
62
/* buffer for inverse matrix = N*3*float */
63
/* buffer for storing weakImagePoints = numPoints * 2 * float */
64
/* buffer for storing object vectors = N*3*float */
65
/* buffer for storing image vectors = N*2*float */
66
67
int N = numPoints - 1;
68
int inv_matr_size = N * 3 * sizeof( float );
69
int obj_vec_size = inv_matr_size;
70
int img_vec_size = N * 2 * sizeof( float );
71
CvPOSITObject *pObject;
72
73
/* check bad arguments */
74
if( points == NULL )
75
return CV_NULLPTR_ERR;
76
if( numPoints < 4 )
77
return CV_BADSIZE_ERR;
78
if( ppObject == NULL )
79
return CV_NULLPTR_ERR;
80
81
/* memory allocation */
82
pObject = (CvPOSITObject *) cvAlloc( sizeof( CvPOSITObject ) +
83
inv_matr_size + obj_vec_size + img_vec_size );
84
85
if( !pObject )
86
return CV_OUTOFMEM_ERR;
87
88
/* part the memory between all structures */
89
pObject->N = N;
90
pObject->inv_matr = (float *) ((char *) pObject + sizeof( CvPOSITObject ));
91
pObject->obj_vecs = (float *) ((char *) (pObject->inv_matr) + inv_matr_size);
92
pObject->img_vecs = (float *) ((char *) (pObject->obj_vecs) + obj_vec_size);
93
94
/****************************************************************************************\
95
* Construct object vectors from object points *
96
\****************************************************************************************/
97
for( i = 0; i < numPoints - 1; i++ )
98
{
99
pObject->obj_vecs[i] = points[i + 1].x - points[0].x;
100
pObject->obj_vecs[N + i] = points[i + 1].y - points[0].y;
101
pObject->obj_vecs[2 * N + i] = points[i + 1].z - points[0].z;
102
}
103
/****************************************************************************************\
104
* Compute pseudoinverse matrix *
105
\****************************************************************************************/
106
icvPseudoInverse3D( pObject->obj_vecs, pObject->inv_matr, N, 0 );
107
108
*ppObject = pObject;
109
return CV_NO_ERR;
110
}
111
112
113
static CvStatus icvPOSIT( CvPOSITObject *pObject, CvPoint2D32f *imagePoints,
114
float focalLength, CvTermCriteria criteria,
115
float* rotation, float* translation )
116
{
117
int i, j, k;
118
int count = 0;
119
bool converged = false;
120
float scale = 0, inv_Z = 0;
121
float diff = (float)criteria.epsilon;
122
123
/* Check bad arguments */
124
if( imagePoints == NULL )
125
return CV_NULLPTR_ERR;
126
if( pObject == NULL )
127
return CV_NULLPTR_ERR;
128
if( focalLength <= 0 )
129
return CV_BADFACTOR_ERR;
130
if( !rotation )
131
return CV_NULLPTR_ERR;
132
if( !translation )
133
return CV_NULLPTR_ERR;
134
if( (criteria.type == 0) || (criteria.type > (CV_TERMCRIT_ITER | CV_TERMCRIT_EPS)))
135
return CV_BADFLAG_ERR;
136
if( (criteria.type & CV_TERMCRIT_EPS) && criteria.epsilon < 0 )
137
return CV_BADFACTOR_ERR;
138
if( (criteria.type & CV_TERMCRIT_ITER) && criteria.max_iter <= 0 )
139
return CV_BADFACTOR_ERR;
140
141
/* init variables */
142
float inv_focalLength = 1 / focalLength;
143
int N = pObject->N;
144
float *objectVectors = pObject->obj_vecs;
145
float *invMatrix = pObject->inv_matr;
146
float *imgVectors = pObject->img_vecs;
147
148
while( !converged )
149
{
150
if( count == 0 )
151
{
152
/* subtract out origin to get image vectors */
153
for( i = 0; i < N; i++ )
154
{
155
imgVectors[i] = imagePoints[i + 1].x - imagePoints[0].x;
156
imgVectors[N + i] = imagePoints[i + 1].y - imagePoints[0].y;
157
}
158
}
159
else
160
{
161
diff = 0;
162
/* Compute new SOP (scaled orthograthic projection) image from pose */
163
for( i = 0; i < N; i++ )
164
{
165
/* objectVector * k */
166
float old;
167
float tmp = objectVectors[i] * rotation[6] /*[2][0]*/ +
168
objectVectors[N + i] * rotation[7] /*[2][1]*/ +
169
objectVectors[2 * N + i] * rotation[8] /*[2][2]*/;
170
171
tmp *= inv_Z;
172
tmp += 1;
173
174
old = imgVectors[i];
175
imgVectors[i] = imagePoints[i + 1].x * tmp - imagePoints[0].x;
176
177
diff = MAX( diff, (float) fabs( imgVectors[i] - old ));
178
179
old = imgVectors[N + i];
180
imgVectors[N + i] = imagePoints[i + 1].y * tmp - imagePoints[0].y;
181
182
diff = MAX( diff, (float) fabs( imgVectors[N + i] - old ));
183
}
184
}
185
186
/* calculate I and J vectors */
187
for( i = 0; i < 2; i++ )
188
{
189
for( j = 0; j < 3; j++ )
190
{
191
rotation[3*i+j] /*[i][j]*/ = 0;
192
for( k = 0; k < N; k++ )
193
{
194
rotation[3*i+j] /*[i][j]*/ += invMatrix[j * N + k] * imgVectors[i * N + k];
195
}
196
}
197
}
198
199
float inorm =
200
rotation[0] /*[0][0]*/ * rotation[0] /*[0][0]*/ +
201
rotation[1] /*[0][1]*/ * rotation[1] /*[0][1]*/ +
202
rotation[2] /*[0][2]*/ * rotation[2] /*[0][2]*/;
203
204
float jnorm =
205
rotation[3] /*[1][0]*/ * rotation[3] /*[1][0]*/ +
206
rotation[4] /*[1][1]*/ * rotation[4] /*[1][1]*/ +
207
rotation[5] /*[1][2]*/ * rotation[5] /*[1][2]*/;
208
209
const float invInorm = cvInvSqrt( inorm );
210
const float invJnorm = cvInvSqrt( jnorm );
211
212
inorm *= invInorm;
213
jnorm *= invJnorm;
214
215
rotation[0] /*[0][0]*/ *= invInorm;
216
rotation[1] /*[0][1]*/ *= invInorm;
217
rotation[2] /*[0][2]*/ *= invInorm;
218
219
rotation[3] /*[1][0]*/ *= invJnorm;
220
rotation[4] /*[1][1]*/ *= invJnorm;
221
rotation[5] /*[1][2]*/ *= invJnorm;
222
223
/* row2 = row0 x row1 (cross product) */
224
rotation[6] /*->m[2][0]*/ = rotation[1] /*->m[0][1]*/ * rotation[5] /*->m[1][2]*/ -
225
rotation[2] /*->m[0][2]*/ * rotation[4] /*->m[1][1]*/;
226
227
rotation[7] /*->m[2][1]*/ = rotation[2] /*->m[0][2]*/ * rotation[3] /*->m[1][0]*/ -
228
rotation[0] /*->m[0][0]*/ * rotation[5] /*->m[1][2]*/;
229
230
rotation[8] /*->m[2][2]*/ = rotation[0] /*->m[0][0]*/ * rotation[4] /*->m[1][1]*/ -
231
rotation[1] /*->m[0][1]*/ * rotation[3] /*->m[1][0]*/;
232
233
scale = (inorm + jnorm) / 2.0f;
234
inv_Z = scale * inv_focalLength;
235
236
count++;
237
converged = ((criteria.type & CV_TERMCRIT_EPS) && (diff < criteria.epsilon))
238
|| ((criteria.type & CV_TERMCRIT_ITER) && (count == criteria.max_iter));
239
}
240
const float invScale = 1 / scale;
241
translation[0] = imagePoints[0].x * invScale;
242
translation[1] = imagePoints[0].y * invScale;
243
translation[2] = 1 / inv_Z;
244
245
return CV_NO_ERR;
246
}
247
248
249
static CvStatus icvReleasePOSITObject( CvPOSITObject ** ppObject )
250
{
251
cvFree( ppObject );
252
return CV_NO_ERR;
253
}
254
255
/*F///////////////////////////////////////////////////////////////////////////////////////
256
// Name: icvPseudoInverse3D
257
// Purpose: Pseudoinverse N x 3 matrix N >= 3
258
// Context:
259
// Parameters:
260
// a - input matrix
261
// b - pseudoinversed a
262
// n - number of rows in a
263
// method - if 0, then b = inv(transpose(a)*a) * transpose(a)
264
// if 1, then SVD used.
265
// Returns:
266
// Notes: Both matrix are stored by n-dimensional vectors.
267
// Now only method == 0 supported.
268
//F*/
269
void
270
icvPseudoInverse3D( float *a, float *b, int n, int method )
271
{
272
if( method == 0 )
273
{
274
float ata00 = 0;
275
float ata11 = 0;
276
float ata22 = 0;
277
float ata01 = 0;
278
float ata02 = 0;
279
float ata12 = 0;
280
281
int k;
282
/* compute matrix ata = transpose(a) * a */
283
for( k = 0; k < n; k++ )
284
{
285
float a0 = a[k];
286
float a1 = a[n + k];
287
float a2 = a[2 * n + k];
288
289
ata00 += a0 * a0;
290
ata11 += a1 * a1;
291
ata22 += a2 * a2;
292
293
ata01 += a0 * a1;
294
ata02 += a0 * a2;
295
ata12 += a1 * a2;
296
}
297
/* inverse matrix ata */
298
{
299
float p00 = ata11 * ata22 - ata12 * ata12;
300
float p01 = -(ata01 * ata22 - ata12 * ata02);
301
float p02 = ata12 * ata01 - ata11 * ata02;
302
303
float p11 = ata00 * ata22 - ata02 * ata02;
304
float p12 = -(ata00 * ata12 - ata01 * ata02);
305
float p22 = ata00 * ata11 - ata01 * ata01;
306
307
float det = 0;
308
det += ata00 * p00;
309
det += ata01 * p01;
310
det += ata02 * p02;
311
312
const float inv_det = 1 / det;
313
314
/* compute resultant matrix */
315
for( k = 0; k < n; k++ )
316
{
317
float a0 = a[k];
318
float a1 = a[n + k];
319
float a2 = a[2 * n + k];
320
321
b[k] = (p00 * a0 + p01 * a1 + p02 * a2) * inv_det;
322
b[n + k] = (p01 * a0 + p11 * a1 + p12 * a2) * inv_det;
323
b[2 * n + k] = (p02 * a0 + p12 * a1 + p22 * a2) * inv_det;
324
}
325
}
326
}
327
328
/*if ( method == 1 )
329
{
330
}
331
*/
332
333
return;
334
}
335
336
CV_IMPL CvPOSITObject *
337
cvCreatePOSITObject( CvPoint3D32f * points, int numPoints )
338
{
339
CvPOSITObject *pObject = 0;
340
IPPI_CALL( icvCreatePOSITObject( points, numPoints, &pObject ));
341
return pObject;
342
}
343
344
345
CV_IMPL void
346
cvPOSIT( CvPOSITObject * pObject, CvPoint2D32f * imagePoints,
347
double focalLength, CvTermCriteria criteria,
348
float* rotation, float* translation )
349
{
350
IPPI_CALL( icvPOSIT( pObject, imagePoints,(float) focalLength, criteria,
351
rotation, translation ));
352
}
353
354
CV_IMPL void
355
cvReleasePOSITObject( CvPOSITObject ** ppObject )
356
{
357
IPPI_CALL( icvReleasePOSITObject( ppObject ));
358
}
359
360
/* End of file. */
361
362