1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
52 static void icvPseudoInverse3D( float *a, float *b, int n, int method );
54 static CvStatus icvCreatePOSITObject( CvPoint3D32f *points,
56 CvPOSITObject **ppObject )
60 /* Compute size of required memory */
61 /* buffer for inverse matrix = N*3*float */
62 /* buffer for storing weakImagePoints = numPoints * 2 * float */
63 /* buffer for storing object vectors = N*3*float */
64 /* buffer for storing image vectors = N*2*float */
66 int N = numPoints - 1;
67 int inv_matr_size = N * 3 * sizeof( float );
68 int obj_vec_size = inv_matr_size;
69 int img_vec_size = N * 2 * sizeof( float );
70 CvPOSITObject *pObject;
72 /* check bad arguments */
74 return CV_NULLPTR_ERR;
76 return CV_BADSIZE_ERR;
77 if( ppObject == NULL )
78 return CV_NULLPTR_ERR;
80 /* memory allocation */
81 pObject = (CvPOSITObject *) cvAlloc( sizeof( CvPOSITObject ) +
82 inv_matr_size + obj_vec_size + img_vec_size );
85 return CV_OUTOFMEM_ERR;
87 /* part the memory between all structures */
89 pObject->inv_matr = (float *) ((char *) pObject + sizeof( CvPOSITObject ));
90 pObject->obj_vecs = (float *) ((char *) (pObject->inv_matr) + inv_matr_size);
91 pObject->img_vecs = (float *) ((char *) (pObject->obj_vecs) + obj_vec_size);
93 /****************************************************************************************\
94 * Construct object vectors from object points *
95 \****************************************************************************************/
96 for( i = 0; i < numPoints - 1; i++ )
98 pObject->obj_vecs[i] = points[i + 1].x - points[0].x;
99 pObject->obj_vecs[N + i] = points[i + 1].y - points[0].y;
100 pObject->obj_vecs[2 * N + i] = points[i + 1].z - points[0].z;
102 /****************************************************************************************\
103 * Compute pseudoinverse matrix *
104 \****************************************************************************************/
105 icvPseudoInverse3D( pObject->obj_vecs, pObject->inv_matr, N, 0 );
112 static CvStatus icvPOSIT( CvPOSITObject *pObject, CvPoint2D32f *imagePoints,
113 float focalLength, CvTermCriteria criteria,
114 CvMatr32f rotation, CvVect32f translation )
117 int count = 0, converged = 0;
118 float inorm, jnorm, invInorm, invJnorm, invScale, scale = 0, inv_Z = 0;
119 float diff = (float)criteria.epsilon;
120 float inv_focalLength = 1 / focalLength;
124 float *objectVectors = pObject->obj_vecs;
125 float *invMatrix = pObject->inv_matr;
126 float *imgVectors = pObject->img_vecs;
128 /* Check bad arguments */
129 if( imagePoints == NULL )
130 return CV_NULLPTR_ERR;
131 if( pObject == NULL )
132 return CV_NULLPTR_ERR;
133 if( focalLength <= 0 )
134 return CV_BADFACTOR_ERR;
136 return CV_NULLPTR_ERR;
138 return CV_NULLPTR_ERR;
139 if( (criteria.type == 0) || (criteria.type > (CV_TERMCRIT_ITER | CV_TERMCRIT_EPS)))
140 return CV_BADFLAG_ERR;
141 if( (criteria.type & CV_TERMCRIT_EPS) && criteria.epsilon < 0 )
142 return CV_BADFACTOR_ERR;
143 if( (criteria.type & CV_TERMCRIT_ITER) && criteria.max_iter <= 0 )
144 return CV_BADFACTOR_ERR;
150 /* subtract out origin to get image vectors */
151 for( i = 0; i < N; i++ )
153 imgVectors[i] = imagePoints[i + 1].x - imagePoints[0].x;
154 imgVectors[N + i] = imagePoints[i + 1].y - imagePoints[0].y;
160 /* Compute new SOP (scaled orthograthic projection) image from pose */
161 for( i = 0; i < N; i++ )
163 /* objectVector * k */
165 float tmp = objectVectors[i] * rotation[6] /*[2][0]*/ +
166 objectVectors[N + i] * rotation[7] /*[2][1]*/ +
167 objectVectors[2 * N + i] * rotation[8] /*[2][2]*/;
173 imgVectors[i] = imagePoints[i + 1].x * tmp - imagePoints[0].x;
175 diff = MAX( diff, (float) fabs( imgVectors[i] - old ));
177 old = imgVectors[N + i];
178 imgVectors[N + i] = imagePoints[i + 1].y * tmp - imagePoints[0].y;
180 diff = MAX( diff, (float) fabs( imgVectors[N + i] - old ));
184 /* calculate I and J vectors */
185 for( i = 0; i < 2; i++ )
187 for( j = 0; j < 3; j++ )
189 rotation[3*i+j] /*[i][j]*/ = 0;
190 for( k = 0; k < N; k++ )
192 rotation[3*i+j] /*[i][j]*/ += invMatrix[j * N + k] * imgVectors[i * N + k];
197 inorm = rotation[0] /*[0][0]*/ * rotation[0] /*[0][0]*/ +
198 rotation[1] /*[0][1]*/ * rotation[1] /*[0][1]*/ +
199 rotation[2] /*[0][2]*/ * rotation[2] /*[0][2]*/;
201 jnorm = rotation[3] /*[1][0]*/ * rotation[3] /*[1][0]*/ +
202 rotation[4] /*[1][1]*/ * rotation[4] /*[1][1]*/ +
203 rotation[5] /*[1][2]*/ * rotation[5] /*[1][2]*/;
205 invInorm = cvInvSqrt( inorm );
206 invJnorm = cvInvSqrt( jnorm );
211 rotation[0] /*[0][0]*/ *= invInorm;
212 rotation[1] /*[0][1]*/ *= invInorm;
213 rotation[2] /*[0][2]*/ *= invInorm;
215 rotation[3] /*[1][0]*/ *= invJnorm;
216 rotation[4] /*[1][1]*/ *= invJnorm;
217 rotation[5] /*[1][2]*/ *= invJnorm;
219 /* row2 = row0 x row1 (cross product) */
220 rotation[6] /*->m[2][0]*/ = rotation[1] /*->m[0][1]*/ * rotation[5] /*->m[1][2]*/ -
221 rotation[2] /*->m[0][2]*/ * rotation[4] /*->m[1][1]*/;
223 rotation[7] /*->m[2][1]*/ = rotation[2] /*->m[0][2]*/ * rotation[3] /*->m[1][0]*/ -
224 rotation[0] /*->m[0][0]*/ * rotation[5] /*->m[1][2]*/;
226 rotation[8] /*->m[2][2]*/ = rotation[0] /*->m[0][0]*/ * rotation[4] /*->m[1][1]*/ -
227 rotation[1] /*->m[0][1]*/ * rotation[3] /*->m[1][0]*/;
229 scale = (inorm + jnorm) / 2.0f;
230 inv_Z = scale * inv_focalLength;
233 converged = ((criteria.type & CV_TERMCRIT_EPS) && (diff < criteria.epsilon));
234 converged |= ((criteria.type & CV_TERMCRIT_ITER) && (count == criteria.max_iter));
236 invScale = 1 / scale;
237 translation[0] = imagePoints[0].x * invScale;
238 translation[1] = imagePoints[0].y * invScale;
239 translation[2] = 1 / inv_Z;
245 static CvStatus icvReleasePOSITObject( CvPOSITObject ** ppObject )
251 /*F///////////////////////////////////////////////////////////////////////////////////////
252 // Name: icvPseudoInverse3D
253 // Purpose: Pseudoinverse N x 3 matrix N >= 3
257 // b - pseudoinversed a
258 // n - number of rows in a
259 // method - if 0, then b = inv(transpose(a)*a) * transpose(a)
260 // if 1, then SVD used.
262 // Notes: Both matrix are stored by n-dimensional vectors.
263 // Now only method == 0 supported.
266 icvPseudoInverse3D( float *a, float *b, int n, int method )
280 /* compute matrix ata = transpose(a) * a */
281 for( k = 0; k < n; k++ )
285 float a2 = a[2 * n + k];
295 /* inverse matrix ata */
298 float p00 = ata11 * ata22 - ata12 * ata12;
299 float p01 = -(ata01 * ata22 - ata12 * ata02);
300 float p02 = ata12 * ata01 - ata11 * ata02;
302 float p11 = ata00 * ata22 - ata02 * ata02;
303 float p12 = -(ata00 * ata12 - ata01 * ata02);
304 float p22 = ata00 * ata11 - ata01 * ata01;
312 /* compute resultant matrix */
313 for( k = 0; k < n; k++ )
317 float a2 = a[2 * n + k];
319 b[k] = (p00 * a0 + p01 * a1 + p02 * a2) * inv_det;
320 b[n + k] = (p01 * a0 + p11 * a1 + p12 * a2) * inv_det;
321 b[2 * n + k] = (p02 * a0 + p12 * a1 + p22 * a2) * inv_det;
334 CV_IMPL CvPOSITObject *
335 cvCreatePOSITObject( CvPoint3D32f * points, int numPoints )
337 CvPOSITObject *pObject = 0;
339 CV_FUNCNAME( "cvCreatePOSITObject" );
343 IPPI_CALL( icvCreatePOSITObject( points, numPoints, &pObject ));
352 cvPOSIT( CvPOSITObject * pObject, CvPoint2D32f * imagePoints,
353 double focalLength, CvTermCriteria criteria,
354 CvMatr32f rotation, CvVect32f translation )
356 CV_FUNCNAME( "cvPOSIT" );
360 IPPI_CALL( icvPOSIT( pObject, imagePoints,(float) focalLength, criteria,
361 rotation, translation ));
367 cvReleasePOSITObject( CvPOSITObject ** ppObject )
369 CV_FUNCNAME( "cvReleasePOSITObject" );
373 IPPI_CALL( icvReleasePOSITObject( ppObject ));