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.
42 #include "precomp.hpp"
43 #include "opencv2/calib3d/calib3d_c.h"
51 /* Function defenitions */
53 /* ----------------- */
55 void cvOptimizeLevenbergMarquardtBundle( CvMat** projMatrs, CvMat** observProjPoints,
56 CvMat** pointsPres, int numImages,
57 CvMat** resultProjMatrs, CvMat* resultPoints4D,int maxIter,double epsilon );
59 int icvComputeProjectMatrices6Points( CvMat* points1,CvMat* points2,CvMat* points3,
60 CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3);
62 void icvFindBaseTransform(CvMat* points,CvMat* resultT);
64 void GetGeneratorReduceFundSolution(CvMat* points1,CvMat* points2,CvMat* fundReduceCoef1,CvMat* fundReduceCoef2);
66 int GetGoodReduceFundamMatrFromTwo(CvMat* fundReduceCoef1,CvMat* fundReduceCoef2,CvMat* resFundReduceCoef);
68 void GetProjMatrFromReducedFundamental(CvMat* fundReduceCoefs,CvMat* projMatrCoefs);
70 void icvComputeProjectMatrix(CvMat* objPoints,CvMat* projPoints,CvMat* projMatr);
72 void icvComputeTransform4D(CvMat* points1,CvMat* points2,CvMat* transMatr);
74 int icvComputeProjectMatricesNPoints( CvMat* points1,CvMat* points2,CvMat* points3,
75 CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
76 double threshold,/* Threshold for good point */
77 double p,/* Probability of good result. */
81 int icvComputeProjectMatricesNPoints( CvMat* points1,CvMat* points2,CvMat* points3,
82 CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
83 double threshold,/* Threshold for good point */
84 double p,/* Probability of good result. */
88 void icvReconstructPointsFor3View( CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
89 CvMat* projPoints1,CvMat* projPoints2,CvMat* projPoints3,
92 void icvReconstructPointsFor3View( CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
93 CvMat* projPoints1,CvMat* projPoints2,CvMat* projPoints3,
96 /*==========================================================================================*/
97 /* Functions for calculation the tensor */
98 /*==========================================================================================*/
101 static void fprintMatrix(FILE* file,CvMat* matrix)
105 for( i=0;i<matrix->rows;i++ )
107 for(j=0;j<matrix->cols;j++)
109 fprintf(file,"%10.7lf ",cvmGet(matrix,i,j));
115 /*==========================================================================================*/
117 static void icvNormalizePoints( CvMat* points, CvMat* normPoints,CvMat* cameraMatr )
119 /* Normalize image points using camera matrix */
121 CV_FUNCNAME( "icvNormalizePoints" );
124 /* Test for null pointers */
125 if( points == 0 || normPoints == 0 || cameraMatr == 0 )
127 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
130 if( !CV_IS_MAT(points) || !CV_IS_MAT(normPoints) || !CV_IS_MAT(cameraMatr) )
132 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
136 numPoints = points->cols;
137 if( numPoints <= 0 || numPoints != normPoints->cols )
139 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be the same and more than 0" );
142 if( normPoints->rows != 2 || normPoints->rows != points->rows )
144 CV_ERROR( CV_StsUnmatchedSizes, "Points must have 2 coordinates" );
147 if(cameraMatr->rows != 3 || cameraMatr->cols != 3)
149 CV_ERROR( CV_StsUnmatchedSizes, "Size of camera matrix must be 3x3" );
154 fx = cvmGet(cameraMatr,0,0);
155 fy = cvmGet(cameraMatr,1,1);
156 cx = cvmGet(cameraMatr,0,2);
157 cy = cvmGet(cameraMatr,1,2);
160 for( i = 0; i < numPoints; i++ )
162 cvmSet(normPoints, 0, i, (cvmGet(points,0,i) - cx) / fx );
163 cvmSet(normPoints, 1, i, (cvmGet(points,1,i) - cy) / fy );
172 /*=====================================================================================*/
174 Computes projection matrices for given 6 points on 3 images
175 May returns 3 results. */
176 int icvComputeProjectMatrices6Points( CvMat* points1,CvMat* points2,CvMat* points3,
177 CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3/*,
180 /* Test input data correctness */
184 CV_FUNCNAME( "icvComputeProjectMatrices6Points" );
187 /* Test for null pointers */
188 if( points1 == 0 || points2 == 0 || points3 == 0 ||
189 projMatr1 == 0 || projMatr2 == 0 || projMatr3 == 0 )
191 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
194 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2) || !CV_IS_MAT(points3) ||
195 !CV_IS_MAT(projMatr1) || !CV_IS_MAT(projMatr2) || !CV_IS_MAT(projMatr3) )
197 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
200 if( (points1->cols != points2->cols) || (points1->cols != points3->cols) || (points1->cols != 6) /* || (points4D->cols !=6) */)
202 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be same and == 6" );
205 if( points1->rows != 2 || points2->rows != 2 || points3->rows != 2 )
207 CV_ERROR( CV_StsUnmatchedSizes, "Number of points coordinates must be 2" );
210 if( projMatr1->cols != 4 || projMatr2->cols != 4 || projMatr3->cols != 4 ||
211 (!(projMatr1->rows == 3 && projMatr2->rows == 3 && projMatr3->rows == 3) &&
212 !(projMatr1->rows == 9 && projMatr2->rows == 9 && projMatr3->rows == 9)) )
214 CV_ERROR( CV_StsUnmatchedSizes, "Size of project matrix must be 3x4 or 9x4 (for 3 matrices)" );
218 if( points4D->row != 4 )
220 CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of points4D must be 4" );
224 /* Find transform matrix for each camera */
232 projMatrs[0] = projMatr1;
233 projMatrs[1] = projMatr2;
234 projMatrs[2] = projMatr3;
237 double transMatr_dat[9];
238 transMatr = cvMat(3,3,CV_64F,transMatr_dat);
243 double corrPoints_dat[3*3*2];/* 3-point(images) by 3-coordinates by 2-correspondence*/
245 corrPoints1 = cvMat(3,3,CV_64F,corrPoints_dat); /* 3-coordinates for each of 3-points(3-image) */
246 corrPoints2 = cvMat(3,3,CV_64F,corrPoints_dat+9);/* 3-coordinates for each of 3-points(3-image) */
248 for( i = 0; i < 3; i++ )/* for each image */
250 /* Get last 4 points for computing transformation */
252 /* find base points transform for last four points on i-th image */
253 cvGetSubRect(points[i],&tmpPoints,cvRect(2,0,4,2));
254 icvFindBaseTransform(&tmpPoints,&transMatr);
256 {/* We have base transform. Compute error scales for three first points */
258 double trPoint_dat[3*3];
259 trPoint = cvMat(3,3,CV_64F,trPoint_dat);
261 for( int kk = 0; kk < 3; kk++ )
263 cvmSet(&trPoint,0,kk,cvmGet(points[i],0,kk+2));
264 cvmSet(&trPoint,1,kk,cvmGet(points[i],1,kk+2));
265 cvmSet(&trPoint,2,kk,1);
268 /* Transform points */
270 double resPnts_dat[9];
271 resPnts = cvMat(3,3,CV_64F,resPnts_dat);
272 cvmMul(&transMatr,&trPoint,&resPnts);
275 /* Transform two first points */
276 for( int j = 0; j < 2; j++ )
280 pnt = cvMat(3,1,CV_64F,pnt_dat);
281 pnt_dat[0] = cvmGet(points[i],0,j);
282 pnt_dat[1] = cvmGet(points[i],1,j);
287 trPnt = cvMat(3,1,CV_64F,trPnt_dat);
289 cvmMul(&transMatr,&pnt,&trPnt);
291 /* Collect transformed points */
292 corrPoints_dat[j * 9 + 0 * 3 + i] = trPnt_dat[0];/* x */
293 corrPoints_dat[j * 9 + 1 * 3 + i] = trPnt_dat[1];/* y */
294 corrPoints_dat[j * 9 + 2 * 3 + i] = trPnt_dat[2];/* w */
298 /* We have computed corr points. Now we can compute generators for reduced fundamental matrix */
300 /* Compute generators for reduced fundamental matrix from 3 pair of collect points */
301 CvMat fundReduceCoef1;
302 CvMat fundReduceCoef2;
303 double fundReduceCoef1_dat[5];
304 double fundReduceCoef2_dat[5];
306 fundReduceCoef1 = cvMat(1,5,CV_64F,fundReduceCoef1_dat);
307 fundReduceCoef2 = cvMat(1,5,CV_64F,fundReduceCoef2_dat);
309 GetGeneratorReduceFundSolution(&corrPoints1, &corrPoints2, &fundReduceCoef1, &fundReduceCoef2);
311 /* Choose best solutions for two generators. We can get 3 solutions */
312 CvMat resFundReduceCoef;
313 double resFundReduceCoef_dat[3*5];
315 resFundReduceCoef = cvMat(3,5,CV_64F,resFundReduceCoef_dat);
317 numSol = GetGoodReduceFundamMatrFromTwo(&fundReduceCoef1, &fundReduceCoef2,&resFundReduceCoef);
320 maxSol = projMatrs[0]->rows / 3;
323 for( currSol = 0; (currSol < numSol && currSol < maxSol); currSol++ )
325 /* For current solution compute projection matrix */
327 cvGetSubRect(&resFundReduceCoef, &fundCoefs, cvRect(0,currSol,5,1));
330 double projMatrCoefs_dat[4];
331 projMatrCoefs = cvMat(1,4,CV_64F,projMatrCoefs_dat);
333 GetProjMatrFromReducedFundamental(&fundCoefs,&projMatrCoefs);
334 /* we have computed coeffs for reduced project matrix */
337 double objPoints_dat[4*6];
338 objPoints = cvMat(4,6,CV_64F,objPoints_dat);
341 /* fill object points */
342 for( i =0; i < 4; i++ )
344 objPoints_dat[i*6] = 1;
345 objPoints_dat[i*6+1] = projMatrCoefs_dat[i];
346 objPoints_dat[i*7+2] = 1;
350 for( currCamera = 0; currCamera < 3; currCamera++ )
354 double projPoints_dat[3*6];
355 projPoints = cvMat(3,6,CV_64F,projPoints_dat);
357 /* fill projected points for current camera */
358 for( i = 0; i < 6; i++ )/* for each points for current camera */
360 projPoints_dat[6*0+i] = cvmGet(points[currCamera],0,i);/* x */
361 projPoints_dat[6*1+i] = cvmGet(points[currCamera],1,i);/* y */
362 projPoints_dat[6*2+i] = 1;/* w */
365 /* compute project matrix for current camera */
367 double projMatrix_dat[3*4];
368 projMatrix = cvMat(3,4,CV_64F,projMatrix_dat);
370 icvComputeProjectMatrix(&objPoints,&projPoints,&projMatrix);
372 /* Add this matrix to result */
374 cvGetSubRect(projMatrs[currCamera],&tmpSubRes,cvRect(0,currSol*3,4,3));
375 cvConvert(&projMatrix,&tmpSubRes);
378 /* We know project matrices. And we can reconstruct 6 3D-points if need */
382 if( currSol < points4D->rows / 4 )
385 double tmpPoints4D_dat[4*6];
386 tmpPoints4D = cvMat(4,6,CV_64F,tmpPoints4D_dat);
388 icvReconstructPointsFor3View( &wProjMatr[0], &wProjMatr[1], &wProjMatr[2],
389 points1, points2, points3,
393 cvGetSubRect(points4D,tmpSubRes,cvRect(0,currSol*4,6,4));
394 cvConvert(tmpPoints4D,points4D);
399 }/* for all sollutions */
405 /*==========================================================================================*/
406 static int icvGetRandNumbers(int range,int count,int* arr)
408 /* Generate random numbers [0,range-1] */
410 CV_FUNCNAME( "icvGetRandNumbers" );
413 /* Test input data */
416 CV_ERROR( CV_StsNullPtr, "Parameter 'arr' is a NULL pointer" );
420 /* Test for errors input data */
421 if( range < count || range <= 0 )
423 CV_ERROR( CV_StsOutOfRange, "Can't generate such numbers. Count must be <= range and range must be > 0" );
428 for( i = 0; i < count; i++ )
431 int haveRep = 0;/* firstly we have not repeats */
434 /* generate new number */
435 newRand = rand()%range;
437 /* Test for repeats in previous numbers */
438 for( j = 0; j < i; j++ )
440 if( arr[j] == newRand )
448 /* We have good random number */
454 /*==========================================================================================*/
455 static void icvSelectColsByNumbers(CvMat* srcMatr, CvMat* dstMatr, int* indexes,int number)
458 CV_FUNCNAME( "icvSelectColsByNumbers" );
461 /* Test input data */
462 if( srcMatr == 0 || dstMatr == 0 || indexes == 0)
464 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
467 if( !CV_IS_MAT(srcMatr) || !CV_IS_MAT(dstMatr) )
469 CV_ERROR( CV_StsUnsupportedFormat, "srcMatr and dstMatr must be a matrices" );
474 numRows = srcMatr->rows;
475 srcSize = srcMatr->cols;
477 if( numRows != dstMatr->rows )
479 CV_ERROR( CV_StsOutOfRange, "Number of rows of matrices must be the same" );
483 for( dst = 0; dst < number; dst++ )
485 int src = indexes[dst];
486 if( src >=0 && src < srcSize )
488 /* Copy each elements in column */
490 for( i = 0; i < numRows; i++ )
492 cvmSet(dstMatr,i,dst,cvmGet(srcMatr,i,src));
501 /*==========================================================================================*/
502 static void icvProject4DPoints(CvMat* points4D,CvMat* projMatr, CvMat* projPoints)
505 CvMat* tmpProjPoints = 0;
507 CV_FUNCNAME( "icvProject4DPoints" );
511 if( points4D == 0 || projMatr == 0 || projPoints == 0)
513 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
516 if( !CV_IS_MAT(points4D) || !CV_IS_MAT(projMatr) || !CV_IS_MAT(projPoints) )
518 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
522 numPoints = points4D->cols;
525 CV_ERROR( CV_StsOutOfRange, "Number of points4D must be more than zero" );
528 if( numPoints != projPoints->cols )
530 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be the same");
533 if( projPoints->rows != 2 )
535 CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of projected points must be 2");
538 if( points4D->rows != 4 )
540 CV_ERROR(CV_StsUnmatchedSizes, "Number of coordinates of 4D points must be 4");
543 if( projMatr->cols != 4 || projMatr->rows != 3 )
545 CV_ERROR( CV_StsUnmatchedSizes, "Size of projection matrix must be 3x4");
549 CV_CALL( tmpProjPoints = cvCreateMat(3,numPoints,CV_64F) );
551 cvmMul(projMatr,points4D,tmpProjPoints);
555 for( i = 0; i < numPoints; i++ )
559 scale = cvmGet(tmpProjPoints,2,i);
560 x = cvmGet(tmpProjPoints,0,i);
561 y = cvmGet(tmpProjPoints,1,i);
563 if( fabs(scale) > 1e-7 )
574 cvmSet(projPoints,0,i,x);
575 cvmSet(projPoints,1,i,y);
580 cvReleaseMat(&tmpProjPoints);
584 /*==========================================================================================*/
586 static int icvCompute3ProjectMatricesNPointsStatus( CvMat** points,/* 3 arrays of points on image */
587 CvMat** projMatrs,/* array of 3 prejection matrices */
588 CvMat** statuses,/* 3 arrays of status of points */
589 double threshold,/* Threshold for good point */
590 double p,/* Probability of good result. */
594 int numProjMatrs = 0;
595 unsigned char *comStat = 0;
596 CvMat *triPoints[3] = {0,0,0};
598 CvMat *triPoints4D = 0;
600 CV_FUNCNAME( "icvCompute3ProjectMatricesNPointsStatus" );
603 /* Test for errors */
604 if( points == 0 || projMatrs == 0 || statuses == 0 || resStatus == 0 )
606 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
610 for( currImage = 0; currImage < 3; currImage++ )
612 /* Test for null pointers */
613 if( points[currImage] == 0 )
615 CV_ERROR( CV_StsNullPtr, "Some of points arrays is a NULL pointer" );
618 if( projMatrs[currImage] == 0 )
620 CV_ERROR( CV_StsNullPtr, "Some of projMatr is a NULL pointer" );
623 if( statuses[currImage] == 0 )
625 CV_ERROR( CV_StsNullPtr, "Some of status arrays is a NULL pointer" );
628 /* Test for matrices */
629 if( !CV_IS_MAT(points[currImage]) )
631 CV_ERROR( CV_StsNullPtr, "Some of points arrays is not a matrix" );
634 if( !CV_IS_MAT(projMatrs[currImage]) )
636 CV_ERROR( CV_StsNullPtr, "Some of projMatr is not a matrix" );
639 if( !CV_IS_MASK_ARR(statuses[currImage]) )
641 CV_ERROR( CV_StsNullPtr, "Some of status arrays is not a mask array" );
646 numPoints = points[0]->cols;
649 CV_ERROR( CV_StsOutOfRange, "Number points must be more than 6" );
652 for( currImage = 0; currImage < 3; currImage++ )
654 if( points[currImage]->cols != numPoints || statuses[currImage]->cols != numPoints )
656 CV_ERROR( CV_StsUnmatchedSizes, "Number of points and statuses must be the same" );
659 if( points[currImage]->rows != 2 )
661 CV_ERROR( CV_StsOutOfRange, "Number of points coordinates must be == 2" );
664 if( statuses[currImage]->rows != 1 )
666 CV_ERROR( CV_StsOutOfRange, "Each of status must be matrix 1xN" );
669 if( projMatrs[currImage]->rows != 3 || projMatrs[currImage]->cols != 4 )
671 CV_ERROR( CV_StsOutOfRange, "Each of projection matrix must be 3x4" );
676 /* Create common status for all points */
680 CV_CALL( comStat = (unsigned char*)cvAlloc(sizeof(unsigned char)*numPoints) );
682 unsigned char *stats[3];
684 stats[0] = statuses[0]->data.ptr;
685 stats[1] = statuses[1]->data.ptr;
686 stats[2] = statuses[2]->data.ptr;
690 for( i = 0; i < numPoints; i++ )
692 comStat[i] = (unsigned char)(stats[0][i] * stats[1][i] * stats[2][i]);
693 numTripl += comStat[i];
698 /* Create new arrays with points */
699 CV_CALL( triPoints[0] = cvCreateMat(2,numTripl,CV_64F) );
700 CV_CALL( triPoints[1] = cvCreateMat(2,numTripl,CV_64F) );
701 CV_CALL( triPoints[2] = cvCreateMat(2,numTripl,CV_64F) );
704 CV_CALL( triPoints4D = cvCreateMat(4,numTripl,CV_64F) );
707 /* Create status array */
708 CV_CALL( status = cvCreateMat(1,numTripl,CV_64F) );
710 /* Copy points to new arrays */
712 for( i = 0; i < numPoints; i++ )
716 for( currImage = 0; currImage < 3; currImage++ )
718 cvmSet(triPoints[currImage],0,currPnt,cvmGet(points[currImage],0,i));
719 cvmSet(triPoints[currImage],1,currPnt,cvmGet(points[currImage],1,i));
726 numProjMatrs = icvComputeProjectMatricesNPoints( triPoints[0],triPoints[1],triPoints[2],
727 projMatrs[0],projMatrs[1],projMatrs[2],
728 threshold,/* Threshold for good point */
729 p,/* Probability of good result. */
733 /* Get computed status and set to result */
736 for( i = 0; i < numPoints; i++ )
740 if( cvmGet(status,0,currPnt) > 0 )
742 resStatus->data.ptr[i] = 1;
750 /* Copy copmuted 4D points */
753 for( i = 0; i < numPoints; i++ )
757 if( cvmGet(status,0,currPnt) > 0 )
759 cvmSet( points4D, 0, i, cvmGet( triPoints4D , 0, currPnt) );
760 cvmSet( points4D, 1, i, cvmGet( triPoints4D , 1, currPnt) );
761 cvmSet( points4D, 2, i, cvmGet( triPoints4D , 2, currPnt) );
762 cvmSet( points4D, 3, i, cvmGet( triPoints4D , 3, currPnt) );
772 /* Free allocated memory */
773 cvReleaseMat(&status);
775 cvReleaseMat(&status);
777 cvReleaseMat(&triPoints[0]);
778 cvReleaseMat(&triPoints[1]);
779 cvReleaseMat(&triPoints[2]);
780 cvReleaseMat(&triPoints4D);
787 /*==========================================================================================*/
788 int icvComputeProjectMatricesNPoints( CvMat* points1,CvMat* points2,CvMat* points3,
789 CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
790 double threshold,/* Threshold for good point */
791 double p,/* Probability of good result. */
795 /* Returns status for each point, Good or bad */
797 /* Compute projection matrices using N points */
802 int numProjMatrs = 0;
804 CvMat* tmpProjPoints[3]={0,0,0};
805 CvMat* recPoints4D = 0;
806 CvMat *reconPoints4D = 0;
809 CV_FUNCNAME( "icvComputeProjectMatricesNPoints" );
817 /* Test for errors */
818 if( points1 == 0 || points2 == 0 || points3 == 0 ||
819 projMatr1 == 0 || projMatr2 == 0 || projMatr3 == 0 ||
822 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
825 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2) || !CV_IS_MAT(points3) ||
826 !CV_IS_MAT(projMatr1) || !CV_IS_MAT(projMatr2) || !CV_IS_MAT(projMatr3) ||
829 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
833 numPoints = points1->cols;
837 CV_ERROR( CV_StsOutOfRange, "Number points must be more than 6" );
840 if( numPoints != points2->cols || numPoints != points3->cols )
842 CV_ERROR( CV_StsUnmatchedSizes, "number of points must be the same" );
845 if( p < 0 || p > 1.0 )
847 CV_ERROR( CV_StsOutOfRange, "Probability must be >=0 and <=1" );
852 CV_ERROR( CV_StsOutOfRange, "Threshold for good points must be at least >= 0" );
857 projMatrs[0] = projMatr1;
858 projMatrs[1] = projMatr2;
859 projMatrs[2] = projMatr3;
861 for(int i = 0; i < 3; i++ )
863 if( projMatrs[i]->cols != 4 || projMatrs[i]->rows != 3 )
865 CV_ERROR( CV_StsUnmatchedSizes, "Size of projection matrices must be 3x4" );
869 for(int i = 0; i < 3; i++ )
871 if( points[i]->rows != 2)
873 CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of points must be 2" );
877 /* use RANSAC algorithm to compute projection matrices */
879 CV_CALL( recPoints4D = cvCreateMat(4,numPoints,CV_64F) );
880 CV_CALL( tmpProjPoints[0] = cvCreateMat(2,numPoints,CV_64F) );
881 CV_CALL( tmpProjPoints[1] = cvCreateMat(2,numPoints,CV_64F) );
882 CV_CALL( tmpProjPoints[2] = cvCreateMat(2,numPoints,CV_64F) );
884 CV_CALL( flags = (char*)cvAlloc(sizeof(char)*numPoints) );
885 CV_CALL( bestFlags = (char*)cvAlloc(sizeof(char)*numPoints) );
888 int NumSamples = 500;/* just init number of samples */
889 int wasCount = 0; /* count of choosing samples */
890 int maxGoodPoints = 0;
891 int numGoodPoints = 0;
893 double bestProjMatrs_dat[36];
894 CvMat bestProjMatrs[3];
895 bestProjMatrs[0] = cvMat(3,4,CV_64F,bestProjMatrs_dat);
896 bestProjMatrs[1] = cvMat(3,4,CV_64F,bestProjMatrs_dat+12);
897 bestProjMatrs[2] = cvMat(3,4,CV_64F,bestProjMatrs_dat+24);
899 double tmpProjMatr_dat[36*3];
900 CvMat tmpProjMatr[3];
901 tmpProjMatr[0] = cvMat(9,4,CV_64F,tmpProjMatr_dat);
902 tmpProjMatr[1] = cvMat(9,4,CV_64F,tmpProjMatr_dat+36);
903 tmpProjMatr[2] = cvMat(9,4,CV_64F,tmpProjMatr_dat+72);
907 while( wasCount < NumSamples )
911 icvGetRandNumbers(numPoints,6,randNumbs);
913 /* random numbers of points was generated */
916 double selPoints_dat[2*6*3];
918 selPoints[0] = cvMat(2,6,CV_64F,selPoints_dat);
919 selPoints[1] = cvMat(2,6,CV_64F,selPoints_dat+12);
920 selPoints[2] = cvMat(2,6,CV_64F,selPoints_dat+24);
922 /* Copy 6 point for random indexes */
923 icvSelectColsByNumbers( points[0], &selPoints[0], randNumbs,6);
924 icvSelectColsByNumbers( points[1], &selPoints[1], randNumbs,6);
925 icvSelectColsByNumbers( points[2], &selPoints[2], randNumbs,6);
927 /* Compute projection matrices for this points */
928 int numProj = icvComputeProjectMatrices6Points( &selPoints[0],&selPoints[1],&selPoints[2],
929 &tmpProjMatr[0],&tmpProjMatr[1],&tmpProjMatr[2]);
931 /* Compute number of good points for each matrix */
933 for( int currProj = 0; currProj < numProj; currProj++ )
935 cvGetSubArr(&tmpProjMatr[0],&proj6[0],cvRect(0,currProj*3,4,3));
936 cvGetSubArr(&tmpProjMatr[1],&proj6[1],cvRect(0,currProj*3,4,3));
937 cvGetSubArr(&tmpProjMatr[2],&proj6[2],cvRect(0,currProj*3,4,3));
939 /* Reconstruct points for projection matrices */
940 icvReconstructPointsFor3View( &proj6[0],&proj6[1],&proj6[2],
941 points[0], points[1], points[2],
944 /* Project points to images using projection matrices */
945 icvProject4DPoints(recPoints4D,&proj6[0],tmpProjPoints[0]);
946 icvProject4DPoints(recPoints4D,&proj6[1],tmpProjPoints[1]);
947 icvProject4DPoints(recPoints4D,&proj6[2],tmpProjPoints[2]);
949 /* Compute distances and number of good points (inliers) */
952 for(int i = 0; i < numPoints; i++ )
956 /* Choose max distance for each of three points */
957 for( currImage = 0; currImage < 3; currImage++ )
960 x1 = cvmGet(tmpProjPoints[currImage],0,i);
961 y1 = cvmGet(tmpProjPoints[currImage],1,i);
962 x2 = cvmGet(points[currImage],0,i);
963 y2 = cvmGet(points[currImage],1,i);
969 double newDist = dx*dx+dy*dy;
975 dist += sqrt(dx*dx+dy*dy)/3.0;
979 flags[i] = (char)(dist > threshold ? 0 : 1);
980 numGoodPoints += flags[i];
985 if( numGoodPoints > maxGoodPoints )
986 {/* Copy current projection matrices as best */
988 cvCopy(&proj6[0],&bestProjMatrs[0]);
989 cvCopy(&proj6[1],&bestProjMatrs[1]);
990 cvCopy(&proj6[2],&bestProjMatrs[2]);
992 maxGoodPoints = numGoodPoints;
993 /* copy best flags */
994 memcpy(bestFlags,flags,sizeof(flags[0])*numPoints);
996 /* Adaptive number of samples to count*/
997 double ep = 1 - (double)numGoodPoints / (double)numPoints;
1000 ep = 0.5;/* if there is not good points set ration of outliers to 50% */
1003 double newNumSamples = (log(1-p) / log(1-pow(1-ep,6)));
1004 if( newNumSamples < double(NumSamples) )
1006 NumSamples = cvRound(newNumSamples);
1015 sprintf(str,"Initial numPoints = %d\nmaxGoodPoints=%d\nRANSAC made %d steps",
1019 MessageBox(0,str,"Info",MB_OK|MB_TASKMODAL);
1022 /* we may have best 6-point projection matrices. */
1023 /* and best points */
1024 /* use these points to improve matrices */
1026 if( maxGoodPoints < 6 )
1028 /* matrix not found */
1033 /* We may Improove matrices using ---- method */
1034 /* We may try to use Levenberg-Marquardt optimization */
1036 int finalGoodPoints = 0;
1037 char *goodFlags = 0;
1038 goodFlags = (char*)cvAlloc(numPoints*sizeof(char));
1044 /* Version without using status for Levenberg-Marquardt minimization */
1047 optStatus = cvCreateMat(1,numPoints,CV_64F);
1049 for(int i=0;i<numPoints;i++ )
1051 cvmSet(optStatus,0,i,(double)bestFlags[i]);
1052 testNumber += bestFlags[i];
1056 sprintf(str2,"test good num=%d\nmaxGoodPoints=%d",testNumber,maxGoodPoints);
1057 MessageBox(0,str2,"Info",MB_OK|MB_TASKMODAL);
1060 gPresPoints = cvCreateMat(1,maxGoodPoints,CV_64F);
1061 for(int i = 0; i < maxGoodPoints; i++)
1063 cvmSet(gPresPoints,0,i,1.0);
1066 /* Create array of points pres */
1067 CvMat *pointsPres[3];
1068 pointsPres[0] = gPresPoints;
1069 pointsPres[1] = gPresPoints;
1070 pointsPres[2] = gPresPoints;
1072 /* Create just good points 2D */
1074 icvCreateGoodPoints(points[0],&gPoints[0],optStatus);
1075 icvCreateGoodPoints(points[1],&gPoints[1],optStatus);
1076 icvCreateGoodPoints(points[2],&gPoints[2],optStatus);
1078 /* Create 4D points array for good points */
1080 resPoints4D = cvCreateMat(4,maxGoodPoints,CV_64F);
1084 projMs[0] = &bestProjMatrs[0];
1085 projMs[1] = &bestProjMatrs[1];
1086 projMs[2] = &bestProjMatrs[2];
1089 CvMat resProjMatrs[3];
1090 double resProjMatrs_dat[36];
1091 resProjMatrs[0] = cvMat(3,4,CV_64F,resProjMatrs_dat);
1092 resProjMatrs[1] = cvMat(3,4,CV_64F,resProjMatrs_dat+12);
1093 resProjMatrs[2] = cvMat(3,4,CV_64F,resProjMatrs_dat+24);
1096 resMatrs[0] = &resProjMatrs[0];
1097 resMatrs[1] = &resProjMatrs[1];
1098 resMatrs[2] = &resProjMatrs[2];
1100 cvOptimizeLevenbergMarquardtBundle( projMs,//projMs,
1101 gPoints,//points,//points2D,
1102 pointsPres,//pointsPres,
1104 resMatrs,//resProjMatrs,
1105 resPoints4D,//resPoints4D,
1108 /* We found optimized projection matrices */
1110 CvMat *reconPoints4D;
1111 reconPoints4D = cvCreateMat(4,numPoints,CV_64F);
1113 /* Reconstruct all points using found projection matrices */
1114 icvReconstructPointsFor3View( &resProjMatrs[0],&resProjMatrs[1],&resProjMatrs[2],
1115 points[0], points[1], points[2],
1118 /* Project points to images using projection matrices */
1119 icvProject4DPoints(reconPoints4D,&resProjMatrs[0],tmpProjPoints[0]);
1120 icvProject4DPoints(reconPoints4D,&resProjMatrs[1],tmpProjPoints[1]);
1121 icvProject4DPoints(reconPoints4D,&resProjMatrs[2],tmpProjPoints[2]);
1124 /* Compute error for each point and select good */
1127 finalGoodPoints = 0;
1128 for(int i = 0; i < numPoints; i++ )
1131 /* Choose max distance for each of three points */
1132 for( currImage = 0; currImage < 3; currImage++ )
1135 x1 = cvmGet(tmpProjPoints[currImage],0,i);
1136 y1 = cvmGet(tmpProjPoints[currImage],1,i);
1137 x2 = cvmGet(points[currImage],0,i);
1138 y2 = cvmGet(points[currImage],1,i);
1144 double newDist = dx*dx+dy*dy;
1145 if( newDist > dist )
1151 goodFlags[i] = (char)(dist > threshold ? 0 : 1);
1152 finalGoodPoints += goodFlags[i];
1156 sprintf(str,"Was num = %d\nNew num=%d",maxGoodPoints,finalGoodPoints);
1157 MessageBox(0,str,"Info",MB_OK|MB_TASKMODAL);
1158 if( finalGoodPoints > maxGoodPoints )
1160 /* Copy new version of projection matrices */
1161 cvCopy(&resProjMatrs[0],&bestProjMatrs[0]);
1162 cvCopy(&resProjMatrs[1],&bestProjMatrs[1]);
1163 cvCopy(&resProjMatrs[2],&bestProjMatrs[2]);
1164 memcpy(bestFlags,goodFlags,numPoints*sizeof(char));
1165 maxGoodPoints = finalGoodPoints;
1168 cvReleaseMat(&optStatus);
1169 cvReleaseMat(&resPoints4D);
1171 /* Version with using status for Levenberd-Marquardt minimization */
1175 optStatus = cvCreateMat(1,numPoints,CV_64F);
1176 for(int i=0;i<numPoints;i++ )
1178 cvmSet(optStatus,0,i,(double)bestFlags[i]);
1181 CvMat *pointsPres[3];
1182 pointsPres[0] = optStatus;
1183 pointsPres[1] = optStatus;
1184 pointsPres[2] = optStatus;
1186 /* Create 4D points array for good points */
1188 resPoints4D = cvCreateMat(4,numPoints,CV_64F);
1192 projMs[0] = &bestProjMatrs[0];
1193 projMs[1] = &bestProjMatrs[1];
1194 projMs[2] = &bestProjMatrs[2];
1196 CvMat resProjMatrs[3];
1197 double resProjMatrs_dat[36];
1198 resProjMatrs[0] = cvMat(3,4,CV_64F,resProjMatrs_dat);
1199 resProjMatrs[1] = cvMat(3,4,CV_64F,resProjMatrs_dat+12);
1200 resProjMatrs[2] = cvMat(3,4,CV_64F,resProjMatrs_dat+24);
1203 resMatrs[0] = &resProjMatrs[0];
1204 resMatrs[1] = &resProjMatrs[1];
1205 resMatrs[2] = &resProjMatrs[2];
1207 cvOptimizeLevenbergMarquardtBundle( projMs,//projMs,
1209 pointsPres,//pointsPres,
1211 resMatrs,//resProjMatrs,
1212 resPoints4D,//resPoints4D,
1215 /* We found optimized projection matrices */
1217 reconPoints4D = cvCreateMat(4,numPoints,CV_64F);
1219 /* Reconstruct all points using found projection matrices */
1220 icvReconstructPointsFor3View( &resProjMatrs[0],&resProjMatrs[1],&resProjMatrs[2],
1221 points[0], points[1], points[2],
1224 /* Project points to images using projection matrices */
1225 icvProject4DPoints(reconPoints4D,&resProjMatrs[0],tmpProjPoints[0]);
1226 icvProject4DPoints(reconPoints4D,&resProjMatrs[1],tmpProjPoints[1]);
1227 icvProject4DPoints(reconPoints4D,&resProjMatrs[2],tmpProjPoints[2]);
1230 /* Compute error for each point and select good */
1233 finalGoodPoints = 0;
1234 for(int i = 0; i < numPoints; i++ )
1237 /* Choose max distance for each of three points */
1238 for( currImage = 0; currImage < 3; currImage++ )
1241 x1 = cvmGet(tmpProjPoints[currImage],0,i);
1242 y1 = cvmGet(tmpProjPoints[currImage],1,i);
1243 x2 = cvmGet(points[currImage],0,i);
1244 y2 = cvmGet(points[currImage],1,i);
1250 double newDist = dx*dx+dy*dy;
1251 if( newDist > dist )
1257 goodFlags[i] = (char)(dist > threshold ? 0 : 1);
1258 finalGoodPoints += goodFlags[i];
1262 sprintf(str,"Was num = %d\nNew num=%d",maxGoodPoints,finalGoodPoints);
1263 MessageBox(0,str,"Info",MB_OK|MB_TASKMODAL);*/
1266 if( finalGoodPoints > maxGoodPoints )
1268 /* Copy new version of projection matrices */
1269 cvCopy(&resProjMatrs[0],&bestProjMatrs[0]);
1270 cvCopy(&resProjMatrs[1],&bestProjMatrs[1]);
1271 cvCopy(&resProjMatrs[2],&bestProjMatrs[2]);
1272 memcpy(bestFlags,goodFlags,numPoints*sizeof(char));
1273 maxGoodPoints = finalGoodPoints;
1277 cvReleaseMat(&optStatus);
1278 cvReleaseMat(&resPoints4D);
1282 } while ( needRepeat );
1284 cvFree( &goodFlags);
1291 /* Copy projection matrices */
1292 cvConvert(&bestProjMatrs[0],projMatr1);
1293 cvConvert(&bestProjMatrs[1],projMatr2);
1294 cvConvert(&bestProjMatrs[2],projMatr3);
1298 /* copy status for each points if need */
1299 for( int i = 0; i < numPoints; i++)
1301 cvmSet(status,0,i,(double)bestFlags[i]);
1308 {/* Fill reconstructed points */
1311 icvReconstructPointsFor3View( projMatr1,projMatr2,projMatr3,
1312 points[0], points[1], points[2],
1321 cvFree( &bestFlags);
1323 cvReleaseMat(&recPoints4D);
1324 cvReleaseMat(&tmpProjPoints[0]);
1325 cvReleaseMat(&tmpProjPoints[1]);
1326 cvReleaseMat(&tmpProjPoints[2]);
1328 return numProjMatrs;
1331 /*==========================================================================================*/
1333 void icvFindBaseTransform(CvMat* points,CvMat* resultT)
1336 CV_FUNCNAME( "icvFindBaseTransform" );
1339 if( points == 0 || resultT == 0 )
1341 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
1344 if( !CV_IS_MAT(points) || !CV_IS_MAT(resultT) )
1346 CV_ERROR( CV_StsUnsupportedFormat, "points and resultT must be a matrices" );
1349 if( points->rows != 2 || points->cols != 4 )
1351 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be 4. And they must have 2 coordinates" );
1354 if( resultT->rows != 3 || resultT->cols != 3 )
1356 CV_ERROR( CV_StsUnmatchedSizes, "size of matrix resultT must be 3x3" );
1359 /* Function gets four points and compute transformation to e1=(100) e2=(010) e3=(001) e4=(111) */
1361 /* !!! test each three points not collinear. Need to test */
1363 /* Create matrices */
1366 double matrA_dat[3*3];
1367 double vectB_dat[3];
1368 matrA = cvMat(3,3,CV_64F,matrA_dat);
1369 vectB = cvMat(3,1,CV_64F,vectB_dat);
1373 for( i = 0; i < 3; i++ )
1375 cvmSet(&matrA,0,i,cvmGet(points,0,i));
1376 cvmSet(&matrA,1,i,cvmGet(points,1,i));
1377 cvmSet(&matrA,2,i,1);
1381 cvmSet(&vectB,0,0,cvmGet(points,0,3));
1382 cvmSet(&vectB,1,0,cvmGet(points,1,3));
1383 cvmSet(&vectB,2,0,1);
1387 double scale_dat[3];
1388 scale = cvMat(3,1,CV_64F,scale_dat);
1390 cvSolve(&matrA,&vectB,&scale,CV_SVD);
1392 /* multiply by scale */
1394 for( j = 0; j < 3; j++ )
1396 double sc = scale_dat[j];
1397 for( i = 0; i < 3; i++ )
1399 matrA_dat[i*3+j] *= sc;
1403 /* Convert inverse matrix */
1405 double tmpRes_dat[9];
1406 tmpRes = cvMat(3,3,CV_64F,tmpRes_dat);
1407 cvInvert(&matrA,&tmpRes);
1409 cvConvert(&tmpRes,resultT);
1417 /*==========================================================================================*/
1418 void GetGeneratorReduceFundSolution(CvMat* points1,CvMat* points2,CvMat* fundReduceCoef1,CvMat* fundReduceCoef2)
1421 CV_FUNCNAME( "GetGeneratorReduceFundSolution" );
1424 /* Test input data for errors */
1426 if( points1 == 0 || points2 == 0 || fundReduceCoef1 == 0 || fundReduceCoef2 == 0)
1428 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
1431 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2) || !CV_IS_MAT(fundReduceCoef1) || !CV_IS_MAT(fundReduceCoef2) )
1433 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
1438 if( points1->rows != 3 || points1->cols != 3 )
1440 CV_ERROR( CV_StsUnmatchedSizes, "Number of points1 must be 3 and and have 3 coordinates" );
1443 if( points2->rows != 3 || points2->cols != 3 )
1445 CV_ERROR( CV_StsUnmatchedSizes, "Number of points2 must be 3 and and have 3 coordinates" );
1448 if( fundReduceCoef1->rows != 1 || fundReduceCoef1->cols != 5 )
1450 CV_ERROR( CV_StsUnmatchedSizes, "Size of fundReduceCoef1 must be 1x5" );
1453 if( fundReduceCoef2->rows != 1 || fundReduceCoef2->cols != 5 )
1455 CV_ERROR( CV_StsUnmatchedSizes, "Size of fundReduceCoef2 must be 1x5" );
1458 /* Using 3 corr. points compute reduce */
1462 double matrA_dat[3*5];
1463 matrA = cvMat(3,5,CV_64F,matrA_dat);
1465 for( i = 0; i < 3; i++ )
1467 double x1,y1,w1,x2,y2,w2;
1468 x1 = cvmGet(points1,0,i);
1469 y1 = cvmGet(points1,1,i);
1470 w1 = cvmGet(points1,2,i);
1472 x2 = cvmGet(points2,0,i);
1473 y2 = cvmGet(points2,1,i);
1474 w2 = cvmGet(points2,2,i);
1476 cvmSet(&matrA,i,0,y1*x2-y1*w2);
1477 cvmSet(&matrA,i,1,w1*x2-y1*w2);
1478 cvmSet(&matrA,i,2,x1*y2-y1*w2);
1479 cvmSet(&matrA,i,3,w1*y2-y1*w2);
1480 cvmSet(&matrA,i,4,x1*w2-y1*w2);
1483 /* solve system using svd */
1488 double matrU_dat[3*3];
1489 double matrW_dat[3*5];
1490 double matrV_dat[5*5];
1492 matrU = cvMat(3,3,CV_64F,matrU_dat);
1493 matrW = cvMat(3,5,CV_64F,matrW_dat);
1494 matrV = cvMat(5,5,CV_64F,matrV_dat);
1496 /* From svd we need just two last vectors of V or two last row V' */
1497 /* We get transposed matrices U and V */
1499 cvSVD(&matrA,&matrW,0,&matrV,CV_SVD_V_T);
1501 /* copy results to fundamental matrices */
1504 cvmSet(fundReduceCoef1,0,i,cvmGet(&matrV,3,i));
1505 cvmSet(fundReduceCoef2,0,i,cvmGet(&matrV,4,i));
1513 /*==========================================================================================*/
1515 int GetGoodReduceFundamMatrFromTwo(CvMat* fundReduceCoef1,CvMat* fundReduceCoef2,CvMat* resFundReduceCoef)
1519 CV_FUNCNAME( "GetGoodReduceFundamMatrFromTwo" );
1522 if( fundReduceCoef1 == 0 || fundReduceCoef2 == 0 || resFundReduceCoef == 0 )
1524 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
1527 if( !CV_IS_MAT(fundReduceCoef1) || !CV_IS_MAT(fundReduceCoef2) || !CV_IS_MAT(resFundReduceCoef) )
1529 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
1532 /* using two fundamental matrix comute matrices for det(F)=0 */
1533 /* May compute 1 or 3 matrices. Returns number of solutions */
1534 /* Here we will use case F=a*F1+(1-a)*F2 instead of F=m*F1+l*F2 */
1536 /* Test for errors */
1537 if( fundReduceCoef1->rows != 1 || fundReduceCoef1->cols != 5 )
1539 CV_ERROR( CV_StsUnmatchedSizes, "Size of fundReduceCoef1 must be 1x5" );
1542 if( fundReduceCoef2->rows != 1 || fundReduceCoef2->cols != 5 )
1544 CV_ERROR( CV_StsUnmatchedSizes, "Size of fundReduceCoef2 must be 1x5" );
1547 if( (resFundReduceCoef->rows != 1 && resFundReduceCoef->rows != 3) || resFundReduceCoef->cols != 5 )
1549 CV_ERROR( CV_StsUnmatchedSizes, "Size of resFundReduceCoef must be 1x5" );
1552 double p1,q1,r1,s1,t1;
1553 double p2,q2,r2,s2,t2;
1554 p1 = cvmGet(fundReduceCoef1,0,0);
1555 q1 = cvmGet(fundReduceCoef1,0,1);
1556 r1 = cvmGet(fundReduceCoef1,0,2);
1557 s1 = cvmGet(fundReduceCoef1,0,3);
1558 t1 = cvmGet(fundReduceCoef1,0,4);
1560 p2 = cvmGet(fundReduceCoef2,0,0);
1561 q2 = cvmGet(fundReduceCoef2,0,1);
1562 r2 = cvmGet(fundReduceCoef2,0,2);
1563 s2 = cvmGet(fundReduceCoef2,0,3);
1564 t2 = cvmGet(fundReduceCoef2,0,4);
1566 /* solve equation */
1569 double result_dat[2*3];
1570 double coeffs_dat[4];
1571 result = cvMat(2,3,CV_64F,result_dat);
1572 coeffs = cvMat(1,4,CV_64F,coeffs_dat);
1574 coeffs_dat[0] = ((r1-r2)*(-p1-q1-r1-s1-t1+p2+q2+r2+s2+t2)*(q1-q2)+(p1-p2)*(s1-s2)*(t1-t2));/* *a^3 */
1575 coeffs_dat[1] = ((r2*(-p1-q1-r1-s1-t1+p2+q2+r2+s2+t2)+(r1-r2)*(-p2-q2-r2-s2-t2))*(q1-q2)+(r1-r2)*(-p1-q1-r1-s1-t1+p2+q2+r2+s2+t2)*q2+(p2*(s1-s2)+(p1-p2)*s2)*(t1-t2)+(p1-p2)*(s1-s2)*t2);/* *a^2 */
1576 coeffs_dat[2] = (r2*(-p2-q2-r2-s2-t2)*(q1-q2)+(r2*(-p1-q1-r1-s1-t1+p2+q2+r2+s2+t2)+(r1-r2)*(-p2-q2-r2-s2-t2))*q2+p2*s2*(t1-t2)+(p2*(s1-s2)+(p1-p2)*s2)*t2);/* *a */
1577 coeffs_dat[3] = r2*(-p2-q2-r2-s2-t2)*q2+p2*s2*t2;/* 1 */
1580 num = cvSolveCubic(&coeffs,&result);
1583 /* test number of solutions and test for real solutions */
1585 for( i = 0; i < num; i++ )
1587 if( fabs(cvmGet(&result,1,i)) < 1e-8 )
1589 double alpha = cvmGet(&result,0,i);
1591 for( j = 0; j < 5; j++ )
1593 cvmSet(resFundReduceCoef,numRoots,j,
1594 alpha * cvmGet(fundReduceCoef1,0,j) + (1-alpha) * cvmGet(fundReduceCoef2,0,j) );
1604 /*==========================================================================================*/
1606 void GetProjMatrFromReducedFundamental(CvMat* fundReduceCoefs,CvMat* projMatrCoefs)
1608 CV_FUNCNAME( "GetProjMatrFromReducedFundamental" );
1611 /* Test for errors */
1612 if( fundReduceCoefs == 0 || projMatrCoefs == 0 )
1614 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
1617 if( !CV_IS_MAT(fundReduceCoefs) || !CV_IS_MAT(projMatrCoefs) )
1619 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
1623 if( fundReduceCoefs->rows != 1 || fundReduceCoefs->cols != 5 )
1625 CV_ERROR( CV_StsUnmatchedSizes, "Size of fundReduceCoefs must be 1x5" );
1628 if( projMatrCoefs->rows != 1 || projMatrCoefs->cols != 4 )
1630 CV_ERROR( CV_StsUnmatchedSizes, "Size of projMatrCoefs must be 1x4" );
1633 /* Computes project matrix from given reduced matrix */
1634 /* we have p,q,r,s,t and need get a,b,c,d */
1635 /* Fill matrix to compute ratio a:b:c as A:B:C */
1638 double matrA_dat[3*3];
1639 matrA = cvMat(3,3,CV_64F,matrA_dat);
1642 p = cvmGet(fundReduceCoefs,0,0);
1643 q = cvmGet(fundReduceCoefs,0,1);
1644 r = cvmGet(fundReduceCoefs,0,2);
1645 s = cvmGet(fundReduceCoefs,0,3);
1646 t = cvmGet(fundReduceCoefs,0,4);
1658 matrA_dat[8] = -(p+q+r+s+t);
1663 double matrW_dat[3*3];
1664 double matrV_dat[3*3];
1666 matrW = cvMat(3,3,CV_64F,matrW_dat);
1667 matrV = cvMat(3,3,CV_64F,matrV_dat);
1669 /* From svd we need just last vector of V or last row V' */
1670 /* We get transposed matrices U and V */
1672 cvSVD(&matrA,&matrW,0,&matrV,CV_SVD_V_T);
1679 /* Get second coeffs */
1686 matrA_dat[5] = -(p+q+r+s+t);
1692 cvSVD(&matrA,&matrW,0,&matrV,CV_SVD_V_T);
1702 double matrK_dat[36];
1703 matrK = cvMat(6,6,CV_64F,matrK_dat);
1718 matrK_dat[0*6+4] = -A1;
1719 matrK_dat[1*6+4] = -B1;
1720 matrK_dat[2*6+4] = -C1;
1722 matrK_dat[3*6+5] = -A2;
1723 matrK_dat[4*6+5] = -B2;
1724 matrK_dat[5*6+5] = -C2;
1729 double matrW_dat1[36];
1730 double matrV_dat1[36];
1732 matrW1 = cvMat(6,6,CV_64F,matrW_dat1);
1733 matrV1 = cvMat(6,6,CV_64F,matrV_dat1);
1735 /* From svd we need just last vector of V or last row V' */
1736 /* We get transposed matrices U and V */
1738 cvSVD(&matrK,&matrW1,0,&matrV1,CV_SVD_V_T);
1740 a = matrV_dat1[6*5+0];
1741 b = matrV_dat1[6*5+1];
1742 c = matrV_dat1[6*5+2];
1743 d = matrV_dat1[6*5+3];
1744 /* we don't need last two coefficients. Because it just a k1,k2 */
1746 cvmSet(projMatrCoefs,0,0,a);
1747 cvmSet(projMatrCoefs,0,1,b);
1748 cvmSet(projMatrCoefs,0,2,c);
1749 cvmSet(projMatrCoefs,0,3,d);
1757 /*==========================================================================================*/
1759 void icvComputeProjectMatrix(CvMat* objPoints,CvMat* projPoints,CvMat* projMatr)
1760 {/* Using SVD method */
1762 /* Reconstruct points using object points and projected points */
1763 /* Number of points must be >=6 */
1768 CvMat* workProjPoints = 0;
1769 CvMat* tmpProjPoints = 0;
1771 CV_FUNCNAME( "icvComputeProjectMatrix" );
1774 /* Test for errors */
1775 if( objPoints == 0 || projPoints == 0 || projMatr == 0)
1777 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
1780 if( !CV_IS_MAT(objPoints) || !CV_IS_MAT(projPoints) || !CV_IS_MAT(projMatr) )
1782 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
1785 if( projMatr->rows != 3 || projMatr->cols != 4 )
1787 CV_ERROR( CV_StsUnmatchedSizes, "Size of projMatr must be 3x4" );
1791 numPoints = projPoints->cols;
1794 CV_ERROR( CV_StsOutOfRange, "Number of points must be at least 6" );
1797 if( numPoints != objPoints->cols )
1799 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be same" );
1802 if( objPoints->rows != 4 )
1804 CV_ERROR( CV_StsUnmatchedSizes, "Object points must have 4 coordinates" );
1807 if( projPoints->rows != 3 && projPoints->rows != 2 )
1809 CV_ERROR( CV_StsUnmatchedSizes, "Projected points must have 2 or 3 coordinates" );
1812 /* Create and fill matrix A */
1813 CV_CALL( matrA = cvCreateMat(numPoints*3, 12, CV_64F) );
1814 CV_CALL( matrW = cvCreateMat(numPoints*3, 12, CV_64F) );
1816 if( projPoints->rows == 2 )
1818 CV_CALL( tmpProjPoints = cvCreateMat(3,numPoints,CV_64F) );
1819 cvMake3DPoints(projPoints,tmpProjPoints);
1820 workProjPoints = tmpProjPoints;
1824 workProjPoints = projPoints;
1827 double matrV_dat[144];
1828 matrV = cvMat(12,12,CV_64F,matrV_dat);
1832 dat = (char*)(matrA->data.db);
1836 file = fopen("d:\\test\\recProjMatr.txt","w");
1839 for( i = 0;i < numPoints; i++ )
1843 double* matrDat = (double*)dat;
1845 x = cvmGet(workProjPoints,0,i);
1846 y = cvmGet(workProjPoints,1,i);
1847 w = cvmGet(workProjPoints,2,i);
1850 X = cvmGet(objPoints,0,i);
1851 Y = cvmGet(objPoints,1,i);
1852 Z = cvmGet(objPoints,2,i);
1853 W = cvmGet(objPoints,3,i);
1856 fprintf(file,"%d (%lf %lf %lf %lf) - (%lf %lf %lf)\n",i,X,Y,Z,W,x,y,w );
1905 dat += (matrA->step)*3;
1912 /* Solve this system */
1914 /* From svd we need just last vector of V or last row V' */
1915 /* We get transposed matrix V */
1917 cvSVD(matrA,matrW,0,&matrV,CV_SVD_V_T);
1919 /* projected matrix was computed */
1920 for( i = 0; i < 12; i++ )
1922 cvmSet(projMatr,i/4,i%4,cvmGet(&matrV,11,i));
1925 cvReleaseMat(&matrA);
1926 cvReleaseMat(&matrW);
1927 cvReleaseMat(&tmpProjPoints);
1932 /*==========================================================================================*/
1933 /* May be useless function */
1934 void icvComputeTransform4D(CvMat* points1,CvMat* points2,CvMat* transMatr)
1939 double matrV_dat[256];
1940 CvMat matrV = cvMat(16,16,CV_64F,matrV_dat);
1942 CV_FUNCNAME( "icvComputeTransform4D" );
1945 if( points1 == 0 || points2 == 0 || transMatr == 0)
1947 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
1950 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2) || !CV_IS_MAT(transMatr) )
1952 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
1955 /* Computes transformation matrix (4x4) for points1 -> points2 */
1958 /* Test for errors */
1960 numPoints = points1->cols;
1962 /* we must have at least 5 points */
1965 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be at least 5" );
1968 if( numPoints != points2->cols )
1970 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be the same" );
1973 if( transMatr->rows != 4 || transMatr->cols != 4 )
1975 CV_ERROR( CV_StsUnmatchedSizes, "Size of transMatr must be 4x4" );
1978 if( points1->rows != 4 || points2->rows != 4 )
1980 CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of points must be 4" );
1984 CV_CALL( matrA = cvCreateMat(6*numPoints,16,CV_64F) );
1985 CV_CALL( matrW = cvCreateMat(6*numPoints,16,CV_64F) );
1991 for( i = 0; i < numPoints; i++ )/* For each point */
1996 P[0] = cvmGet(points1,0,i);
1997 P[1] = cvmGet(points1,1,i);
1998 P[2] = cvmGet(points1,2,i);
1999 P[3] = cvmGet(points1,3,i);
2001 X1 = cvmGet(points2,0,i);
2002 Y1 = cvmGet(points2,1,i);
2003 Z1 = cvmGet(points2,2,i);
2004 W1 = cvmGet(points2,3,i);
2007 for( int j = 0; j < 4; j++ )/* For each coordinate */
2016 cvmSet(matrA,6*i+0,4*0+j,y);
2017 cvmSet(matrA,6*i+0,4*1+j,-x);
2019 cvmSet(matrA,6*i+1,4*0+j,z);
2020 cvmSet(matrA,6*i+1,4*2+j,-x);
2022 cvmSet(matrA,6*i+2,4*0+j,w);
2023 cvmSet(matrA,6*i+2,4*3+j,-x);
2025 cvmSet(matrA,6*i+3,4*1+j,-z);
2026 cvmSet(matrA,6*i+3,4*2+j,y);
2028 cvmSet(matrA,6*i+4,4*1+j,-w);
2029 cvmSet(matrA,6*i+4,4*3+j,y);
2031 cvmSet(matrA,6*i+5,4*2+j,-w);
2032 cvmSet(matrA,6*i+5,4*3+j,z);
2036 /* From svd we need just two last vectors of V or two last row V' */
2037 /* We get transposed matrices U and V */
2039 cvSVD(matrA,matrW,0,&matrV,CV_SVD_V_T);
2041 /* Copy result to result matrix */
2042 for( i = 0; i < 16; i++ )
2044 cvmSet(transMatr,i/4,i%4,cvmGet(&matrV,15,i));
2047 cvReleaseMat(&matrA);
2048 cvReleaseMat(&matrW);
2054 /*==========================================================================================*/
2056 void icvReconstructPointsFor3View( CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
2057 CvMat* projPoints1,CvMat* projPoints2,CvMat* projPoints3,
2060 CV_FUNCNAME( "icvReconstructPointsFor3View" );
2063 if( projMatr1 == 0 || projMatr2 == 0 || projMatr3 == 0 ||
2064 projPoints1 == 0 || projPoints2 == 0 || projPoints3 == 0 ||
2067 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
2070 if( !CV_IS_MAT(projMatr1) || !CV_IS_MAT(projMatr2) || !CV_IS_MAT(projMatr3) ||
2071 !CV_IS_MAT(projPoints1) || !CV_IS_MAT(projPoints2) || !CV_IS_MAT(projPoints3) ||
2072 !CV_IS_MAT(points4D) )
2074 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
2078 numPoints = projPoints1->cols;
2082 CV_ERROR( CV_StsOutOfRange, "Number of points must be more than zero" );
2085 if( projPoints2->cols != numPoints || projPoints3->cols != numPoints || points4D->cols != numPoints )
2087 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be the same" );
2090 if( projPoints1->rows != 2 || projPoints2->rows != 2 || projPoints3->rows != 2)
2092 CV_ERROR( CV_StsUnmatchedSizes, "Number of proj points coordinates must be == 2" );
2095 if( points4D->rows != 4 )
2097 CV_ERROR( CV_StsUnmatchedSizes, "Number of world points coordinates must be == 4" );
2100 if( projMatr1->cols != 4 || projMatr1->rows != 3 ||
2101 projMatr2->cols != 4 || projMatr2->rows != 3 ||
2102 projMatr3->cols != 4 || projMatr3->rows != 3)
2104 CV_ERROR( CV_StsUnmatchedSizes, "Size of projection matrices must be 3x4" );
2108 double matrA_dat[36];
2109 matrA = cvMat(9,4,CV_64F,matrA_dat);
2114 //double matrU_dat[9*9];
2115 double matrW_dat[9*4];
2116 double matrV_dat[4*4];
2118 //matrU = cvMat(9,9,CV_64F,matrU_dat);
2119 matrW = cvMat(9,4,CV_64F,matrW_dat);
2120 matrV = cvMat(4,4,CV_64F,matrV_dat);
2122 CvMat* projPoints[3];
2123 CvMat* projMatrs[3];
2125 projPoints[0] = projPoints1;
2126 projPoints[1] = projPoints2;
2127 projPoints[2] = projPoints3;
2129 projMatrs[0] = projMatr1;
2130 projMatrs[1] = projMatr2;
2131 projMatrs[2] = projMatr3;
2133 /* Solve system for each point */
2135 for( i = 0; i < numPoints; i++ )/* For each point */
2137 /* Fill matrix for current point */
2138 for( j = 0; j < 3; j++ )/* For each view */
2141 x = cvmGet(projPoints[j],0,i);
2142 y = cvmGet(projPoints[j],1,i);
2143 for( int k = 0; k < 4; k++ )
2145 cvmSet(&matrA, j*3+0, k, x * cvmGet(projMatrs[j],2,k) - cvmGet(projMatrs[j],0,k) );
2146 cvmSet(&matrA, j*3+1, k, y * cvmGet(projMatrs[j],2,k) - cvmGet(projMatrs[j],1,k) );
2147 cvmSet(&matrA, j*3+2, k, x * cvmGet(projMatrs[j],1,k) - y * cvmGet(projMatrs[j],0,k) );
2150 /* Solve system for current point */
2152 cvSVD(&matrA,&matrW,0,&matrV,CV_SVD_V_T);
2154 /* Copy computed point */
2155 cvmSet(points4D,0,i,cvmGet(&matrV,3,0));/* X */
2156 cvmSet(points4D,1,i,cvmGet(&matrV,3,1));/* Y */
2157 cvmSet(points4D,2,i,cvmGet(&matrV,3,2));/* Z */
2158 cvmSet(points4D,3,i,cvmGet(&matrV,3,3));/* W */
2162 /* Points was reconstructed. Try to reproject points */
2163 /* We can compute reprojection error if need */
2167 double point3D_dat[4];
2168 point3D = cvMat(4,1,CV_64F,point3D_dat);
2171 double point2D_dat[3];
2172 point2D = cvMat(3,1,CV_64F,point2D_dat);
2174 for( i = 0; i < numPoints; i++ )
2176 double W = cvmGet(points4D,3,i);
2178 point3D_dat[0] = cvmGet(points4D,0,i)/W;
2179 point3D_dat[1] = cvmGet(points4D,1,i)/W;
2180 point3D_dat[2] = cvmGet(points4D,2,i)/W;
2183 // !!! Project this point for each camera
2184 for( int currCamera = 0; currCamera < 3; currCamera++ )
2186 cvmMul(projMatrs[currCamera], &point3D, &point2D);
2190 x = (float)cvmGet(projPoints[currCamera],0,i);
2191 y = (float)cvmGet(projPoints[currCamera],1,i);
2193 wr = (float)point2D_dat[2];
2194 xr = (float)(point2D_dat[0]/wr);
2195 yr = (float)(point2D_dat[1]/wr);
2197 float deltaX,deltaY;
2198 deltaX = (float)fabs(x-xr);
2199 deltaY = (float)fabs(y-yr);
2212 void ReconstructPointsFor3View_bySolve( CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
2213 CvMat* projPoints1,CvMat* projPoints2,CvMat* projPoints3,
2216 CV_FUNCNAME( "ReconstructPointsFor3View" );
2221 numPoints = projPoints1->cols;
2222 if( projPoints2->cols != numPoints || projPoints3->cols != numPoints || points3D->cols != numPoints )
2224 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be the same" );
2227 if( projPoints1->rows != 2 || projPoints2->rows != 2 || projPoints3->rows != 2)
2229 CV_ERROR( CV_StsUnmatchedSizes, "Number of proj points coordinates must be == 2" );
2232 if( points3D->rows != 4 )
2234 CV_ERROR( CV_StsUnmatchedSizes, "Number of world points coordinates must be == 4" );
2237 if( projMatr1->cols != 4 || projMatr1->rows != 3 ||
2238 projMatr2->cols != 4 || projMatr2->rows != 3 ||
2239 projMatr3->cols != 4 || projMatr3->rows != 3)
2241 CV_ERROR( CV_StsUnmatchedSizes, "Size of proj matrix must be 3x4" );
2245 double matrA_dat[3*3*3];
2246 matrA = cvMat(3*3,3,CV_64F,matrA_dat);
2249 double vectB_dat[9];
2250 vectB = cvMat(9,1,CV_64F,vectB_dat);
2253 double result_dat[3];
2254 result = cvMat(3,1,CV_64F,result_dat);
2256 CvMat* projPoints[3];
2257 CvMat* projMatrs[3];
2259 projPoints[0] = projPoints1;
2260 projPoints[1] = projPoints2;
2261 projPoints[2] = projPoints3;
2263 projMatrs[0] = projMatr1;
2264 projMatrs[1] = projMatr2;
2265 projMatrs[2] = projMatr3;
2267 /* Solve system for each point */
2269 for( i = 0; i < numPoints; i++ )/* For each point */
2271 /* Fill matrix for current point */
2272 for( j = 0; j < 3; j++ )/* For each view */
2275 x = cvmGet(projPoints[j],0,i);
2276 y = cvmGet(projPoints[j],1,i);
2278 cvmSet(&vectB,j*3+0,0,x-cvmGet(projMatrs[j],0,3));
2279 cvmSet(&vectB,j*3+1,0,y-cvmGet(projMatrs[j],1,3));
2280 cvmSet(&vectB,j*3+2,0,1-cvmGet(projMatrs[j],2,3));
2282 for( int t = 0; t < 3; t++ )
2284 for( int k = 0; k < 3; k++ )
2286 cvmSet(&matrA, j*3+t, k, cvmGet(projMatrs[j],t,k) );
2292 /* Solve system for current point */
2293 cvSolve(&matrA,&vectB,&result,CV_SVD);
2295 cvmSet(points3D,0,i,result_dat[0]);/* X */
2296 cvmSet(points3D,1,i,result_dat[1]);/* Y */
2297 cvmSet(points3D,2,i,result_dat[2]);/* Z */
2298 cvmSet(points3D,3,i,1);/* W */
2302 /* Points was reconstructed. Try to reproject points */
2306 double point3D_dat[4];
2307 point3D = cvMat(4,1,CV_64F,point3D_dat);
2310 double point2D_dat[3];
2311 point2D = cvMat(3,1,CV_64F,point2D_dat);
2313 for( i = 0; i < numPoints; i++ )
2315 double W = cvmGet(points3D,3,i);
2317 point3D_dat[0] = cvmGet(points3D,0,i)/W;
2318 point3D_dat[1] = cvmGet(points3D,1,i)/W;
2319 point3D_dat[2] = cvmGet(points3D,2,i)/W;
2322 /* Project this point for each camera */
2323 for( int currCamera = 0; currCamera < 3; currCamera++ )
2325 cvmMul(projMatrs[currCamera], &point3D, &point2D);
2328 x = (float)cvmGet(projPoints[currCamera],0,i);
2329 y = (float)cvmGet(projPoints[currCamera],1,i);
2331 wr = (float)point2D_dat[2];
2332 xr = (float)(point2D_dat[0]/wr);
2333 yr = (float)(point2D_dat[1]/wr);
2344 /*==========================================================================================*/
2346 static void icvComputeCameraExrinnsicByPosition(CvMat* camPos, CvMat* rotMatr, CvMat* transVect)
2348 /* We know position of camera. we must to compute rotate matrix and translate vector */
2350 CV_FUNCNAME( "icvComputeCameraExrinnsicByPosition" );
2353 /* Test input paramaters */
2354 if( camPos == 0 || rotMatr == 0 || transVect == 0 )
2356 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
2359 if( !CV_IS_MAT(camPos) || !CV_IS_MAT(rotMatr) || !CV_IS_MAT(transVect) )
2361 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
2364 if( camPos->cols != 1 || camPos->rows != 3 )
2366 CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of camera position must be 3x1 vector" );
2369 if( rotMatr->cols != 3 || rotMatr->rows != 3 )
2371 CV_ERROR( CV_StsUnmatchedSizes, "Rotate matrix must be 3x3" );
2374 if( transVect->cols != 1 || transVect->rows != 3 )
2376 CV_ERROR( CV_StsUnmatchedSizes, "Translate vector must be 3x1" );
2380 x = cvmGet(camPos,0,0);
2381 y = cvmGet(camPos,1,0);
2382 z = cvmGet(camPos,2,0);
2384 /* Set translate vector. It same as camea position */
2385 cvmSet(transVect,0,0,x);
2386 cvmSet(transVect,1,0,y);
2387 cvmSet(transVect,2,0,z);
2389 /* Compute rotate matrix. Compute each unit transformed vector */
2391 /* normalize flat direction x,y */
2401 vectorY[1] = x*x+z*z;
2408 /* normaize vectors */
2414 for( i = 0; i < 3; i++ )
2415 norm += vectorX[i]*vectorX[i];
2417 for( i = 0; i < 3; i++ )
2422 for( i = 0; i < 3; i++ )
2423 norm += vectorY[i]*vectorY[i];
2425 for( i = 0; i < 3; i++ )
2430 for( i = 0; i < 3; i++ )
2431 norm += vectorZ[i]*vectorZ[i];
2433 for( i = 0; i < 3; i++ )
2436 /* Set output results */
2438 for( i = 0; i < 3; i++ )
2440 cvmSet(rotMatr,i,0,vectorX[i]);
2441 cvmSet(rotMatr,i,1,vectorY[i]);
2442 cvmSet(rotMatr,i,2,vectorZ[i]);
2445 {/* Try to inverse rotate matrix */
2447 double tmpInvRot_dat[9];
2448 tmpInvRot = cvMat(3,3,CV_64F,tmpInvRot_dat);
2449 cvInvert(rotMatr,&tmpInvRot,CV_SVD);
2450 cvConvert(&tmpInvRot,rotMatr);
2461 /*==========================================================================================*/
2463 static void FindTransformForProjectMatrices(CvMat* projMatr1,CvMat* projMatr2,CvMat* rotMatr,CvMat* transVect)
2465 /* Computes homography for project matrix be "canonical" form */
2466 CV_FUNCNAME( "computeProjMatrHomography" );
2469 /* Test input paramaters */
2470 if( projMatr1 == 0 || projMatr2 == 0 || rotMatr == 0 || transVect == 0 )
2472 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
2475 if( !CV_IS_MAT(projMatr1) || !CV_IS_MAT(projMatr2) || !CV_IS_MAT(rotMatr) || !CV_IS_MAT(transVect) )
2477 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
2480 if( projMatr1->cols != 4 || projMatr1->rows != 3 )
2482 CV_ERROR( CV_StsUnmatchedSizes, "Size of project matrix 1 must be 3x4" );
2485 if( projMatr2->cols != 4 || projMatr2->rows != 3 )
2487 CV_ERROR( CV_StsUnmatchedSizes, "Size of project matrix 2 must be 3x4" );
2490 if( rotMatr->cols != 3 || rotMatr->rows != 3 )
2492 CV_ERROR( CV_StsUnmatchedSizes, "Size of rotation matrix must be 3x3" );
2495 if( transVect->cols != 1 || transVect->rows != 3 )
2497 CV_ERROR( CV_StsUnmatchedSizes, "Size of translation vector must be 3x1" );
2501 double matrA_dat[12*12];
2502 matrA = cvMat(12,12,CV_64F,matrA_dat);
2504 double vectB_dat[12];
2505 vectB = cvMat(12,1,CV_64F,vectB_dat);
2510 for( i = 0; i < 12; i++ )
2512 for( j = 0; j < 12; j++ )
2514 cvmSet(&matrA,i,j,cvmGet(projMatr1,i/4,j%4));
2518 double val = cvmGet(projMatr2,i/4,i%4);
2521 val -= cvmGet(projMatr1,i/4,3);
2524 cvmSet(&vectB,i,0,val);
2529 double resVect_dat[12];
2530 resVect = cvMat(12,1,CV_64F,resVect_dat);
2532 cvSolve(&matrA,&vectB,&resVect);
2534 /* Fill rotation matrix */
2535 for( i = 0; i < 12; i++ )
2537 double val = cvmGet(&resVect,i,0);
2539 cvmSet(rotMatr,i%3,i/3,val);
2541 cvmSet(transVect,i-9,0,val);
2549 /*==========================================================================================*/
2551 void icvComputeQknowPrincipalPoint(int numImages, CvMat **projMatrs,CvMat *matrQ, double cx,double cy)
2553 /* Computes matrix Q */
2554 /* focal x and y eqauls () */
2555 /* we know principal point for camera */
2556 /* focal may differ from image to image */
2557 /* image skew is 0 */
2559 if( numImages < 10 )
2562 //Error. Number of images too few
2572 /*==========================================================================================*/
2574 /*==========================================================================================*/
2575 /*==========================================================================================*/
2576 /*==========================================================================================*/
2577 /*==========================================================================================*/
2578 /* Part with metric reconstruction */
2581 static void icvComputeQ(int numMatr, CvMat** projMatr, CvMat** cameraMatr, CvMat* matrQ)
2584 /* try to solve Q by linear method */
2589 CV_FUNCNAME( "ComputeQ" );
2592 /* Define number of projection matrices */
2595 CV_ERROR( CV_StsUnmatchedSizes, "Number of projection matrices must be at least 2" );
2599 /* test matrices sizes */
2600 if( matrQ->cols != 4 || matrQ->rows != 4 )
2602 CV_ERROR( CV_StsUnmatchedSizes, "Size of matrix Q must be 3x3" );
2606 for( currMatr = 0; currMatr < numMatr; currMatr++ )
2609 if( cameraMatr[currMatr]->cols != 3 || cameraMatr[currMatr]->rows != 3 )
2611 CV_ERROR( CV_StsUnmatchedSizes, "Size of each camera matrix must be 3x3" );
2614 if( projMatr[currMatr]->cols != 4 || projMatr[currMatr]->rows != 3 )
2616 CV_ERROR( CV_StsUnmatchedSizes, "Size of each camera matrix must be 3x3" );
2621 double matrw_dat[9];
2622 matrw = cvMat(3,3,CV_64F,matrw_dat);
2625 double matrKt_dat[9];
2626 matrKt = cvMat(3,3,CV_64F,matrKt_dat);
2629 /* Create matrix A and vector B */
2630 CV_CALL( matrA = cvCreateMat(9*numMatr,10,CV_64F) );
2631 CV_CALL( vectB = cvCreateMat(9*numMatr,1,CV_64F) );
2635 for( currMatr = 0; currMatr < numMatr; currMatr++ )
2637 int ord10[10] = {0,1,2,3,5,6,7,10,11,15};
2638 /* Fill atrix A by data from matrices */
2640 /* Compute matrix w for current camera matrix */
2641 cvTranspose(cameraMatr[currMatr],&matrKt);
2642 cvmMul(cameraMatr[currMatr],&matrKt,&matrw);
2644 /* Fill matrix A and vector B */
2648 for( currMatr = 0; currMatr < numMatr; currMatr++ )
2650 for( currWi = 0; currWi < 3; currWi++ )
2652 for( currWj = 0; currWj < 3; currWj++ )
2655 for( i = 0; i < 4; i++ )
2657 for( j = 0; j < 4; j++ )
2659 /* get elements from current projection matrix */
2660 dataQ[i*4+j] = cvmGet(projMatr[currMatr],currWi,j) *
2661 cvmGet(projMatr[currMatr],currWj,i);
2665 /* we know 16 elements in dataQ move them to matrQ 10 */
2666 dataQ[1] += dataQ[4];
2667 dataQ[2] += dataQ[8];
2668 dataQ[3] += dataQ[12];
2669 dataQ[6] += dataQ[9];
2670 dataQ[7] += dataQ[13];
2671 dataQ[11] += dataQ[14];
2672 /* Now first 10 elements has coeffs */
2674 /* copy to matrix A */
2675 for( i = 0; i < 10; i++ )
2677 cvmSet(matrA,currMatr*9 + currWi*3+currWj,i,dataQ[ord10[i]]);
2683 for( int i = 0; i < 9; i++ )
2685 cvmSet(vectB,currMatr*9+i,0,matrw_dat[i]);
2690 /* Matrix A and vector B filled and we can solve system */
2694 double resQ_dat[10];
2695 resQ = cvMat(10,1,CV_64F,resQ_dat);
2697 cvSolve(matrA,vectB,&resQ,CV_SVD);
2699 /* System was solved. We know matrix Q. But we must have condition det Q=0 */
2700 /* Just copy result matrix Q */
2703 int ord16[16] = {0,1,2,3,1,4,5,6,2,5,7,8,3,6,8,9};
2705 for( int i = 0; i < 4; i++ )
2707 for( int j = 0; j < 4; j++ )
2709 cvmSet(matrQ,i,j,resQ_dat[ord16[curr++]]);
2717 /* Free allocated memory */
2718 cvReleaseMat(&matrA);
2719 cvReleaseMat(&vectB);
2724 /*-----------------------------------------------------------------------------------------------------*/
2726 static void icvDecomposeQ(CvMat* /*matrQ*/,CvMat* /*matrH*/)
2729 /* Use SVD to decompose matrix Q=H*I*H' */
2730 /* test input data */
2735 double matrW_dat[16];
2736 double matrU_dat[16];
2737 // double matrV_dat[16];
2739 matrW = cvMat(4,4,CV_64F,matrW_dat);
2740 matrU = cvMat(4,4,CV_64F,matrU_dat);
2741 // matrV = cvMat(4,4,CV_64F,matrV_dat);
2743 cvSVD(matrQ,&matrW,&matrU,0);
2746 eig[0] = fsqrt(cvmGet(&matrW,0,0));
2747 eig[1] = fsqrt(cvmGet(&matrW,1,1));
2748 eig[2] = fsqrt(cvmGet(&matrW,2,2));
2751 double matrIS_dat[16];
2757 /* det for matrix Q with q1-q10 */
2778 // (1-a)^4 = 1 - 4 * a + 6 * a * a - 4 * a * a * a + a * a * a * a;