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 42 #include "_cvaux.h" 43 44 //#include "cvtypes.h" 45 #include <float.h> 46 #include <limits.h> 47 //#include "cv.h" 48 //#include "windows.h" 49 50 #include <stdio.h> 51 52 /* Valery Mosyagin */ 53 54 /* Function defenitions */ 55 56 /* ----------------- */ 57 58 void cvOptimizeLevenbergMarquardtBundle( CvMat** projMatrs, CvMat** observProjPoints, 59 CvMat** pointsPres, int numImages, 60 CvMat** resultProjMatrs, CvMat* resultPoints4D,int maxIter,double epsilon ); 61 62 int icvComputeProjectMatrices6Points( CvMat* points1,CvMat* points2,CvMat* points3, 63 CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3); 64 65 void icvFindBaseTransform(CvMat* points,CvMat* resultT); 66 67 void GetGeneratorReduceFundSolution(CvMat* points1,CvMat* points2,CvMat* fundReduceCoef1,CvMat* fundReduceCoef2); 68 69 int GetGoodReduceFundamMatrFromTwo(CvMat* fundReduceCoef1,CvMat* fundReduceCoef2,CvMat* resFundReduceCoef); 70 71 void GetProjMatrFromReducedFundamental(CvMat* fundReduceCoefs,CvMat* projMatrCoefs); 72 73 void icvComputeProjectMatrix(CvMat* objPoints,CvMat* projPoints,CvMat* projMatr); 74 75 void icvComputeTransform4D(CvMat* points1,CvMat* points2,CvMat* transMatr); 76 77 int icvComputeProjectMatricesNPoints( CvMat* points1,CvMat* points2,CvMat* points3, 78 CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3, 79 double threshold,/* Threshold for good point */ 80 double p,/* Probability of good result. */ 81 CvMat* status, 82 CvMat* points4D); 83 84 int icvComputeProjectMatricesNPoints( CvMat* points1,CvMat* points2,CvMat* points3, 85 CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3, 86 double threshold,/* Threshold for good point */ 87 double p,/* Probability of good result. */ 88 CvMat* status, 89 CvMat* points4D); 90 91 void icvReconstructPointsFor3View( CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3, 92 CvMat* projPoints1,CvMat* projPoints2,CvMat* projPoints3, 93 CvMat* points4D); 94 95 void icvReconstructPointsFor3View( CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3, 96 CvMat* projPoints1,CvMat* projPoints2,CvMat* projPoints3, 97 CvMat* points4D); 98 99 /*==========================================================================================*/ 100 /* Functions for calculation the tensor */ 101 /*==========================================================================================*/ 102 #if 1 103 void fprintMatrix(FILE* file,CvMat* matrix) 104 { 105 int i,j; 106 fprintf(file,"\n"); 107 for( i=0;i<matrix->rows;i++ ) 108 { 109 for(j=0;j<matrix->cols;j++) 110 { 111 fprintf(file,"%10.7lf ",cvmGet(matrix,i,j)); 112 } 113 fprintf(file,"\n"); 114 } 115 } 116 #endif 117 /*==========================================================================================*/ 118 119 void icvNormalizePoints( CvMat* points, CvMat* normPoints,CvMat* cameraMatr ) 120 { 121 /* Normalize image points using camera matrix */ 122 123 CV_FUNCNAME( "icvNormalizePoints" ); 124 __BEGIN__; 125 126 /* Test for null pointers */ 127 if( points == 0 || normPoints == 0 || cameraMatr == 0 ) 128 { 129 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 130 } 131 132 if( !CV_IS_MAT(points) || !CV_IS_MAT(normPoints) || !CV_IS_MAT(cameraMatr) ) 133 { 134 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" ); 135 } 136 137 int numPoints; 138 numPoints = points->cols; 139 if( numPoints <= 0 || numPoints != normPoints->cols ) 140 { 141 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be the same and more than 0" ); 142 } 143 144 if( normPoints->rows != 2 || normPoints->rows != points->rows ) 145 { 146 CV_ERROR( CV_StsUnmatchedSizes, "Points must have 2 coordinates" ); 147 } 148 149 if(cameraMatr->rows != 3 || cameraMatr->cols != 3) 150 { 151 CV_ERROR( CV_StsUnmatchedSizes, "Size of camera matrix must be 3x3" ); 152 } 153 154 double fx,fy,cx,cy; 155 156 fx = cvmGet(cameraMatr,0,0); 157 fy = cvmGet(cameraMatr,1,1); 158 cx = cvmGet(cameraMatr,0,2); 159 cy = cvmGet(cameraMatr,1,2); 160 161 int i; 162 for( i = 0; i < numPoints; i++ ) 163 { 164 cvmSet(normPoints, 0, i, (cvmGet(points,0,i) - cx) / fx ); 165 cvmSet(normPoints, 1, i, (cvmGet(points,1,i) - cy) / fy ); 166 } 167 168 __END__; 169 170 return; 171 } 172 173 174 /*=====================================================================================*/ 175 /* 176 Computes projection matrices for given 6 points on 3 images 177 May returns 3 results. */ 178 int icvComputeProjectMatrices6Points( CvMat* points1,CvMat* points2,CvMat* points3, 179 CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3/*, 180 CvMat* points4D*/) 181 { 182 /* Test input data correctness */ 183 184 int numSol = 0; 185 186 CV_FUNCNAME( "icvComputeProjectMatrices6Points" ); 187 __BEGIN__; 188 189 /* Test for null pointers */ 190 if( points1 == 0 || points2 == 0 || points3 == 0 || 191 projMatr1 == 0 || projMatr2 == 0 || projMatr3 == 0 ) 192 { 193 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 194 } 195 196 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2) || !CV_IS_MAT(points3) || 197 !CV_IS_MAT(projMatr1) || !CV_IS_MAT(projMatr2) || !CV_IS_MAT(projMatr3) ) 198 { 199 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" ); 200 } 201 202 if( (points1->cols != points2->cols) || (points1->cols != points3->cols) || (points1->cols != 6) /* || (points4D->cols !=6) */) 203 { 204 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be same and == 6" ); 205 } 206 207 if( points1->rows != 2 || points2->rows != 2 || points3->rows != 2 ) 208 { 209 CV_ERROR( CV_StsUnmatchedSizes, "Number of points coordinates must be 2" ); 210 } 211 212 if( projMatr1->cols != 4 || projMatr2->cols != 4 || projMatr3->cols != 4 || 213 !(projMatr1->rows == 3 && projMatr2->rows == 3 && projMatr3->rows == 3) && 214 !(projMatr1->rows == 9 && projMatr2->rows == 9 && projMatr3->rows == 9) ) 215 { 216 CV_ERROR( CV_StsUnmatchedSizes, "Size of project matrix must be 3x4 or 9x4 (for 3 matrices)" ); 217 } 218 219 #if 0 220 if( points4D->row != 4 ) 221 { 222 CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of points4D must be 4" ); 223 } 224 #endif 225 226 /* Find transform matrix for each camera */ 227 int i; 228 CvMat* points[3]; 229 points[0] = points1; 230 points[1] = points2; 231 points[2] = points3; 232 233 CvMat* projMatrs[3]; 234 projMatrs[0] = projMatr1; 235 projMatrs[1] = projMatr2; 236 projMatrs[2] = projMatr3; 237 238 CvMat transMatr; 239 double transMatr_dat[9]; 240 transMatr = cvMat(3,3,CV_64F,transMatr_dat); 241 242 CvMat corrPoints1; 243 CvMat corrPoints2; 244 245 double corrPoints_dat[3*3*2];/* 3-point(images) by 3-coordinates by 2-correspondence*/ 246 247 corrPoints1 = cvMat(3,3,CV_64F,corrPoints_dat); /* 3-coordinates for each of 3-points(3-image) */ 248 corrPoints2 = cvMat(3,3,CV_64F,corrPoints_dat+9);/* 3-coordinates for each of 3-points(3-image) */ 249 250 for( i = 0; i < 3; i++ )/* for each image */ 251 { 252 /* Get last 4 points for computing transformation */ 253 CvMat tmpPoints; 254 /* find base points transform for last four points on i-th image */ 255 cvGetSubRect(points[i],&tmpPoints,cvRect(2,0,4,2)); 256 icvFindBaseTransform(&tmpPoints,&transMatr); 257 258 {/* We have base transform. Compute error scales for three first points */ 259 CvMat trPoint; 260 double trPoint_dat[3*3]; 261 trPoint = cvMat(3,3,CV_64F,trPoint_dat); 262 /* fill points */ 263 for( int kk = 0; kk < 3; kk++ ) 264 { 265 cvmSet(&trPoint,0,kk,cvmGet(points[i],0,kk+2)); 266 cvmSet(&trPoint,1,kk,cvmGet(points[i],1,kk+2)); 267 cvmSet(&trPoint,2,kk,1); 268 } 269 270 /* Transform points */ 271 CvMat resPnts; 272 double resPnts_dat[9]; 273 resPnts = cvMat(3,3,CV_64F,resPnts_dat); 274 cvmMul(&transMatr,&trPoint,&resPnts); 275 } 276 277 /* Transform two first points */ 278 for( int j = 0; j < 2; j++ ) 279 { 280 CvMat pnt; 281 double pnt_dat[3]; 282 pnt = cvMat(3,1,CV_64F,pnt_dat); 283 pnt_dat[0] = cvmGet(points[i],0,j); 284 pnt_dat[1] = cvmGet(points[i],1,j); 285 pnt_dat[2] = 1.0; 286 287 CvMat trPnt; 288 double trPnt_dat[3]; 289 trPnt = cvMat(3,1,CV_64F,trPnt_dat); 290 291 cvmMul(&transMatr,&pnt,&trPnt); 292 293 /* Collect transformed points */ 294 corrPoints_dat[j * 9 + 0 * 3 + i] = trPnt_dat[0];/* x */ 295 corrPoints_dat[j * 9 + 1 * 3 + i] = trPnt_dat[1];/* y */ 296 corrPoints_dat[j * 9 + 2 * 3 + i] = trPnt_dat[2];/* w */ 297 } 298 } 299 300 /* We have computed corr points. Now we can compute generators for reduced fundamental matrix */ 301 302 /* Compute generators for reduced fundamental matrix from 3 pair of collect points */ 303 CvMat fundReduceCoef1; 304 CvMat fundReduceCoef2; 305 double fundReduceCoef1_dat[5]; 306 double fundReduceCoef2_dat[5]; 307 308 fundReduceCoef1 = cvMat(1,5,CV_64F,fundReduceCoef1_dat); 309 fundReduceCoef2 = cvMat(1,5,CV_64F,fundReduceCoef2_dat); 310 311 GetGeneratorReduceFundSolution(&corrPoints1, &corrPoints2, &fundReduceCoef1, &fundReduceCoef2); 312 313 /* Choose best solutions for two generators. We can get 3 solutions */ 314 CvMat resFundReduceCoef; 315 double resFundReduceCoef_dat[3*5]; 316 317 resFundReduceCoef = cvMat(3,5,CV_64F,resFundReduceCoef_dat); 318 319 numSol = GetGoodReduceFundamMatrFromTwo(&fundReduceCoef1, &fundReduceCoef2,&resFundReduceCoef); 320 321 int maxSol; 322 maxSol = projMatrs[0]->rows / 3; 323 324 int currSol; 325 for( currSol = 0; (currSol < numSol && currSol < maxSol); currSol++ ) 326 { 327 /* For current solution compute projection matrix */ 328 CvMat fundCoefs; 329 cvGetSubRect(&resFundReduceCoef, &fundCoefs, cvRect(0,currSol,5,1)); 330 331 CvMat projMatrCoefs; 332 double projMatrCoefs_dat[4]; 333 projMatrCoefs = cvMat(1,4,CV_64F,projMatrCoefs_dat); 334 335 GetProjMatrFromReducedFundamental(&fundCoefs,&projMatrCoefs); 336 /* we have computed coeffs for reduced project matrix */ 337 338 CvMat objPoints; 339 double objPoints_dat[4*6]; 340 objPoints = cvMat(4,6,CV_64F,objPoints_dat); 341 cvZero(&objPoints); 342 343 /* fill object points */ 344 for( i =0; i < 4; i++ ) 345 { 346 objPoints_dat[i*6] = 1; 347 objPoints_dat[i*6+1] = projMatrCoefs_dat[i]; 348 objPoints_dat[i*7+2] = 1; 349 } 350 351 int currCamera; 352 for( currCamera = 0; currCamera < 3; currCamera++ ) 353 { 354 355 CvMat projPoints; 356 double projPoints_dat[3*6]; 357 projPoints = cvMat(3,6,CV_64F,projPoints_dat); 358 359 /* fill projected points for current camera */ 360 for( i = 0; i < 6; i++ )/* for each points for current camera */ 361 { 362 projPoints_dat[6*0+i] = cvmGet(points[currCamera],0,i);/* x */ 363 projPoints_dat[6*1+i] = cvmGet(points[currCamera],1,i);/* y */ 364 projPoints_dat[6*2+i] = 1;/* w */ 365 } 366 367 /* compute project matrix for current camera */ 368 CvMat projMatrix; 369 double projMatrix_dat[3*4]; 370 projMatrix = cvMat(3,4,CV_64F,projMatrix_dat); 371 372 icvComputeProjectMatrix(&objPoints,&projPoints,&projMatrix); 373 374 /* Add this matrix to result */ 375 CvMat tmpSubRes; 376 cvGetSubRect(projMatrs[currCamera],&tmpSubRes,cvRect(0,currSol*3,4,3)); 377 cvConvert(&projMatrix,&tmpSubRes); 378 } 379 380 /* We know project matrices. And we can reconstruct 6 3D-points if need */ 381 #if 0 382 if( points4D ) 383 { 384 if( currSol < points4D->rows / 4 ) 385 { 386 CvMat tmpPoints4D; 387 double tmpPoints4D_dat[4*6]; 388 tmpPoints4D = cvMat(4,6,CV_64F,tmpPoints4D_dat); 389 390 icvReconstructPointsFor3View( &wProjMatr[0], &wProjMatr[1], &wProjMatr[2], 391 points1, points2, points3, 392 &tmpPoints4D); 393 394 CvMat tmpSubRes; 395 cvGetSubRect(points4D,tmpSubRes,cvRect(0,currSol*4,6,4)); 396 cvConvert(tmpPoints4D,points4D); 397 } 398 } 399 #endif 400 401 }/* for all sollutions */ 402 403 __END__; 404 return numSol; 405 } 406 407 /*==========================================================================================*/ 408 int icvGetRandNumbers(int range,int count,int* arr) 409 { 410 /* Generate random numbers [0,range-1] */ 411 412 CV_FUNCNAME( "icvGetRandNumbers" ); 413 __BEGIN__; 414 415 /* Test input data */ 416 if( arr == 0 ) 417 { 418 CV_ERROR( CV_StsNullPtr, "Parameter 'arr' is a NULL pointer" ); 419 } 420 421 422 /* Test for errors input data */ 423 if( range < count || range <= 0 ) 424 { 425 CV_ERROR( CV_StsOutOfRange, "Can't generate such numbers. Count must be <= range and range must be > 0" ); 426 } 427 428 int i,j; 429 int newRand; 430 for( i = 0; i < count; i++ ) 431 { 432 433 int haveRep = 0;/* firstly we have not repeats */ 434 do 435 { 436 /* generate new number */ 437 newRand = rand()%range; 438 haveRep = 0; 439 /* Test for repeats in previous numbers */ 440 for( j = 0; j < i; j++ ) 441 { 442 if( arr[j] == newRand ) 443 { 444 haveRep = 1; 445 break; 446 } 447 } 448 } while(haveRep); 449 450 /* We have good random number */ 451 arr[i] = newRand; 452 } 453 __END__; 454 return 1; 455 } 456 /*==========================================================================================*/ 457 void icvSelectColsByNumbers(CvMat* srcMatr, CvMat* dstMatr, int* indexes,int number) 458 { 459 460 CV_FUNCNAME( "icvSelectColsByNumbers" ); 461 __BEGIN__; 462 463 /* Test input data */ 464 if( srcMatr == 0 || dstMatr == 0 || indexes == 0) 465 { 466 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 467 } 468 469 if( !CV_IS_MAT(srcMatr) || !CV_IS_MAT(dstMatr) ) 470 { 471 CV_ERROR( CV_StsUnsupportedFormat, "srcMatr and dstMatr must be a matrices" ); 472 } 473 474 int srcSize; 475 int numRows; 476 numRows = srcMatr->rows; 477 srcSize = srcMatr->cols; 478 479 if( numRows != dstMatr->rows ) 480 { 481 CV_ERROR( CV_StsOutOfRange, "Number of rows of matrices must be the same" ); 482 } 483 484 int dst; 485 for( dst = 0; dst < number; dst++ ) 486 { 487 int src = indexes[dst]; 488 if( src >=0 && src < srcSize ) 489 { 490 /* Copy each elements in column */ 491 int i; 492 for( i = 0; i < numRows; i++ ) 493 { 494 cvmSet(dstMatr,i,dst,cvmGet(srcMatr,i,src)); 495 } 496 } 497 } 498 499 __END__; 500 return; 501 } 502 503 /*==========================================================================================*/ 504 void icvProject4DPoints(CvMat* points4D,CvMat* projMatr, CvMat* projPoints) 505 { 506 507 CvMat* tmpProjPoints = 0; 508 509 CV_FUNCNAME( "icvProject4DPoints" ); 510 511 __BEGIN__; 512 513 if( points4D == 0 || projMatr == 0 || projPoints == 0) 514 { 515 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 516 } 517 518 if( !CV_IS_MAT(points4D) || !CV_IS_MAT(projMatr) || !CV_IS_MAT(projPoints) ) 519 { 520 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" ); 521 } 522 523 int numPoints; 524 numPoints = points4D->cols; 525 if( numPoints < 1 ) 526 { 527 CV_ERROR( CV_StsOutOfRange, "Number of points4D must be more than zero" ); 528 } 529 530 if( numPoints != projPoints->cols ) 531 { 532 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be the same"); 533 } 534 535 if( projPoints->rows != 2 ) 536 { 537 CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of projected points must be 2"); 538 } 539 540 if( points4D->rows != 4 ) 541 { 542 CV_ERROR(CV_StsUnmatchedSizes, "Number of coordinates of 4D points must be 4"); 543 } 544 545 if( projMatr->cols != 4 || projMatr->rows != 3 ) 546 { 547 CV_ERROR( CV_StsUnmatchedSizes, "Size of projection matrix must be 3x4"); 548 } 549 550 551 CV_CALL( tmpProjPoints = cvCreateMat(3,numPoints,CV_64F) ); 552 553 cvmMul(projMatr,points4D,tmpProjPoints); 554 555 /* Scale points */ 556 int i; 557 for( i = 0; i < numPoints; i++ ) 558 { 559 double scale,x,y; 560 561 scale = cvmGet(tmpProjPoints,2,i); 562 x = cvmGet(tmpProjPoints,0,i); 563 y = cvmGet(tmpProjPoints,1,i); 564 565 if( fabs(scale) > 1e-7 ) 566 { 567 x /= scale; 568 y /= scale; 569 } 570 else 571 { 572 x = 1e8; 573 y = 1e8; 574 } 575 576 cvmSet(projPoints,0,i,x); 577 cvmSet(projPoints,1,i,y); 578 } 579 580 __END__; 581 582 cvReleaseMat(&tmpProjPoints); 583 584 return; 585 } 586 /*==========================================================================================*/ 587 int icvCompute3ProjectMatricesNPointsStatus( CvMat** points,/* 3 arrays of points on image */ 588 CvMat** projMatrs,/* array of 3 prejection matrices */ 589 CvMat** statuses,/* 3 arrays of status of points */ 590 double threshold,/* Threshold for good point */ 591 double p,/* Probability of good result. */ 592 CvMat* resStatus, 593 CvMat* points4D) 594 { 595 int numProjMatrs = 0; 596 unsigned char *comStat = 0; 597 CvMat *triPoints[3] = {0,0,0}; 598 CvMat *status = 0; 599 CvMat *triPoints4D = 0; 600 601 CV_FUNCNAME( "icvCompute3ProjectMatricesNPointsStatus" ); 602 __BEGIN__; 603 604 /* Test for errors */ 605 if( points == 0 || projMatrs == 0 || statuses == 0 || resStatus == 0 ) 606 { 607 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 608 } 609 610 int currImage; 611 for( currImage = 0; currImage < 3; currImage++ ) 612 { 613 /* Test for null pointers */ 614 if( points[currImage] == 0 ) 615 { 616 CV_ERROR( CV_StsNullPtr, "Some of points arrays is a NULL pointer" ); 617 } 618 619 if( projMatrs[currImage] == 0 ) 620 { 621 CV_ERROR( CV_StsNullPtr, "Some of projMatr is a NULL pointer" ); 622 } 623 624 if( statuses[currImage] == 0 ) 625 { 626 CV_ERROR( CV_StsNullPtr, "Some of status arrays is a NULL pointer" ); 627 } 628 629 /* Test for matrices */ 630 if( !CV_IS_MAT(points[currImage]) ) 631 { 632 CV_ERROR( CV_StsNullPtr, "Some of points arrays is not a matrix" ); 633 } 634 635 if( !CV_IS_MAT(projMatrs[currImage]) ) 636 { 637 CV_ERROR( CV_StsNullPtr, "Some of projMatr is not a matrix" ); 638 } 639 640 if( !CV_IS_MASK_ARR(statuses[currImage]) ) 641 { 642 CV_ERROR( CV_StsNullPtr, "Some of status arrays is not a mask array" ); 643 } 644 } 645 646 int numPoints; 647 numPoints = points[0]->cols; 648 if( numPoints < 6 ) 649 { 650 CV_ERROR( CV_StsOutOfRange, "Number points must be more than 6" ); 651 } 652 653 for( currImage = 0; currImage < 3; currImage++ ) 654 { 655 if( points[currImage]->cols != numPoints || statuses[currImage]->cols != numPoints ) 656 { 657 CV_ERROR( CV_StsUnmatchedSizes, "Number of points and statuses must be the same" ); 658 } 659 660 if( points[currImage]->rows != 2 ) 661 { 662 CV_ERROR( CV_StsOutOfRange, "Number of points coordinates must be == 2" ); 663 } 664 665 if( statuses[currImage]->rows != 1 ) 666 { 667 CV_ERROR( CV_StsOutOfRange, "Each of status must be matrix 1xN" ); 668 } 669 670 if( projMatrs[currImage]->rows != 3 || projMatrs[currImage]->cols != 4 ) 671 { 672 CV_ERROR( CV_StsOutOfRange, "Each of projection matrix must be 3x4" ); 673 } 674 } 675 676 677 /* Create common status for all points */ 678 679 int i; 680 681 CV_CALL( comStat = (unsigned char*)cvAlloc(sizeof(unsigned char)*numPoints) ); 682 683 unsigned char *stats[3]; 684 685 stats[0] = statuses[0]->data.ptr; 686 stats[1] = statuses[1]->data.ptr; 687 stats[2] = statuses[2]->data.ptr; 688 689 int numTripl; 690 numTripl = 0; 691 for( i = 0; i < numPoints; i++ ) 692 { 693 comStat[i] = (unsigned char)(stats[0][i] * stats[1][i] * stats[2][i]); 694 numTripl += comStat[i]; 695 } 696 697 if( numTripl > 0 ) 698 { 699 /* Create new arrays with points */ 700 CV_CALL( triPoints[0] = cvCreateMat(2,numTripl,CV_64F) ); 701 CV_CALL( triPoints[1] = cvCreateMat(2,numTripl,CV_64F) ); 702 CV_CALL( triPoints[2] = cvCreateMat(2,numTripl,CV_64F) ); 703 if( points4D ) 704 { 705 CV_CALL( triPoints4D = cvCreateMat(4,numTripl,CV_64F) ); 706 } 707 708 /* Create status array */ 709 CV_CALL( status = cvCreateMat(1,numTripl,CV_64F) ); 710 711 /* Copy points to new arrays */ 712 int currPnt = 0; 713 for( i = 0; i < numPoints; i++ ) 714 { 715 if( comStat[i] ) 716 { 717 for( currImage = 0; currImage < 3; currImage++ ) 718 { 719 cvmSet(triPoints[currImage],0,currPnt,cvmGet(points[currImage],0,i)); 720 cvmSet(triPoints[currImage],1,currPnt,cvmGet(points[currImage],1,i)); 721 } 722 currPnt++; 723 } 724 } 725 726 /* Call function */ 727 numProjMatrs = icvComputeProjectMatricesNPoints( triPoints[0],triPoints[1],triPoints[2], 728 projMatrs[0],projMatrs[1],projMatrs[2], 729 threshold,/* Threshold for good point */ 730 p,/* Probability of good result. */ 731 status, 732 triPoints4D); 733 734 /* Get computed status and set to result */ 735 cvZero(resStatus); 736 currPnt = 0; 737 for( i = 0; i < numPoints; i++ ) 738 { 739 if( comStat[i] ) 740 { 741 if( cvmGet(status,0,currPnt) > 0 ) 742 { 743 resStatus->data.ptr[i] = 1; 744 } 745 currPnt++; 746 } 747 } 748 749 if( triPoints4D ) 750 { 751 /* Copy copmuted 4D points */ 752 cvZero(points4D); 753 currPnt = 0; 754 for( i = 0; i < numPoints; i++ ) 755 { 756 if( comStat[i] ) 757 { 758 if( cvmGet(status,0,currPnt) > 0 ) 759 { 760 cvmSet( points4D, 0, i, cvmGet( triPoints4D , 0, currPnt) ); 761 cvmSet( points4D, 1, i, cvmGet( triPoints4D , 1, currPnt) ); 762 cvmSet( points4D, 2, i, cvmGet( triPoints4D , 2, currPnt) ); 763 cvmSet( points4D, 3, i, cvmGet( triPoints4D , 3, currPnt) ); 764 } 765 currPnt++; 766 } 767 } 768 } 769 } 770 771 __END__; 772 773 /* Free allocated memory */ 774 cvReleaseMat(&status); 775 cvFree( &comStat); 776 cvReleaseMat(&status); 777 778 cvReleaseMat(&triPoints[0]); 779 cvReleaseMat(&triPoints[1]); 780 cvReleaseMat(&triPoints[2]); 781 cvReleaseMat(&triPoints4D); 782 783 return numProjMatrs; 784 785 } 786 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. */ 792 CvMat* status, 793 CvMat* points4D) 794 { 795 /* Returns status for each point, Good or bad */ 796 797 /* Compute projection matrices using N points */ 798 799 char* flags = 0; 800 char* bestFlags = 0; 801 802 int numProjMatrs = 0; 803 804 CvMat* tmpProjPoints[3]={0,0,0}; 805 CvMat* recPoints4D = 0; 806 CvMat *reconPoints4D = 0; 807 808 809 CV_FUNCNAME( "icvComputeProjectMatricesNPoints" ); 810 __BEGIN__; 811 812 CvMat* points[3]; 813 points[0] = points1; 814 points[1] = points2; 815 points[2] = points3; 816 817 /* Test for errors */ 818 if( points1 == 0 || points2 == 0 || points3 == 0 || 819 projMatr1 == 0 || projMatr2 == 0 || projMatr3 == 0 || 820 status == 0) 821 { 822 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 823 } 824 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) || 827 !CV_IS_MAT(status) ) 828 { 829 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" ); 830 } 831 832 int numPoints; 833 numPoints = points1->cols; 834 835 if( numPoints < 6 ) 836 { 837 CV_ERROR( CV_StsOutOfRange, "Number points must be more than 6" ); 838 } 839 840 if( numPoints != points2->cols || numPoints != points3->cols ) 841 { 842 CV_ERROR( CV_StsUnmatchedSizes, "number of points must be the same" ); 843 } 844 845 if( p < 0 || p > 1.0 ) 846 { 847 CV_ERROR( CV_StsOutOfRange, "Probability must be >=0 and <=1" ); 848 } 849 850 if( threshold < 0 ) 851 { 852 CV_ERROR( CV_StsOutOfRange, "Threshold for good points must be at least >= 0" ); 853 } 854 855 CvMat* projMatrs[3]; 856 857 projMatrs[0] = projMatr1; 858 projMatrs[1] = projMatr2; 859 projMatrs[2] = projMatr3; 860 861 int i; 862 for( i = 0; i < 3; i++ ) 863 { 864 if( projMatrs[i]->cols != 4 || projMatrs[i]->rows != 3 ) 865 { 866 CV_ERROR( CV_StsUnmatchedSizes, "Size of projection matrices must be 3x4" ); 867 } 868 } 869 870 for( i = 0; i < 3; i++ ) 871 { 872 if( points[i]->rows != 2) 873 { 874 CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of points must be 2" ); 875 } 876 } 877 878 /* use RANSAC algorithm to compute projection matrices */ 879 880 CV_CALL( recPoints4D = cvCreateMat(4,numPoints,CV_64F) ); 881 CV_CALL( tmpProjPoints[0] = cvCreateMat(2,numPoints,CV_64F) ); 882 CV_CALL( tmpProjPoints[1] = cvCreateMat(2,numPoints,CV_64F) ); 883 CV_CALL( tmpProjPoints[2] = cvCreateMat(2,numPoints,CV_64F) ); 884 885 CV_CALL( flags = (char*)cvAlloc(sizeof(char)*numPoints) ); 886 CV_CALL( bestFlags = (char*)cvAlloc(sizeof(char)*numPoints) ); 887 888 { 889 int NumSamples = 500;/* just init number of samples */ 890 int wasCount = 0; /* count of choosing samples */ 891 int maxGoodPoints = 0; 892 int numGoodPoints = 0; 893 894 double bestProjMatrs_dat[36]; 895 CvMat bestProjMatrs[3]; 896 bestProjMatrs[0] = cvMat(3,4,CV_64F,bestProjMatrs_dat); 897 bestProjMatrs[1] = cvMat(3,4,CV_64F,bestProjMatrs_dat+12); 898 bestProjMatrs[2] = cvMat(3,4,CV_64F,bestProjMatrs_dat+24); 899 900 double tmpProjMatr_dat[36*3]; 901 CvMat tmpProjMatr[3]; 902 tmpProjMatr[0] = cvMat(9,4,CV_64F,tmpProjMatr_dat); 903 tmpProjMatr[1] = cvMat(9,4,CV_64F,tmpProjMatr_dat+36); 904 tmpProjMatr[2] = cvMat(9,4,CV_64F,tmpProjMatr_dat+72); 905 906 /* choosen points */ 907 908 while( wasCount < NumSamples ) 909 { 910 /* select samples */ 911 int randNumbs[6]; 912 icvGetRandNumbers(numPoints,6,randNumbs); 913 914 /* random numbers of points was generated */ 915 /* select points */ 916 917 double selPoints_dat[2*6*3]; 918 CvMat selPoints[3]; 919 selPoints[0] = cvMat(2,6,CV_64F,selPoints_dat); 920 selPoints[1] = cvMat(2,6,CV_64F,selPoints_dat+12); 921 selPoints[2] = cvMat(2,6,CV_64F,selPoints_dat+24); 922 923 /* Copy 6 point for random indexes */ 924 icvSelectColsByNumbers( points[0], &selPoints[0], randNumbs,6); 925 icvSelectColsByNumbers( points[1], &selPoints[1], randNumbs,6); 926 icvSelectColsByNumbers( points[2], &selPoints[2], randNumbs,6); 927 928 /* Compute projection matrices for this points */ 929 int numProj = icvComputeProjectMatrices6Points( &selPoints[0],&selPoints[1],&selPoints[2], 930 &tmpProjMatr[0],&tmpProjMatr[1],&tmpProjMatr[2]); 931 932 /* Compute number of good points for each matrix */ 933 CvMat proj6[3]; 934 for( int currProj = 0; currProj < numProj; currProj++ ) 935 { 936 cvGetSubArr(&tmpProjMatr[0],&proj6[0],cvRect(0,currProj*3,4,3)); 937 cvGetSubArr(&tmpProjMatr[1],&proj6[1],cvRect(0,currProj*3,4,3)); 938 cvGetSubArr(&tmpProjMatr[2],&proj6[2],cvRect(0,currProj*3,4,3)); 939 940 /* Reconstruct points for projection matrices */ 941 icvReconstructPointsFor3View( &proj6[0],&proj6[1],&proj6[2], 942 points[0], points[1], points[2], 943 recPoints4D); 944 945 /* Project points to images using projection matrices */ 946 icvProject4DPoints(recPoints4D,&proj6[0],tmpProjPoints[0]); 947 icvProject4DPoints(recPoints4D,&proj6[1],tmpProjPoints[1]); 948 icvProject4DPoints(recPoints4D,&proj6[2],tmpProjPoints[2]); 949 950 /* Compute distances and number of good points (inliers) */ 951 int i; 952 int currImage; 953 numGoodPoints = 0; 954 for( i = 0; i < numPoints; i++ ) 955 { 956 double dist=-1; 957 dist = 0; 958 /* Choose max distance for each of three points */ 959 for( currImage = 0; currImage < 3; currImage++ ) 960 { 961 double x1,y1,x2,y2; 962 x1 = cvmGet(tmpProjPoints[currImage],0,i); 963 y1 = cvmGet(tmpProjPoints[currImage],1,i); 964 x2 = cvmGet(points[currImage],0,i); 965 y2 = cvmGet(points[currImage],1,i); 966 967 double dx,dy; 968 dx = x1-x2; 969 dy = y1-y2; 970 #if 1 971 double newDist = dx*dx+dy*dy; 972 if( newDist > dist ) 973 { 974 dist = newDist; 975 } 976 #else 977 dist += sqrt(dx*dx+dy*dy)/3.0; 978 #endif 979 } 980 dist = sqrt(dist); 981 flags[i] = (char)(dist > threshold ? 0 : 1); 982 numGoodPoints += flags[i]; 983 984 } 985 986 987 if( numGoodPoints > maxGoodPoints ) 988 {/* Copy current projection matrices as best */ 989 990 cvCopy(&proj6[0],&bestProjMatrs[0]); 991 cvCopy(&proj6[1],&bestProjMatrs[1]); 992 cvCopy(&proj6[2],&bestProjMatrs[2]); 993 994 maxGoodPoints = numGoodPoints; 995 /* copy best flags */ 996 memcpy(bestFlags,flags,sizeof(flags[0])*numPoints); 997 998 /* Adaptive number of samples to count*/ 999 double ep = 1 - (double)numGoodPoints / (double)numPoints; 1000 if( ep == 1 ) 1001 { 1002 ep = 0.5;/* if there is not good points set ration of outliers to 50% */ 1003 } 1004 1005 double newNumSamples = (log(1-p) / log(1-pow(1-ep,6))); 1006 if( newNumSamples < double(NumSamples) ) 1007 { 1008 NumSamples = cvRound(newNumSamples); 1009 } 1010 } 1011 } 1012 1013 wasCount++; 1014 } 1015 #if 0 1016 char str[300]; 1017 sprintf(str,"Initial numPoints = %d\nmaxGoodPoints=%d\nRANSAC made %d steps", 1018 numPoints, 1019 maxGoodPoints, 1020 cvRound(wasCount)); 1021 MessageBox(0,str,"Info",MB_OK|MB_TASKMODAL); 1022 #endif 1023 1024 /* we may have best 6-point projection matrices. */ 1025 /* and best points */ 1026 /* use these points to improve matrices */ 1027 1028 if( maxGoodPoints < 6 ) 1029 { 1030 /* matrix not found */ 1031 numProjMatrs = 0; 1032 } 1033 else 1034 { 1035 /* We may Improove matrices using ---- method */ 1036 /* We may try to use Levenberg-Marquardt optimization */ 1037 //int currIter = 0; 1038 int finalGoodPoints = 0; 1039 char *goodFlags = 0; 1040 goodFlags = (char*)cvAlloc(numPoints*sizeof(char)); 1041 1042 int needRepeat; 1043 do 1044 { 1045 #if 0 1046 /* Version without using status for Levenberg-Marquardt minimization */ 1047 1048 CvMat *optStatus; 1049 optStatus = cvCreateMat(1,numPoints,CV_64F); 1050 int testNumber = 0; 1051 for( i=0;i<numPoints;i++ ) 1052 { 1053 cvmSet(optStatus,0,i,(double)bestFlags[i]); 1054 testNumber += bestFlags[i]; 1055 } 1056 1057 char str2[200]; 1058 sprintf(str2,"test good num=%d\nmaxGoodPoints=%d",testNumber,maxGoodPoints); 1059 MessageBox(0,str2,"Info",MB_OK|MB_TASKMODAL); 1060 1061 CvMat *gPresPoints; 1062 gPresPoints = cvCreateMat(1,maxGoodPoints,CV_64F); 1063 for( i = 0; i < maxGoodPoints; i++) 1064 { 1065 cvmSet(gPresPoints,0,i,1.0); 1066 } 1067 1068 /* Create array of points pres */ 1069 CvMat *pointsPres[3]; 1070 pointsPres[0] = gPresPoints; 1071 pointsPres[1] = gPresPoints; 1072 pointsPres[2] = gPresPoints; 1073 1074 /* Create just good points 2D */ 1075 CvMat *gPoints[3]; 1076 icvCreateGoodPoints(points[0],&gPoints[0],optStatus); 1077 icvCreateGoodPoints(points[1],&gPoints[1],optStatus); 1078 icvCreateGoodPoints(points[2],&gPoints[2],optStatus); 1079 1080 /* Create 4D points array for good points */ 1081 CvMat *resPoints4D; 1082 resPoints4D = cvCreateMat(4,maxGoodPoints,CV_64F); 1083 1084 CvMat* projMs[3]; 1085 1086 projMs[0] = &bestProjMatrs[0]; 1087 projMs[1] = &bestProjMatrs[1]; 1088 projMs[2] = &bestProjMatrs[2]; 1089 1090 1091 CvMat resProjMatrs[3]; 1092 double resProjMatrs_dat[36]; 1093 resProjMatrs[0] = cvMat(3,4,CV_64F,resProjMatrs_dat); 1094 resProjMatrs[1] = cvMat(3,4,CV_64F,resProjMatrs_dat+12); 1095 resProjMatrs[2] = cvMat(3,4,CV_64F,resProjMatrs_dat+24); 1096 1097 CvMat* resMatrs[3]; 1098 resMatrs[0] = &resProjMatrs[0]; 1099 resMatrs[1] = &resProjMatrs[1]; 1100 resMatrs[2] = &resProjMatrs[2]; 1101 1102 cvOptimizeLevenbergMarquardtBundle( projMs,//projMs, 1103 gPoints,//points,//points2D, 1104 pointsPres,//pointsPres, 1105 3, 1106 resMatrs,//resProjMatrs, 1107 resPoints4D,//resPoints4D, 1108 100, 1e-9 ); 1109 1110 /* We found optimized projection matrices */ 1111 1112 CvMat *reconPoints4D; 1113 reconPoints4D = cvCreateMat(4,numPoints,CV_64F); 1114 1115 /* Reconstruct all points using found projection matrices */ 1116 icvReconstructPointsFor3View( &resProjMatrs[0],&resProjMatrs[1],&resProjMatrs[2], 1117 points[0], points[1], points[2], 1118 reconPoints4D); 1119 1120 /* Project points to images using projection matrices */ 1121 icvProject4DPoints(reconPoints4D,&resProjMatrs[0],tmpProjPoints[0]); 1122 icvProject4DPoints(reconPoints4D,&resProjMatrs[1],tmpProjPoints[1]); 1123 icvProject4DPoints(reconPoints4D,&resProjMatrs[2],tmpProjPoints[2]); 1124 1125 1126 /* Compute error for each point and select good */ 1127 1128 int currImage; 1129 finalGoodPoints = 0; 1130 for( i = 0; i < numPoints; i++ ) 1131 { 1132 double dist=-1; 1133 /* Choose max distance for each of three points */ 1134 for( currImage = 0; currImage < 3; currImage++ ) 1135 { 1136 double x1,y1,x2,y2; 1137 x1 = cvmGet(tmpProjPoints[currImage],0,i); 1138 y1 = cvmGet(tmpProjPoints[currImage],1,i); 1139 x2 = cvmGet(points[currImage],0,i); 1140 y2 = cvmGet(points[currImage],1,i); 1141 1142 double dx,dy; 1143 dx = x1-x2; 1144 dy = y1-y2; 1145 1146 double newDist = dx*dx+dy*dy; 1147 if( newDist > dist ) 1148 { 1149 dist = newDist; 1150 } 1151 } 1152 dist = sqrt(dist); 1153 goodFlags[i] = (char)(dist > threshold ? 0 : 1); 1154 finalGoodPoints += goodFlags[i]; 1155 } 1156 1157 char str[200]; 1158 sprintf(str,"Was num = %d\nNew num=%d",maxGoodPoints,finalGoodPoints); 1159 MessageBox(0,str,"Info",MB_OK|MB_TASKMODAL); 1160 if( finalGoodPoints > maxGoodPoints ) 1161 { 1162 /* Copy new version of projection matrices */ 1163 cvCopy(&resProjMatrs[0],&bestProjMatrs[0]); 1164 cvCopy(&resProjMatrs[1],&bestProjMatrs[1]); 1165 cvCopy(&resProjMatrs[2],&bestProjMatrs[2]); 1166 memcpy(bestFlags,goodFlags,numPoints*sizeof(char)); 1167 maxGoodPoints = finalGoodPoints; 1168 } 1169 1170 cvReleaseMat(&optStatus); 1171 cvReleaseMat(&resPoints4D); 1172 #else 1173 /* Version with using status for Levenberd-Marquardt minimization */ 1174 1175 /* Create status */ 1176 CvMat *optStatus; 1177 optStatus = cvCreateMat(1,numPoints,CV_64F); 1178 for( i=0;i<numPoints;i++ ) 1179 { 1180 cvmSet(optStatus,0,i,(double)bestFlags[i]); 1181 } 1182 1183 CvMat *pointsPres[3]; 1184 pointsPres[0] = optStatus; 1185 pointsPres[1] = optStatus; 1186 pointsPres[2] = optStatus; 1187 1188 /* Create 4D points array for good points */ 1189 CvMat *resPoints4D; 1190 resPoints4D = cvCreateMat(4,numPoints,CV_64F); 1191 1192 CvMat* projMs[3]; 1193 1194 projMs[0] = &bestProjMatrs[0]; 1195 projMs[1] = &bestProjMatrs[1]; 1196 projMs[2] = &bestProjMatrs[2]; 1197 1198 CvMat resProjMatrs[3]; 1199 double resProjMatrs_dat[36]; 1200 resProjMatrs[0] = cvMat(3,4,CV_64F,resProjMatrs_dat); 1201 resProjMatrs[1] = cvMat(3,4,CV_64F,resProjMatrs_dat+12); 1202 resProjMatrs[2] = cvMat(3,4,CV_64F,resProjMatrs_dat+24); 1203 1204 CvMat* resMatrs[3]; 1205 resMatrs[0] = &resProjMatrs[0]; 1206 resMatrs[1] = &resProjMatrs[1]; 1207 resMatrs[2] = &resProjMatrs[2]; 1208 1209 cvOptimizeLevenbergMarquardtBundle( projMs,//projMs, 1210 points,//points2D, 1211 pointsPres,//pointsPres, 1212 3, 1213 resMatrs,//resProjMatrs, 1214 resPoints4D,//resPoints4D, 1215 100, 1e-9 ); 1216 1217 /* We found optimized projection matrices */ 1218 1219 reconPoints4D = cvCreateMat(4,numPoints,CV_64F); 1220 1221 /* Reconstruct all points using found projection matrices */ 1222 icvReconstructPointsFor3View( &resProjMatrs[0],&resProjMatrs[1],&resProjMatrs[2], 1223 points[0], points[1], points[2], 1224 reconPoints4D); 1225 1226 /* Project points to images using projection matrices */ 1227 icvProject4DPoints(reconPoints4D,&resProjMatrs[0],tmpProjPoints[0]); 1228 icvProject4DPoints(reconPoints4D,&resProjMatrs[1],tmpProjPoints[1]); 1229 icvProject4DPoints(reconPoints4D,&resProjMatrs[2],tmpProjPoints[2]); 1230 1231 1232 /* Compute error for each point and select good */ 1233 1234 int currImage; 1235 finalGoodPoints = 0; 1236 for( i = 0; i < numPoints; i++ ) 1237 { 1238 double dist=-1; 1239 /* Choose max distance for each of three points */ 1240 for( currImage = 0; currImage < 3; currImage++ ) 1241 { 1242 double x1,y1,x2,y2; 1243 x1 = cvmGet(tmpProjPoints[currImage],0,i); 1244 y1 = cvmGet(tmpProjPoints[currImage],1,i); 1245 x2 = cvmGet(points[currImage],0,i); 1246 y2 = cvmGet(points[currImage],1,i); 1247 1248 double dx,dy; 1249 dx = x1-x2; 1250 dy = y1-y2; 1251 1252 double newDist = dx*dx+dy*dy; 1253 if( newDist > dist ) 1254 { 1255 dist = newDist; 1256 } 1257 } 1258 dist = sqrt(dist); 1259 goodFlags[i] = (char)(dist > threshold ? 0 : 1); 1260 finalGoodPoints += goodFlags[i]; 1261 } 1262 1263 /*char str[200]; 1264 sprintf(str,"Was num = %d\nNew num=%d",maxGoodPoints,finalGoodPoints); 1265 MessageBox(0,str,"Info",MB_OK|MB_TASKMODAL);*/ 1266 1267 needRepeat = 0; 1268 if( finalGoodPoints > maxGoodPoints ) 1269 { 1270 /* Copy new version of projection matrices */ 1271 cvCopy(&resProjMatrs[0],&bestProjMatrs[0]); 1272 cvCopy(&resProjMatrs[1],&bestProjMatrs[1]); 1273 cvCopy(&resProjMatrs[2],&bestProjMatrs[2]); 1274 memcpy(bestFlags,goodFlags,numPoints*sizeof(char)); 1275 maxGoodPoints = finalGoodPoints; 1276 needRepeat = 1; 1277 } 1278 1279 cvReleaseMat(&optStatus); 1280 cvReleaseMat(&resPoints4D); 1281 1282 1283 #endif 1284 } while ( needRepeat ); 1285 1286 cvFree( &goodFlags); 1287 1288 1289 1290 1291 numProjMatrs = 1; 1292 1293 /* Copy projection matrices */ 1294 cvConvert(&bestProjMatrs[0],projMatr1); 1295 cvConvert(&bestProjMatrs[1],projMatr2); 1296 cvConvert(&bestProjMatrs[2],projMatr3); 1297 1298 if( status ) 1299 { 1300 /* copy status for each points if need */ 1301 for( int i = 0; i < numPoints; i++) 1302 { 1303 cvmSet(status,0,i,(double)bestFlags[i]); 1304 } 1305 } 1306 } 1307 } 1308 1309 if( points4D ) 1310 {/* Fill reconstructed points */ 1311 1312 cvZero(points4D); 1313 icvReconstructPointsFor3View( projMatr1,projMatr2,projMatr3, 1314 points[0], points[1], points[2], 1315 points4D); 1316 } 1317 1318 1319 1320 __END__; 1321 1322 cvFree( &flags); 1323 cvFree( &bestFlags); 1324 1325 cvReleaseMat(&recPoints4D); 1326 cvReleaseMat(&tmpProjPoints[0]); 1327 cvReleaseMat(&tmpProjPoints[1]); 1328 cvReleaseMat(&tmpProjPoints[2]); 1329 1330 return numProjMatrs; 1331 } 1332 1333 /*==========================================================================================*/ 1334 1335 void icvFindBaseTransform(CvMat* points,CvMat* resultT) 1336 { 1337 1338 CV_FUNCNAME( "icvFindBaseTransform" ); 1339 __BEGIN__; 1340 1341 if( points == 0 || resultT == 0 ) 1342 { 1343 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 1344 } 1345 1346 if( !CV_IS_MAT(points) || !CV_IS_MAT(resultT) ) 1347 { 1348 CV_ERROR( CV_StsUnsupportedFormat, "points and resultT must be a matrices" ); 1349 } 1350 1351 if( points->rows != 2 || points->cols != 4 ) 1352 { 1353 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be 4. And they must have 2 coordinates" ); 1354 } 1355 1356 if( resultT->rows != 3 || resultT->cols != 3 ) 1357 { 1358 CV_ERROR( CV_StsUnmatchedSizes, "size of matrix resultT must be 3x3" ); 1359 } 1360 1361 /* Function gets four points and compute transformation to e1=(100) e2=(010) e3=(001) e4=(111) */ 1362 1363 /* !!! test each three points not collinear. Need to test */ 1364 1365 /* Create matrices */ 1366 CvMat matrA; 1367 CvMat vectB; 1368 double matrA_dat[3*3]; 1369 double vectB_dat[3]; 1370 matrA = cvMat(3,3,CV_64F,matrA_dat); 1371 vectB = cvMat(3,1,CV_64F,vectB_dat); 1372 1373 /* fill matrices */ 1374 int i; 1375 for( i = 0; i < 3; i++ ) 1376 { 1377 cvmSet(&matrA,0,i,cvmGet(points,0,i)); 1378 cvmSet(&matrA,1,i,cvmGet(points,1,i)); 1379 cvmSet(&matrA,2,i,1); 1380 } 1381 1382 /* Fill vector B */ 1383 cvmSet(&vectB,0,0,cvmGet(points,0,3)); 1384 cvmSet(&vectB,1,0,cvmGet(points,1,3)); 1385 cvmSet(&vectB,2,0,1); 1386 1387 /* result scale */ 1388 CvMat scale; 1389 double scale_dat[3]; 1390 scale = cvMat(3,1,CV_64F,scale_dat); 1391 1392 cvSolve(&matrA,&vectB,&scale,CV_SVD); 1393 1394 /* multiply by scale */ 1395 int j; 1396 for( j = 0; j < 3; j++ ) 1397 { 1398 double sc = scale_dat[j]; 1399 for( i = 0; i < 3; i++ ) 1400 { 1401 matrA_dat[i*3+j] *= sc; 1402 } 1403 } 1404 1405 /* Convert inverse matrix */ 1406 CvMat tmpRes; 1407 double tmpRes_dat[9]; 1408 tmpRes = cvMat(3,3,CV_64F,tmpRes_dat); 1409 cvInvert(&matrA,&tmpRes); 1410 1411 cvConvert(&tmpRes,resultT); 1412 1413 __END__; 1414 1415 return; 1416 } 1417 1418 1419 /*==========================================================================================*/ 1420 void GetGeneratorReduceFundSolution(CvMat* points1,CvMat* points2,CvMat* fundReduceCoef1,CvMat* fundReduceCoef2) 1421 { 1422 1423 CV_FUNCNAME( "GetGeneratorReduceFundSolution" ); 1424 __BEGIN__; 1425 1426 /* Test input data for errors */ 1427 1428 if( points1 == 0 || points2 == 0 || fundReduceCoef1 == 0 || fundReduceCoef2 == 0) 1429 { 1430 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 1431 } 1432 1433 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2) || !CV_IS_MAT(fundReduceCoef1) || !CV_IS_MAT(fundReduceCoef2) ) 1434 { 1435 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" ); 1436 } 1437 1438 1439 1440 if( points1->rows != 3 || points1->cols != 3 ) 1441 { 1442 CV_ERROR( CV_StsUnmatchedSizes, "Number of points1 must be 3 and and have 3 coordinates" ); 1443 } 1444 1445 if( points2->rows != 3 || points2->cols != 3 ) 1446 { 1447 CV_ERROR( CV_StsUnmatchedSizes, "Number of points2 must be 3 and and have 3 coordinates" ); 1448 } 1449 1450 if( fundReduceCoef1->rows != 1 || fundReduceCoef1->cols != 5 ) 1451 { 1452 CV_ERROR( CV_StsUnmatchedSizes, "Size of fundReduceCoef1 must be 1x5" ); 1453 } 1454 1455 if( fundReduceCoef2->rows != 1 || fundReduceCoef2->cols != 5 ) 1456 { 1457 CV_ERROR( CV_StsUnmatchedSizes, "Size of fundReduceCoef2 must be 1x5" ); 1458 } 1459 1460 /* Using 3 corr. points compute reduce */ 1461 1462 /* Create matrix */ 1463 CvMat matrA; 1464 double matrA_dat[3*5]; 1465 matrA = cvMat(3,5,CV_64F,matrA_dat); 1466 int i; 1467 for( i = 0; i < 3; i++ ) 1468 { 1469 double x1,y1,w1,x2,y2,w2; 1470 x1 = cvmGet(points1,0,i); 1471 y1 = cvmGet(points1,1,i); 1472 w1 = cvmGet(points1,2,i); 1473 1474 x2 = cvmGet(points2,0,i); 1475 y2 = cvmGet(points2,1,i); 1476 w2 = cvmGet(points2,2,i); 1477 1478 cvmSet(&matrA,i,0,y1*x2-y1*w2); 1479 cvmSet(&matrA,i,1,w1*x2-y1*w2); 1480 cvmSet(&matrA,i,2,x1*y2-y1*w2); 1481 cvmSet(&matrA,i,3,w1*y2-y1*w2); 1482 cvmSet(&matrA,i,4,x1*w2-y1*w2); 1483 } 1484 1485 /* solve system using svd */ 1486 CvMat matrU; 1487 CvMat matrW; 1488 CvMat matrV; 1489 1490 double matrU_dat[3*3]; 1491 double matrW_dat[3*5]; 1492 double matrV_dat[5*5]; 1493 1494 matrU = cvMat(3,3,CV_64F,matrU_dat); 1495 matrW = cvMat(3,5,CV_64F,matrW_dat); 1496 matrV = cvMat(5,5,CV_64F,matrV_dat); 1497 1498 /* From svd we need just two last vectors of V or two last row V' */ 1499 /* We get transposed matrixes U and V */ 1500 1501 cvSVD(&matrA,&matrW,0,&matrV,CV_SVD_V_T); 1502 1503 /* copy results to fundamental matrices */ 1504 for(i=0;i<5;i++) 1505 { 1506 cvmSet(fundReduceCoef1,0,i,cvmGet(&matrV,3,i)); 1507 cvmSet(fundReduceCoef2,0,i,cvmGet(&matrV,4,i)); 1508 } 1509 1510 __END__; 1511 return; 1512 1513 } 1514 1515 /*==========================================================================================*/ 1516 1517 int GetGoodReduceFundamMatrFromTwo(CvMat* fundReduceCoef1,CvMat* fundReduceCoef2,CvMat* resFundReduceCoef) 1518 { 1519 int numRoots = 0; 1520 1521 CV_FUNCNAME( "GetGoodReduceFundamMatrFromTwo" ); 1522 __BEGIN__; 1523 1524 if( fundReduceCoef1 == 0 || fundReduceCoef2 == 0 || resFundReduceCoef == 0 ) 1525 { 1526 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 1527 } 1528 1529 if( !CV_IS_MAT(fundReduceCoef1) || !CV_IS_MAT(fundReduceCoef2) || !CV_IS_MAT(resFundReduceCoef) ) 1530 { 1531 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" ); 1532 } 1533 1534 /* using two fundamental matrix comute matrixes for det(F)=0 */ 1535 /* May compute 1 or 3 matrices. Returns number of solutions */ 1536 /* Here we will use case F=a*F1+(1-a)*F2 instead of F=m*F1+l*F2 */ 1537 1538 /* Test for errors */ 1539 if( fundReduceCoef1->rows != 1 || fundReduceCoef1->cols != 5 ) 1540 { 1541 CV_ERROR( CV_StsUnmatchedSizes, "Size of fundReduceCoef1 must be 1x5" ); 1542 } 1543 1544 if( fundReduceCoef2->rows != 1 || fundReduceCoef2->cols != 5 ) 1545 { 1546 CV_ERROR( CV_StsUnmatchedSizes, "Size of fundReduceCoef2 must be 1x5" ); 1547 } 1548 1549 if( (resFundReduceCoef->rows != 1 && resFundReduceCoef->rows != 3) || resFundReduceCoef->cols != 5 ) 1550 { 1551 CV_ERROR( CV_StsUnmatchedSizes, "Size of resFundReduceCoef must be 1x5" ); 1552 } 1553 1554 double p1,q1,r1,s1,t1; 1555 double p2,q2,r2,s2,t2; 1556 p1 = cvmGet(fundReduceCoef1,0,0); 1557 q1 = cvmGet(fundReduceCoef1,0,1); 1558 r1 = cvmGet(fundReduceCoef1,0,2); 1559 s1 = cvmGet(fundReduceCoef1,0,3); 1560 t1 = cvmGet(fundReduceCoef1,0,4); 1561 1562 p2 = cvmGet(fundReduceCoef2,0,0); 1563 q2 = cvmGet(fundReduceCoef2,0,1); 1564 r2 = cvmGet(fundReduceCoef2,0,2); 1565 s2 = cvmGet(fundReduceCoef2,0,3); 1566 t2 = cvmGet(fundReduceCoef2,0,4); 1567 1568 /* solve equation */ 1569 CvMat result; 1570 CvMat coeffs; 1571 double result_dat[2*3]; 1572 double coeffs_dat[4]; 1573 result = cvMat(2,3,CV_64F,result_dat); 1574 coeffs = cvMat(1,4,CV_64F,coeffs_dat); 1575 1576 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 */ 1577 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 */ 1578 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 */ 1579 coeffs_dat[3] = r2*(-p2-q2-r2-s2-t2)*q2+p2*s2*t2;/* 1 */ 1580 1581 int num; 1582 num = cvSolveCubic(&coeffs,&result); 1583 1584 1585 /* test number of solutions and test for real solutions */ 1586 int i; 1587 for( i = 0; i < num; i++ ) 1588 { 1589 if( fabs(cvmGet(&result,1,i)) < 1e-8 ) 1590 { 1591 double alpha = cvmGet(&result,0,i); 1592 int j; 1593 for( j = 0; j < 5; j++ ) 1594 { 1595 cvmSet(resFundReduceCoef,numRoots,j, 1596 alpha * cvmGet(fundReduceCoef1,0,j) + (1-alpha) * cvmGet(fundReduceCoef2,0,j) ); 1597 } 1598 numRoots++; 1599 } 1600 } 1601 1602 __END__; 1603 return numRoots; 1604 } 1605 1606 /*==========================================================================================*/ 1607 1608 void GetProjMatrFromReducedFundamental(CvMat* fundReduceCoefs,CvMat* projMatrCoefs) 1609 { 1610 CV_FUNCNAME( "GetProjMatrFromReducedFundamental" ); 1611 __BEGIN__; 1612 1613 /* Test for errors */ 1614 if( fundReduceCoefs == 0 || projMatrCoefs == 0 ) 1615 { 1616 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 1617 } 1618 1619 if( !CV_IS_MAT(fundReduceCoefs) || !CV_IS_MAT(projMatrCoefs) ) 1620 { 1621 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" ); 1622 } 1623 1624 1625 if( fundReduceCoefs->rows != 1 || fundReduceCoefs->cols != 5 ) 1626 { 1627 CV_ERROR( CV_StsUnmatchedSizes, "Size of fundReduceCoefs must be 1x5" ); 1628 } 1629 1630 if( projMatrCoefs->rows != 1 || projMatrCoefs->cols != 4 ) 1631 { 1632 CV_ERROR( CV_StsUnmatchedSizes, "Size of projMatrCoefs must be 1x4" ); 1633 } 1634 1635 /* Computes project matrix from given reduced matrix */ 1636 /* we have p,q,r,s,t and need get a,b,c,d */ 1637 /* Fill matrix to compute ratio a:b:c as A:B:C */ 1638 1639 CvMat matrA; 1640 double matrA_dat[3*3]; 1641 matrA = cvMat(3,3,CV_64F,matrA_dat); 1642 1643 double p,q,r,s,t; 1644 p = cvmGet(fundReduceCoefs,0,0); 1645 q = cvmGet(fundReduceCoefs,0,1); 1646 r = cvmGet(fundReduceCoefs,0,2); 1647 s = cvmGet(fundReduceCoefs,0,3); 1648 t = cvmGet(fundReduceCoefs,0,4); 1649 1650 matrA_dat[0] = p; 1651 matrA_dat[1] = r; 1652 matrA_dat[2] = 0; 1653 1654 matrA_dat[3] = q; 1655 matrA_dat[4] = 0; 1656 matrA_dat[5] = t; 1657 1658 matrA_dat[6] = 0; 1659 matrA_dat[7] = s; 1660 matrA_dat[8] = -(p+q+r+s+t); 1661 1662 CvMat matrU; 1663 CvMat matrW; 1664 CvMat matrV; 1665 1666 double matrU_dat[3*3]; 1667 double matrW_dat[3*3]; 1668 double matrV_dat[3*3]; 1669 1670 matrU = cvMat(3,3,CV_64F,matrU_dat); 1671 matrW = cvMat(3,3,CV_64F,matrW_dat); 1672 matrV = cvMat(3,3,CV_64F,matrV_dat); 1673 1674 /* From svd we need just last vector of V or last row V' */ 1675 /* We get transposed matrixes U and V */ 1676 1677 cvSVD(&matrA,&matrW,0,&matrV,CV_SVD_V_T); 1678 1679 double A1,B1,C1; 1680 A1 = matrV_dat[6]; 1681 B1 = matrV_dat[7]; 1682 C1 = matrV_dat[8]; 1683 1684 /* Get second coeffs */ 1685 matrA_dat[0] = 0; 1686 matrA_dat[1] = r; 1687 matrA_dat[2] = t; 1688 1689 matrA_dat[3] = p; 1690 matrA_dat[4] = 0; 1691 matrA_dat[5] = -(p+q+r+s+t); 1692 1693 matrA_dat[6] = q; 1694 matrA_dat[7] = s; 1695 matrA_dat[8] = 0; 1696 1697 cvSVD(&matrA,&matrW,0,&matrV,CV_SVD_V_T); 1698 1699 double A2,B2,C2; 1700 A2 = matrV_dat[6]; 1701 B2 = matrV_dat[7]; 1702 C2 = matrV_dat[8]; 1703 1704 double a,b,c,d; 1705 { 1706 CvMat matrK; 1707 double matrK_dat[36]; 1708 matrK = cvMat(6,6,CV_64F,matrK_dat); 1709 cvZero(&matrK); 1710 1711 matrK_dat[0] = 1; 1712 matrK_dat[7] = 1; 1713 matrK_dat[14] = 1; 1714 1715 matrK_dat[18] = -1; 1716 matrK_dat[25] = -1; 1717 matrK_dat[32] = -1; 1718 1719 matrK_dat[21] = 1; 1720 matrK_dat[27] = 1; 1721 matrK_dat[33] = 1; 1722 1723 matrK_dat[0*6+4] = -A1; 1724 matrK_dat[1*6+4] = -B1; 1725 matrK_dat[2*6+4] = -C1; 1726 1727 matrK_dat[3*6+5] = -A2; 1728 matrK_dat[4*6+5] = -B2; 1729 matrK_dat[5*6+5] = -C2; 1730 1731 CvMat matrU; 1732 CvMat matrW; 1733 CvMat matrV; 1734 1735 double matrU_dat[36]; 1736 double matrW_dat[36]; 1737 double matrV_dat[36]; 1738 1739 matrU = cvMat(6,6,CV_64F,matrU_dat); 1740 matrW = cvMat(6,6,CV_64F,matrW_dat); 1741 matrV = cvMat(6,6,CV_64F,matrV_dat); 1742 1743 /* From svd we need just last vector of V or last row V' */ 1744 /* We get transposed matrixes U and V */ 1745 1746 cvSVD(&matrK,&matrW,0,&matrV,CV_SVD_V_T); 1747 1748 a = matrV_dat[6*5+0]; 1749 b = matrV_dat[6*5+1]; 1750 c = matrV_dat[6*5+2]; 1751 d = matrV_dat[6*5+3]; 1752 /* we don't need last two coefficients. Because it just a k1,k2 */ 1753 1754 cvmSet(projMatrCoefs,0,0,a); 1755 cvmSet(projMatrCoefs,0,1,b); 1756 cvmSet(projMatrCoefs,0,2,c); 1757 cvmSet(projMatrCoefs,0,3,d); 1758 1759 } 1760 1761 __END__; 1762 return; 1763 } 1764 1765 /*==========================================================================================*/ 1766 1767 void icvComputeProjectMatrix(CvMat* objPoints,CvMat* projPoints,CvMat* projMatr) 1768 {/* Using SVD method */ 1769 1770 /* Reconstruct points using object points and projected points */ 1771 /* Number of points must be >=6 */ 1772 1773 CvMat matrV; 1774 CvMat* matrA = 0; 1775 CvMat* matrW = 0; 1776 CvMat* workProjPoints = 0; 1777 CvMat* tmpProjPoints = 0; 1778 1779 CV_FUNCNAME( "icvComputeProjectMatrix" ); 1780 __BEGIN__; 1781 1782 /* Test for errors */ 1783 if( objPoints == 0 || projPoints == 0 || projMatr == 0) 1784 { 1785 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 1786 } 1787 1788 if( !CV_IS_MAT(objPoints) || !CV_IS_MAT(projPoints) || !CV_IS_MAT(projMatr) ) 1789 { 1790 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" ); 1791 } 1792 1793 if( projMatr->rows != 3 || projMatr->cols != 4 ) 1794 { 1795 CV_ERROR( CV_StsUnmatchedSizes, "Size of projMatr must be 3x4" ); 1796 } 1797 1798 int numPoints; 1799 numPoints = projPoints->cols; 1800 if( numPoints < 6 ) 1801 { 1802 CV_ERROR( CV_StsOutOfRange, "Number of points must be at least 6" ); 1803 } 1804 1805 if( numPoints != objPoints->cols ) 1806 { 1807 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be same" ); 1808 } 1809 1810 if( objPoints->rows != 4 ) 1811 { 1812 CV_ERROR( CV_StsUnmatchedSizes, "Object points must have 4 coordinates" ); 1813 } 1814 1815 if( projPoints->rows != 3 && projPoints->rows != 2 ) 1816 { 1817 CV_ERROR( CV_StsUnmatchedSizes, "Projected points must have 2 or 3 coordinates" ); 1818 } 1819 1820 /* Create and fill matrix A */ 1821 CV_CALL( matrA = cvCreateMat(numPoints*3, 12, CV_64F) ); 1822 CV_CALL( matrW = cvCreateMat(numPoints*3, 12, CV_64F) ); 1823 1824 if( projPoints->rows == 2 ) 1825 { 1826 CV_CALL( tmpProjPoints = cvCreateMat(3,numPoints,CV_64F) ); 1827 cvMake3DPoints(projPoints,tmpProjPoints); 1828 workProjPoints = tmpProjPoints; 1829 } 1830 else 1831 { 1832 workProjPoints = projPoints; 1833 } 1834 1835 double matrV_dat[144]; 1836 matrV = cvMat(12,12,CV_64F,matrV_dat); 1837 int i; 1838 1839 char* dat; 1840 dat = (char*)(matrA->data.db); 1841 1842 #if 1 1843 FILE *file; 1844 file = fopen("d:\\test\\recProjMatr.txt","w"); 1845 1846 #endif 1847 for( i = 0;i < numPoints; i++ ) 1848 { 1849 double x,y,w; 1850 double X,Y,Z,W; 1851 double* matrDat = (double*)dat; 1852 1853 x = cvmGet(workProjPoints,0,i); 1854 y = cvmGet(workProjPoints,1,i); 1855 w = cvmGet(workProjPoints,2,i); 1856 1857 1858 X = cvmGet(objPoints,0,i); 1859 Y = cvmGet(objPoints,1,i); 1860 Z = cvmGet(objPoints,2,i); 1861 W = cvmGet(objPoints,3,i); 1862 1863 #if 1 1864 fprintf(file,"%d (%lf %lf %lf %lf) - (%lf %lf %lf)\n",i,X,Y,Z,W,x,y,w ); 1865 #endif 1866 1867 /*---*/ 1868 matrDat[ 0] = 0; 1869 matrDat[ 1] = 0; 1870 matrDat[ 2] = 0; 1871 matrDat[ 3] = 0; 1872 1873 matrDat[ 4] = -w*X; 1874 matrDat[ 5] = -w*Y; 1875 matrDat[ 6] = -w*Z; 1876 matrDat[ 7] = -w*W; 1877 1878 matrDat[ 8] = y*X; 1879 matrDat[ 9] = y*Y; 1880 matrDat[10] = y*Z; 1881 matrDat[11] = y*W; 1882 /*---*/ 1883 matrDat[12] = w*X; 1884 matrDat[13] = w*Y; 1885 matrDat[14] = w*Z; 1886 matrDat[15] = w*W; 1887 1888 matrDat[16] = 0; 1889 matrDat[17] = 0; 1890 matrDat[18] = 0; 1891 matrDat[19] = 0; 1892 1893 matrDat[20] = -x*X; 1894 matrDat[21] = -x*Y; 1895 matrDat[22] = -x*Z; 1896 matrDat[23] = -x*W; 1897 /*---*/ 1898 matrDat[24] = -y*X; 1899 matrDat[25] = -y*Y; 1900 matrDat[26] = -y*Z; 1901 matrDat[27] = -y*W; 1902 1903 matrDat[28] = x*X; 1904 matrDat[29] = x*Y; 1905 matrDat[30] = x*Z; 1906 matrDat[31] = x*W; 1907 1908 matrDat[32] = 0; 1909 matrDat[33] = 0; 1910 matrDat[34] = 0; 1911 matrDat[35] = 0; 1912 /*---*/ 1913 dat += (matrA->step)*3; 1914 } 1915 #if 1 1916 fclose(file); 1917 1918 #endif 1919 1920 /* Solve this system */ 1921 1922 /* From svd we need just last vector of V or last row V' */ 1923 /* We get transposed matrix V */ 1924 1925 cvSVD(matrA,matrW,0,&matrV,CV_SVD_V_T); 1926 1927 /* projected matrix was computed */ 1928 for( i = 0; i < 12; i++ ) 1929 { 1930 cvmSet(projMatr,i/4,i%4,cvmGet(&matrV,11,i)); 1931 } 1932 1933 cvReleaseMat(&matrA); 1934 cvReleaseMat(&matrW); 1935 cvReleaseMat(&tmpProjPoints); 1936 __END__; 1937 } 1938 1939 1940 /*==========================================================================================*/ 1941 /* May be useless function */ 1942 void icvComputeTransform4D(CvMat* points1,CvMat* points2,CvMat* transMatr) 1943 { 1944 CvMat* matrA = 0; 1945 CvMat* matrW = 0; 1946 1947 double matrV_dat[256]; 1948 CvMat matrV = cvMat(16,16,CV_64F,matrV_dat); 1949 1950 CV_FUNCNAME( "icvComputeTransform4D" ); 1951 __BEGIN__; 1952 1953 if( points1 == 0 || points2 == 0 || transMatr == 0) 1954 { 1955 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 1956 } 1957 1958 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2) || !CV_IS_MAT(transMatr) ) 1959 { 1960 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" ); 1961 } 1962 1963 /* Computes transformation matrix (4x4) for points1 -> points2 */ 1964 /* p2=H*p1 */ 1965 1966 /* Test for errors */ 1967 int numPoints; 1968 numPoints = points1->cols; 1969 1970 /* we must have at least 5 points */ 1971 if( numPoints < 5 ) 1972 { 1973 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be at least 5" ); 1974 } 1975 1976 if( numPoints != points2->cols ) 1977 { 1978 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be the same" ); 1979 } 1980 1981 if( transMatr->rows != 4 || transMatr->cols != 4 ) 1982 { 1983 CV_ERROR( CV_StsUnmatchedSizes, "Size of transMatr must be 4x4" ); 1984 } 1985 1986 if( points1->rows != 4 || points2->rows != 4 ) 1987 { 1988 CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of points must be 4" ); 1989 } 1990 1991 /* Create matrix */ 1992 CV_CALL( matrA = cvCreateMat(6*numPoints,16,CV_64F) ); 1993 CV_CALL( matrW = cvCreateMat(6*numPoints,16,CV_64F) ); 1994 1995 cvZero(matrA); 1996 1997 /* Fill matrices */ 1998 int i; 1999 for( i = 0; i < numPoints; i++ )/* For each point */ 2000 { 2001 double X1,Y1,Z1,W1; 2002 double P[4]; 2003 2004 P[0] = cvmGet(points1,0,i); 2005 P[1] = cvmGet(points1,1,i); 2006 P[2] = cvmGet(points1,2,i); 2007 P[3] = cvmGet(points1,3,i); 2008 2009 X1 = cvmGet(points2,0,i); 2010 Y1 = cvmGet(points2,1,i); 2011 Z1 = cvmGet(points2,2,i); 2012 W1 = cvmGet(points2,3,i); 2013 2014 /* Fill matrA */ 2015 for( int j = 0; j < 4; j++ )/* For each coordinate */ 2016 { 2017 double x,y,z,w; 2018 2019 x = X1*P[j]; 2020 y = Y1*P[j]; 2021 z = Z1*P[j]; 2022 w = W1*P[j]; 2023 2024 cvmSet(matrA,6*i+0,4*0+j,y); 2025 cvmSet(matrA,6*i+0,4*1+j,-x); 2026 2027 cvmSet(matrA,6*i+1,4*0+j,z); 2028 cvmSet(matrA,6*i+1,4*2+j,-x); 2029 2030 cvmSet(matrA,6*i+2,4*0+j,w); 2031 cvmSet(matrA,6*i+2,4*3+j,-x); 2032 2033 cvmSet(matrA,6*i+3,4*1+j,-z); 2034 cvmSet(matrA,6*i+3,4*2+j,y); 2035 2036 cvmSet(matrA,6*i+4,4*1+j,-w); 2037 cvmSet(matrA,6*i+4,4*3+j,y); 2038 2039 cvmSet(matrA,6*i+5,4*2+j,-w); 2040 cvmSet(matrA,6*i+5,4*3+j,z); 2041 } 2042 } 2043 2044 /* From svd we need just two last vectors of V or two last row V' */ 2045 /* We get transposed matrixes U and V */ 2046 2047 cvSVD(matrA,matrW,0,&matrV,CV_SVD_V_T); 2048 2049 /* Copy result to result matrix */ 2050 for( i = 0; i < 16; i++ ) 2051 { 2052 cvmSet(transMatr,i/4,i%4,cvmGet(&matrV,15,i)); 2053 } 2054 2055 cvReleaseMat(&matrA); 2056 cvReleaseMat(&matrW); 2057 2058 __END__; 2059 return; 2060 } 2061 2062 /*==========================================================================================*/ 2063 2064 void icvReconstructPointsFor3View( CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3, 2065 CvMat* projPoints1,CvMat* projPoints2,CvMat* projPoints3, 2066 CvMat* points4D) 2067 { 2068 CV_FUNCNAME( "icvReconstructPointsFor3View" ); 2069 __BEGIN__; 2070 2071 if( projMatr1 == 0 || projMatr2 == 0 || projMatr3 == 0 || 2072 projPoints1 == 0 || projPoints2 == 0 || projPoints3 == 0 || 2073 points4D == 0) 2074 { 2075 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 2076 } 2077 2078 if( !CV_IS_MAT(projMatr1) || !CV_IS_MAT(projMatr2) || !CV_IS_MAT(projMatr3) || 2079 !CV_IS_MAT(projPoints1) || !CV_IS_MAT(projPoints2) || !CV_IS_MAT(projPoints3) || 2080 !CV_IS_MAT(points4D) ) 2081 { 2082 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" ); 2083 } 2084 2085 int numPoints; 2086 numPoints = projPoints1->cols; 2087 2088 if( numPoints < 1 ) 2089 { 2090 CV_ERROR( CV_StsOutOfRange, "Number of points must be more than zero" ); 2091 } 2092 2093 if( projPoints2->cols != numPoints || projPoints3->cols != numPoints || points4D->cols != numPoints ) 2094 { 2095 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be the same" ); 2096 } 2097 2098 if( projPoints1->rows != 2 || projPoints2->rows != 2 || projPoints3->rows != 2) 2099 { 2100 CV_ERROR( CV_StsUnmatchedSizes, "Number of proj points coordinates must be == 2" ); 2101 } 2102 2103 if( points4D->rows != 4 ) 2104 { 2105 CV_ERROR( CV_StsUnmatchedSizes, "Number of world points coordinates must be == 4" ); 2106 } 2107 2108 if( projMatr1->cols != 4 || projMatr1->rows != 3 || 2109 projMatr2->cols != 4 || projMatr2->rows != 3 || 2110 projMatr3->cols != 4 || projMatr3->rows != 3) 2111 { 2112 CV_ERROR( CV_StsUnmatchedSizes, "Size of projection matrices must be 3x4" ); 2113 } 2114 2115 CvMat matrA; 2116 double matrA_dat[36]; 2117 matrA = cvMat(9,4,CV_64F,matrA_dat); 2118 2119 //CvMat matrU; 2120 CvMat matrW; 2121 CvMat matrV; 2122 //double matrU_dat[9*9]; 2123 double matrW_dat[9*4]; 2124 double matrV_dat[4*4]; 2125 2126 //matrU = cvMat(9,9,CV_64F,matrU_dat); 2127 matrW = cvMat(9,4,CV_64F,matrW_dat); 2128 matrV = cvMat(4,4,CV_64F,matrV_dat); 2129 2130 CvMat* projPoints[3]; 2131 CvMat* projMatrs[3]; 2132 2133 projPoints[0] = projPoints1; 2134 projPoints[1] = projPoints2; 2135 projPoints[2] = projPoints3; 2136 2137 projMatrs[0] = projMatr1; 2138 projMatrs[1] = projMatr2; 2139 projMatrs[2] = projMatr3; 2140 2141 /* Solve system for each point */ 2142 int i,j; 2143 for( i = 0; i < numPoints; i++ )/* For each point */ 2144 { 2145 /* Fill matrix for current point */ 2146 for( j = 0; j < 3; j++ )/* For each view */ 2147 { 2148 double x,y; 2149 x = cvmGet(projPoints[j],0,i); 2150 y = cvmGet(projPoints[j],1,i); 2151 for( int k = 0; k < 4; k++ ) 2152 { 2153 cvmSet(&matrA, j*3+0, k, x * cvmGet(projMatrs[j],2,k) - cvmGet(projMatrs[j],0,k) ); 2154 cvmSet(&matrA, j*3+1, k, y * cvmGet(projMatrs[j],2,k) - cvmGet(projMatrs[j],1,k) ); 2155 cvmSet(&matrA, j*3+2, k, x * cvmGet(projMatrs[j],1,k) - y * cvmGet(projMatrs[j],0,k) ); 2156 } 2157 } 2158 /* Solve system for current point */ 2159 { 2160 cvSVD(&matrA,&matrW,0,&matrV,CV_SVD_V_T); 2161 2162 /* Copy computed point */ 2163 cvmSet(points4D,0,i,cvmGet(&matrV,3,0));/* X */ 2164 cvmSet(points4D,1,i,cvmGet(&matrV,3,1));/* Y */ 2165 cvmSet(points4D,2,i,cvmGet(&matrV,3,2));/* Z */ 2166 cvmSet(points4D,3,i,cvmGet(&matrV,3,3));/* W */ 2167 } 2168 } 2169 2170 /* Points was reconstructed. Try to reproject points */ 2171 /* We can compute reprojection error if need */ 2172 { 2173 int i; 2174 CvMat point3D; 2175 double point3D_dat[4]; 2176 point3D = cvMat(4,1,CV_64F,point3D_dat); 2177 2178 CvMat point2D; 2179 double point2D_dat[3]; 2180 point2D = cvMat(3,1,CV_64F,point2D_dat); 2181 2182 for( i = 0; i < numPoints; i++ ) 2183 { 2184 double W = cvmGet(points4D,3,i); 2185 2186 point3D_dat[0] = cvmGet(points4D,0,i)/W; 2187 point3D_dat[1] = cvmGet(points4D,1,i)/W; 2188 point3D_dat[2] = cvmGet(points4D,2,i)/W; 2189 point3D_dat[3] = 1; 2190 2191 /* !!! Project this point for each camera */ 2192 for( int currCamera = 0; currCamera < 3; currCamera++ ) 2193 { 2194 cvmMul(projMatrs[currCamera], &point3D, &point2D); 2195 2196 float x,y; 2197 float xr,yr,wr; 2198 x = (float)cvmGet(projPoints[currCamera],0,i); 2199 y = (float)cvmGet(projPoints[currCamera],1,i); 2200 2201 wr = (float)point2D_dat[2]; 2202 xr = (float)(point2D_dat[0]/wr); 2203 yr = (float)(point2D_dat[1]/wr); 2204 2205 float deltaX,deltaY; 2206 deltaX = (float)fabs(x-xr); 2207 deltaY = (float)fabs(y-yr); 2208 } 2209 } 2210 } 2211 2212 __END__; 2213 return; 2214 } 2215 2216 2217 2218 2219 #if 0 2220 void ReconstructPointsFor3View_bySolve( CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3, 2221 CvMat* projPoints1,CvMat* projPoints2,CvMat* projPoints3, 2222 CvMat* points3D) 2223 { 2224 CV_FUNCNAME( "ReconstructPointsFor3View" ); 2225 __BEGIN__; 2226 2227 2228 int numPoints; 2229 numPoints = projPoints1->cols; 2230 if( projPoints2->cols != numPoints || projPoints3->cols != numPoints || points3D->cols != numPoints ) 2231 { 2232 CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be the same" ); 2233 } 2234 2235 if( projPoints1->rows != 2 || projPoints2->rows != 2 || projPoints3->rows != 2) 2236 { 2237 CV_ERROR( CV_StsUnmatchedSizes, "Number of proj points coordinates must be == 2" ); 2238 } 2239 2240 if( points3D->rows != 4 ) 2241 { 2242 CV_ERROR( CV_StsUnmatchedSizes, "Number of world points coordinates must be == 4" ); 2243 } 2244 2245 if( projMatr1->cols != 4 || projMatr1->rows != 3 || 2246 projMatr2->cols != 4 || projMatr2->rows != 3 || 2247 projMatr3->cols != 4 || projMatr3->rows != 3) 2248 { 2249 CV_ERROR( CV_StsUnmatchedSizes, "Size of proj matrix must be 3x4" ); 2250 } 2251 2252 CvMat matrA; 2253 double matrA_dat[3*3*3]; 2254 matrA = cvMat(3*3,3,CV_64F,matrA_dat); 2255 2256 CvMat vectB; 2257 double vectB_dat[9]; 2258 vectB = cvMat(9,1,CV_64F,vectB_dat); 2259 2260 CvMat result; 2261 double result_dat[3]; 2262 result = cvMat(3,1,CV_64F,result_dat); 2263 2264 CvMat* projPoints[3]; 2265 CvMat* projMatrs[3]; 2266 2267 projPoints[0] = projPoints1; 2268 projPoints[1] = projPoints2; 2269 projPoints[2] = projPoints3; 2270 2271 projMatrs[0] = projMatr1; 2272 projMatrs[1] = projMatr2; 2273 projMatrs[2] = projMatr3; 2274 2275 /* Solve system for each point */ 2276 int i,j; 2277 for( i = 0; i < numPoints; i++ )/* For each point */ 2278 { 2279 /* Fill matrix for current point */ 2280 for( j = 0; j < 3; j++ )/* For each view */ 2281 { 2282 double x,y; 2283 x = cvmGet(projPoints[j],0,i); 2284 y = cvmGet(projPoints[j],1,i); 2285 2286 cvmSet(&vectB,j*3+0,0,x-cvmGet(projMatrs[j],0,3)); 2287 cvmSet(&vectB,j*3+1,0,y-cvmGet(projMatrs[j],1,3)); 2288 cvmSet(&vectB,j*3+2,0,1-cvmGet(projMatrs[j],2,3)); 2289 2290 for( int t = 0; t < 3; t++ ) 2291 { 2292 for( int k = 0; k < 3; k++ ) 2293 { 2294 cvmSet(&matrA, j*3+t, k, cvmGet(projMatrs[j],t,k) ); 2295 } 2296 } 2297 } 2298 2299 2300 /* Solve system for current point */ 2301 cvSolve(&matrA,&vectB,&result,CV_SVD); 2302 2303 cvmSet(points3D,0,i,result_dat[0]);/* X */ 2304 cvmSet(points3D,1,i,result_dat[1]);/* Y */ 2305 cvmSet(points3D,2,i,result_dat[2]);/* Z */ 2306 cvmSet(points3D,3,i,1);/* W */ 2307 2308 } 2309 2310 /* Points was reconstructed. Try to reproject points */ 2311 { 2312 int i; 2313 CvMat point3D; 2314 double point3D_dat[4]; 2315 point3D = cvMat(4,1,CV_64F,point3D_dat); 2316 2317 CvMat point2D; 2318 double point2D_dat[3]; 2319 point2D = cvMat(3,1,CV_64F,point2D_dat); 2320 2321 for( i = 0; i < numPoints; i++ ) 2322 { 2323 double W = cvmGet(points3D,3,i); 2324 2325 point3D_dat[0] = cvmGet(points3D,0,i)/W; 2326 point3D_dat[1] = cvmGet(points3D,1,i)/W; 2327 point3D_dat[2] = cvmGet(points3D,2,i)/W; 2328 point3D_dat[3] = 1; 2329 2330 /* Project this point for each camera */ 2331 for( int currCamera = 0; currCamera < 3; currCamera++ ) 2332 { 2333 cvmMul(projMatrs[currCamera], &point3D, &point2D); 2334 float x,y; 2335 float xr,yr,wr; 2336 x = (float)cvmGet(projPoints[currCamera],0,i); 2337 y = (float)cvmGet(projPoints[currCamera],1,i); 2338 2339 wr = (float)point2D_dat[2]; 2340 xr = (float)(point2D_dat[0]/wr); 2341 yr = (float)(point2D_dat[1]/wr); 2342 2343 } 2344 } 2345 } 2346 2347 __END__; 2348 return; 2349 } 2350 #endif 2351 2352 /*==========================================================================================*/ 2353 2354 void icvComputeCameraExrinnsicByPosition(CvMat* camPos, CvMat* rotMatr, CvMat* transVect) 2355 { 2356 /* We know position of camera. we must to compute rotate matrix and translate vector */ 2357 2358 CV_FUNCNAME( "icvComputeCameraExrinnsicByPosition" ); 2359 __BEGIN__; 2360 2361 /* Test input paramaters */ 2362 if( camPos == 0 || rotMatr == 0 || transVect == 0 ) 2363 { 2364 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 2365 } 2366 2367 if( !CV_IS_MAT(camPos) || !CV_IS_MAT(rotMatr) || !CV_IS_MAT(transVect) ) 2368 { 2369 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" ); 2370 } 2371 2372 if( camPos->cols != 1 || camPos->rows != 3 ) 2373 { 2374 CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of camera position must be 3x1 vector" ); 2375 } 2376 2377 if( rotMatr->cols != 3 || rotMatr->rows != 3 ) 2378 { 2379 CV_ERROR( CV_StsUnmatchedSizes, "Rotate matrix must be 3x3" ); 2380 } 2381 2382 if( transVect->cols != 1 || transVect->rows != 3 ) 2383 { 2384 CV_ERROR( CV_StsUnmatchedSizes, "Translate vector must be 3x1" ); 2385 } 2386 2387 double x,y,z; 2388 x = cvmGet(camPos,0,0); 2389 y = cvmGet(camPos,1,0); 2390 z = cvmGet(camPos,2,0); 2391 2392 /* Set translate vector. It same as camea position */ 2393 cvmSet(transVect,0,0,x); 2394 cvmSet(transVect,1,0,y); 2395 cvmSet(transVect,2,0,z); 2396 2397 /* Compute rotate matrix. Compute each unit transformed vector */ 2398 2399 /* normalize flat direction x,y */ 2400 double vectorX[3]; 2401 double vectorY[3]; 2402 double vectorZ[3]; 2403 2404 vectorX[0] = -z; 2405 vectorX[1] = 0; 2406 vectorX[2] = x; 2407 2408 vectorY[0] = x*y; 2409 vectorY[1] = x*x+z*z; 2410 vectorY[2] = z*y; 2411 2412 vectorZ[0] = -x; 2413 vectorZ[1] = -y; 2414 vectorZ[2] = -z; 2415 2416 /* normaize vectors */ 2417 double norm; 2418 int i; 2419 2420 /* Norm X */ 2421 norm = 0; 2422 for( i = 0; i < 3; i++ ) 2423 norm += vectorX[i]*vectorX[i]; 2424 norm = sqrt(norm); 2425 for( i = 0; i < 3; i++ ) 2426 vectorX[i] /= norm; 2427 2428 /* Norm Y */ 2429 norm = 0; 2430 for( i = 0; i < 3; i++ ) 2431 norm += vectorY[i]*vectorY[i]; 2432 norm = sqrt(norm); 2433 for( i = 0; i < 3; i++ ) 2434 vectorY[i] /= norm; 2435 2436 /* Norm Z */ 2437 norm = 0; 2438 for( i = 0; i < 3; i++ ) 2439 norm += vectorZ[i]*vectorZ[i]; 2440 norm = sqrt(norm); 2441 for( i = 0; i < 3; i++ ) 2442 vectorZ[i] /= norm; 2443 2444 /* Set output results */ 2445 2446 for( i = 0; i < 3; i++ ) 2447 { 2448 cvmSet(rotMatr,i,0,vectorX[i]); 2449 cvmSet(rotMatr,i,1,vectorY[i]); 2450 cvmSet(rotMatr,i,2,vectorZ[i]); 2451 } 2452 2453 {/* Try to inverse rotate matrix */ 2454 CvMat tmpInvRot; 2455 double tmpInvRot_dat[9]; 2456 tmpInvRot = cvMat(3,3,CV_64F,tmpInvRot_dat); 2457 cvInvert(rotMatr,&tmpInvRot,CV_SVD); 2458 cvConvert(&tmpInvRot,rotMatr); 2459 2460 2461 2462 } 2463 2464 __END__; 2465 2466 return; 2467 } 2468 2469 /*==========================================================================================*/ 2470 2471 void FindTransformForProjectMatrices(CvMat* projMatr1,CvMat* projMatr2,CvMat* rotMatr,CvMat* transVect) 2472 { 2473 /* Computes homography for project matrix be "canonical" form */ 2474 CV_FUNCNAME( "computeProjMatrHomography" ); 2475 __BEGIN__; 2476 2477 /* Test input paramaters */ 2478 if( projMatr1 == 0 || projMatr2 == 0 || rotMatr == 0 || transVect == 0 ) 2479 { 2480 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 2481 } 2482 2483 if( !CV_IS_MAT(projMatr1) || !CV_IS_MAT(projMatr2) || !CV_IS_MAT(rotMatr) || !CV_IS_MAT(transVect) ) 2484 { 2485 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" ); 2486 } 2487 2488 if( projMatr1->cols != 4 || projMatr1->rows != 3 ) 2489 { 2490 CV_ERROR( CV_StsUnmatchedSizes, "Size of project matrix 1 must be 3x4" ); 2491 } 2492 2493 if( projMatr2->cols != 4 || projMatr2->rows != 3 ) 2494 { 2495 CV_ERROR( CV_StsUnmatchedSizes, "Size of project matrix 2 must be 3x4" ); 2496 } 2497 2498 if( rotMatr->cols != 3 || rotMatr->rows != 3 ) 2499 { 2500 CV_ERROR( CV_StsUnmatchedSizes, "Size of rotation matrix must be 3x3" ); 2501 } 2502 2503 if( transVect->cols != 1 || transVect->rows != 3 ) 2504 { 2505 CV_ERROR( CV_StsUnmatchedSizes, "Size of translation vector must be 3x1" ); 2506 } 2507 2508 CvMat matrA; 2509 double matrA_dat[12*12]; 2510 matrA = cvMat(12,12,CV_64F,matrA_dat); 2511 CvMat vectB; 2512 double vectB_dat[12]; 2513 vectB = cvMat(12,1,CV_64F,vectB_dat); 2514 2515 cvZero(&matrA); 2516 cvZero(&vectB); 2517 int i,j; 2518 for( i = 0; i < 12; i++ ) 2519 { 2520 for( j = 0; j < 12; j++ ) 2521 { 2522 cvmSet(&matrA,i,j,cvmGet(projMatr1,i/4,j%4)); 2523 } 2524 /* Fill vector B */ 2525 2526 double val = cvmGet(projMatr2,i/4,i%4); 2527 if( (i+1)%4 == 0 ) 2528 { 2529 val -= cvmGet(projMatr1,i/4,3); 2530 2531 } 2532 cvmSet(&vectB,i,0,val); 2533 } 2534 2535 /* Solve system */ 2536 CvMat resVect; 2537 double resVect_dat[12]; 2538 resVect = cvMat(12,1,CV_64F,resVect_dat); 2539 2540 int sing; 2541 sing = cvSolve(&matrA,&vectB,&resVect); 2542 2543 /* Fill rotation matrix */ 2544 for( i = 0; i < 12; i++ ) 2545 { 2546 double val = cvmGet(&resVect,i,0); 2547 if( i < 9 ) 2548 cvmSet(rotMatr,i%3,i/3,val); 2549 else 2550 cvmSet(transVect,i-9,0,val); 2551 } 2552 2553 __END__; 2554 2555 return; 2556 } 2557 2558 /*==========================================================================================*/ 2559 #if 0 2560 void icvComputeQknowPrincipalPoint(int numImages, CvMat **projMatrs,CvMat *matrQ, double cx,double cy) 2561 { 2562 /* Computes matrix Q */ 2563 /* focal x and y eqauls () */ 2564 /* we know principal point for camera */ 2565 /* focal may differ from image to image */ 2566 /* image skew is 0 */ 2567 2568 if( numImages < 10 ) 2569 { 2570 return; 2571 //Error. Number of images too few 2572 } 2573 2574 /* Create */ 2575 2576 2577 return; 2578 } 2579 #endif 2580 2581 /*==========================================================================================*/ 2582 2583 /*==========================================================================================*/ 2584 /*==========================================================================================*/ 2585 /*==========================================================================================*/ 2586 /*==========================================================================================*/ 2587 /* Part with metric reconstruction */ 2588 2589 #if 1 2590 void icvComputeQ(int numMatr, CvMat** projMatr, CvMat** cameraMatr, CvMat* matrQ) 2591 { 2592 /* K*K' = P*Q*P' */ 2593 /* try to solve Q by linear method */ 2594 2595 CvMat* matrA = 0; 2596 CvMat* vectB = 0; 2597 2598 CV_FUNCNAME( "ComputeQ" ); 2599 __BEGIN__; 2600 2601 /* Define number of projection matrices */ 2602 if( numMatr < 2 ) 2603 { 2604 CV_ERROR( CV_StsUnmatchedSizes, "Number of projection matrices must be at least 2" ); 2605 } 2606 2607 2608 /* test matrices sizes */ 2609 if( matrQ->cols != 4 || matrQ->rows != 4 ) 2610 { 2611 CV_ERROR( CV_StsUnmatchedSizes, "Size of matrix Q must be 3x3" ); 2612 } 2613 2614 int currMatr; 2615 for( currMatr = 0; currMatr < numMatr; currMatr++ ) 2616 { 2617 2618 if( cameraMatr[currMatr]->cols != 3 || cameraMatr[currMatr]->rows != 3 ) 2619 { 2620 CV_ERROR( CV_StsUnmatchedSizes, "Size of each camera matrix must be 3x3" ); 2621 } 2622 2623 if( projMatr[currMatr]->cols != 4 || projMatr[currMatr]->rows != 3 ) 2624 { 2625 CV_ERROR( CV_StsUnmatchedSizes, "Size of each camera matrix must be 3x3" ); 2626 } 2627 } 2628 2629 CvMat matrw; 2630 double matrw_dat[9]; 2631 matrw = cvMat(3,3,CV_64F,matrw_dat); 2632 2633 CvMat matrKt; 2634 double matrKt_dat[9]; 2635 matrKt = cvMat(3,3,CV_64F,matrKt_dat); 2636 2637 2638 /* Create matrix A and vector B */ 2639 CV_CALL( matrA = cvCreateMat(9*numMatr,10,CV_64F) ); 2640 CV_CALL( vectB = cvCreateMat(9*numMatr,1,CV_64F) ); 2641 2642 double dataQ[16]; 2643 2644 for( currMatr = 0; currMatr < numMatr; currMatr++ ) 2645 { 2646 int ord10[10] = {0,1,2,3,5,6,7,10,11,15}; 2647 /* Fill atrix A by data from matrices */ 2648 2649 /* Compute matrix w for current camera matrix */ 2650 cvTranspose(cameraMatr[currMatr],&matrKt); 2651 cvmMul(cameraMatr[currMatr],&matrKt,&matrw); 2652 2653 /* Fill matrix A and vector B */ 2654 2655 int currWi,currWj; 2656 int currMatr; 2657 for( currMatr = 0; currMatr < numMatr; currMatr++ ) 2658 { 2659 for( currWi = 0; currWi < 3; currWi++ ) 2660 { 2661 for( currWj = 0; currWj < 3; currWj++ ) 2662 { 2663 int i,j; 2664 for( i = 0; i < 4; i++ ) 2665 { 2666 for( j = 0; j < 4; j++ ) 2667 { 2668 /* get elements from current projection matrix */ 2669 dataQ[i*4+j] = cvmGet(projMatr[currMatr],currWi,j) * 2670 cvmGet(projMatr[currMatr],currWj,i); 2671 } 2672 } 2673 2674 /* we know 16 elements in dataQ move them to matrQ 10 */ 2675 dataQ[1] += dataQ[4]; 2676 dataQ[2] += dataQ[8]; 2677 dataQ[3] += dataQ[12]; 2678 dataQ[6] += dataQ[9]; 2679 dataQ[7] += dataQ[13]; 2680 dataQ[11] += dataQ[14]; 2681 /* Now first 10 elements has coeffs */ 2682 2683 /* copy to matrix A */ 2684 for( i = 0; i < 10; i++ ) 2685 { 2686 cvmSet(matrA,currMatr*9 + currWi*3+currWj,i,dataQ[ord10[i]]); 2687 } 2688 } 2689 } 2690 2691 /* Fill vector B */ 2692 for( int i = 0; i < 9; i++ ) 2693 { 2694 cvmSet(vectB,currMatr*9+i,0,matrw_dat[i]); 2695 } 2696 } 2697 } 2698 2699 /* Matrix A and vector B filled and we can solve system */ 2700 2701 /* Solve system */ 2702 CvMat resQ; 2703 double resQ_dat[10]; 2704 resQ = cvMat(10,1,CV_64F,resQ_dat); 2705 2706 cvSolve(matrA,vectB,&resQ,CV_SVD); 2707 2708 /* System was solved. We know matrix Q. But we must have condition det Q=0 */ 2709 /* Just copy result matrix Q */ 2710 { 2711 int curr = 0; 2712 int ord16[16] = {0,1,2,3,1,4,5,6,2,5,7,8,3,6,8,9}; 2713 2714 for( int i = 0; i < 4; i++ ) 2715 { 2716 for( int j = 0; j < 4; j++ ) 2717 { 2718 cvmSet(matrQ,i,j,resQ_dat[ord16[curr++]]); 2719 } 2720 } 2721 } 2722 2723 2724 __END__; 2725 2726 /* Free allocated memory */ 2727 cvReleaseMat(&matrA); 2728 cvReleaseMat(&vectB); 2729 2730 return; 2731 } 2732 #endif 2733 /*-----------------------------------------------------------------------------------------------------*/ 2734 2735 void icvDecomposeQ(CvMat* /*matrQ*/,CvMat* /*matrH*/) 2736 { 2737 #if 0 2738 /* Use SVD to decompose matrix Q=H*I*H' */ 2739 /* test input data */ 2740 2741 CvMat matrW; 2742 CvMat matrU; 2743 // CvMat matrV; 2744 double matrW_dat[16]; 2745 double matrU_dat[16]; 2746 // double matrV_dat[16]; 2747 2748 matrW = cvMat(4,4,CV_64F,matrW_dat); 2749 matrU = cvMat(4,4,CV_64F,matrU_dat); 2750 // matrV = cvMat(4,4,CV_64F,matrV_dat); 2751 2752 cvSVD(matrQ,&matrW,&matrU,0); 2753 2754 double eig[3]; 2755 eig[0] = fsqrt(cvmGet(&matrW,0,0)); 2756 eig[1] = fsqrt(cvmGet(&matrW,1,1)); 2757 eig[2] = fsqrt(cvmGet(&matrW,2,2)); 2758 2759 CvMat matrIS; 2760 double matrIS_dat[16]; 2761 matrIS = 2762 2763 2764 2765 2766 /* det for matrix Q with q1-q10 */ 2767 /* 2768 + q1*q5*q8*q10 2769 - q1*q5*q9*q9 2770 - q1*q6*q6*q10 2771 + 2*q1*q6*q7*q9 2772 - q1*q7*q7*q8 2773 - q2*q2*q8*q10 2774 + q2*q2*q9*q9 2775 + 2*q2*q6*q3*q10 2776 - 2*q2*q6*q4*q9 2777 - 2*q2*q7*q3*q9 2778 + 2*q2*q7*q4*q8 2779 - q5*q3*q3*q10 2780 + 2*q3*q5*q4*q9 2781 + q3*q3*q7*q7 2782 - 2*q3*q7*q4*q6 2783 - q5*q4*q4*q8 2784 + q4*q4*q6*q6 2785 */ 2786 2787 // (1-a)^4 = 1 - 4 * a + 6 * a * a - 4 * a * a * a + a * a * a * a; 2788 2789 2790 #endif 2791 } 2792 2793