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 43 #include "_cvaux.h" 44 #include "cvtypes.h" 45 #include <float.h> 46 #include <limits.h> 47 #include "cv.h" 48 49 /* Valery Mosyagin */ 50 51 #undef quad 52 53 #define EPS64D 1e-9 54 55 int cvComputeEssentialMatrix( CvMatr32f rotMatr, 56 CvMatr32f transVect, 57 CvMatr32f essMatr); 58 59 int cvConvertEssential2Fundamental( CvMatr32f essMatr, 60 CvMatr32f fundMatr, 61 CvMatr32f cameraMatr1, 62 CvMatr32f cameraMatr2); 63 64 int cvComputeEpipolesFromFundMatrix(CvMatr32f fundMatr, 65 CvPoint3D32f* epipole1, 66 CvPoint3D32f* epipole2); 67 68 void icvTestPoint( CvPoint2D64d testPoint, 69 CvVect64d line1,CvVect64d line2, 70 CvPoint2D64d basePoint, 71 int* result); 72 73 74 75 int icvGetSymPoint3D( CvPoint3D64d pointCorner, 76 CvPoint3D64d point1, 77 CvPoint3D64d point2, 78 CvPoint3D64d *pointSym2) 79 { 80 double len1,len2; 81 double alpha; 82 icvGetPieceLength3D(pointCorner,point1,&len1); 83 if( len1 < EPS64D ) 84 { 85 return CV_BADARG_ERR; 86 } 87 icvGetPieceLength3D(pointCorner,point2,&len2); 88 alpha = len2 / len1; 89 90 pointSym2->x = pointCorner.x + alpha*(point1.x - pointCorner.x); 91 pointSym2->y = pointCorner.y + alpha*(point1.y - pointCorner.y); 92 pointSym2->z = pointCorner.z + alpha*(point1.z - pointCorner.z); 93 return CV_NO_ERR; 94 } 95 96 /* author Valery Mosyagin */ 97 98 /* Compute 3D point for scanline and alpha betta */ 99 int icvCompute3DPoint( double alpha,double betta, 100 CvStereoLineCoeff* coeffs, 101 CvPoint3D64d* point) 102 { 103 104 double partX; 105 double partY; 106 double partZ; 107 double partAll; 108 double invPartAll; 109 110 double alphabetta = alpha*betta; 111 112 partAll = alpha - betta; 113 if( fabs(partAll) > 0.00001 ) /* alpha must be > betta */ 114 { 115 116 partX = coeffs->Xcoef + coeffs->XcoefA *alpha + 117 coeffs->XcoefB*betta + coeffs->XcoefAB*alphabetta; 118 119 partY = coeffs->Ycoef + coeffs->YcoefA *alpha + 120 coeffs->YcoefB*betta + coeffs->YcoefAB*alphabetta; 121 122 partZ = coeffs->Zcoef + coeffs->ZcoefA *alpha + 123 coeffs->ZcoefB*betta + coeffs->ZcoefAB*alphabetta; 124 125 invPartAll = 1.0 / partAll; 126 127 point->x = partX * invPartAll; 128 point->y = partY * invPartAll; 129 point->z = partZ * invPartAll; 130 return CV_NO_ERR; 131 } 132 else 133 { 134 return CV_BADFACTOR_ERR; 135 } 136 } 137 138 /*--------------------------------------------------------------------------------------*/ 139 140 /* Compute rotate matrix and trans vector for change system */ 141 int icvCreateConvertMatrVect( CvMatr64d rotMatr1, 142 CvMatr64d transVect1, 143 CvMatr64d rotMatr2, 144 CvMatr64d transVect2, 145 CvMatr64d convRotMatr, 146 CvMatr64d convTransVect) 147 { 148 double invRotMatr2[9]; 149 double tmpVect[3]; 150 151 152 icvInvertMatrix_64d(rotMatr2,3,invRotMatr2); 153 /* Test for error */ 154 155 icvMulMatrix_64d( rotMatr1, 156 3,3, 157 invRotMatr2, 158 3,3, 159 convRotMatr); 160 161 icvMulMatrix_64d( convRotMatr, 162 3,3, 163 transVect2, 164 1,3, 165 tmpVect); 166 167 icvSubVector_64d(transVect1,tmpVect,convTransVect,3); 168 169 170 return CV_NO_ERR; 171 } 172 173 /*--------------------------------------------------------------------------------------*/ 174 175 /* Compute point coordinates in other system */ 176 int icvConvertPointSystem(CvPoint3D64d M2, 177 CvPoint3D64d* M1, 178 CvMatr64d rotMatr, 179 CvMatr64d transVect 180 ) 181 { 182 double tmpVect[3]; 183 184 icvMulMatrix_64d( rotMatr, 185 3,3, 186 (double*)&M2, 187 1,3, 188 tmpVect); 189 190 icvAddVector_64d(tmpVect,transVect,(double*)M1,3); 191 192 return CV_NO_ERR; 193 } 194 /*--------------------------------------------------------------------------------------*/ 195 int icvComputeCoeffForStereoV3( double quad1[4][2], 196 double quad2[4][2], 197 int numScanlines, 198 CvMatr64d camMatr1, 199 CvMatr64d rotMatr1, 200 CvMatr64d transVect1, 201 CvMatr64d camMatr2, 202 CvMatr64d rotMatr2, 203 CvMatr64d transVect2, 204 CvStereoLineCoeff* startCoeffs, 205 int* needSwapCamera) 206 { 207 /* For each pair */ 208 /* In this function we must define position of cameras */ 209 210 CvPoint2D64d point1; 211 CvPoint2D64d point2; 212 CvPoint2D64d point3; 213 CvPoint2D64d point4; 214 215 int currLine; 216 *needSwapCamera = 0; 217 for( currLine = 0; currLine < numScanlines; currLine++ ) 218 { 219 /* Compute points */ 220 double alpha = ((double)currLine)/((double)(numScanlines)); /* maybe - 1 */ 221 222 point1.x = (1.0 - alpha) * quad1[0][0] + alpha * quad1[3][0]; 223 point1.y = (1.0 - alpha) * quad1[0][1] + alpha * quad1[3][1]; 224 225 point2.x = (1.0 - alpha) * quad1[1][0] + alpha * quad1[2][0]; 226 point2.y = (1.0 - alpha) * quad1[1][1] + alpha * quad1[2][1]; 227 228 point3.x = (1.0 - alpha) * quad2[0][0] + alpha * quad2[3][0]; 229 point3.y = (1.0 - alpha) * quad2[0][1] + alpha * quad2[3][1]; 230 231 point4.x = (1.0 - alpha) * quad2[1][0] + alpha * quad2[2][0]; 232 point4.y = (1.0 - alpha) * quad2[1][1] + alpha * quad2[2][1]; 233 234 /* We can compute coeffs for this line */ 235 icvComCoeffForLine( point1, 236 point2, 237 point3, 238 point4, 239 camMatr1, 240 rotMatr1, 241 transVect1, 242 camMatr2, 243 rotMatr2, 244 transVect2, 245 &startCoeffs[currLine], 246 needSwapCamera); 247 } 248 return CV_NO_ERR; 249 } 250 /*--------------------------------------------------------------------------------------*/ 251 int icvComputeCoeffForStereoNew( double quad1[4][2], 252 double quad2[4][2], 253 int numScanlines, 254 CvMatr32f camMatr1, 255 CvMatr32f rotMatr1, 256 CvMatr32f transVect1, 257 CvMatr32f camMatr2, 258 CvStereoLineCoeff* startCoeffs, 259 int* needSwapCamera) 260 { 261 /* Convert data */ 262 263 double camMatr1_64d[9]; 264 double camMatr2_64d[9]; 265 266 double rotMatr1_64d[9]; 267 double transVect1_64d[3]; 268 269 double rotMatr2_64d[9]; 270 double transVect2_64d[3]; 271 272 icvCvt_32f_64d(camMatr1,camMatr1_64d,9); 273 icvCvt_32f_64d(camMatr2,camMatr2_64d,9); 274 275 icvCvt_32f_64d(rotMatr1,rotMatr1_64d,9); 276 icvCvt_32f_64d(transVect1,transVect1_64d,3); 277 278 rotMatr2_64d[0] = 1; 279 rotMatr2_64d[1] = 0; 280 rotMatr2_64d[2] = 0; 281 rotMatr2_64d[3] = 0; 282 rotMatr2_64d[4] = 1; 283 rotMatr2_64d[5] = 0; 284 rotMatr2_64d[6] = 0; 285 rotMatr2_64d[7] = 0; 286 rotMatr2_64d[8] = 1; 287 288 transVect2_64d[0] = 0; 289 transVect2_64d[1] = 0; 290 transVect2_64d[2] = 0; 291 292 int status = icvComputeCoeffForStereoV3( quad1, 293 quad2, 294 numScanlines, 295 camMatr1_64d, 296 rotMatr1_64d, 297 transVect1_64d, 298 camMatr2_64d, 299 rotMatr2_64d, 300 transVect2_64d, 301 startCoeffs, 302 needSwapCamera); 303 304 305 return status; 306 307 } 308 /*--------------------------------------------------------------------------------------*/ 309 int icvComputeCoeffForStereo( CvStereoCamera* stereoCamera) 310 { 311 double quad1[4][2]; 312 double quad2[4][2]; 313 314 int i; 315 for( i = 0; i < 4; i++ ) 316 { 317 quad1[i][0] = stereoCamera->quad[0][i].x; 318 quad1[i][1] = stereoCamera->quad[0][i].y; 319 320 quad2[i][0] = stereoCamera->quad[1][i].x; 321 quad2[i][1] = stereoCamera->quad[1][i].y; 322 } 323 324 icvComputeCoeffForStereoNew( quad1, 325 quad2, 326 stereoCamera->warpSize.height, 327 stereoCamera->camera[0]->matrix, 328 stereoCamera->rotMatrix, 329 stereoCamera->transVector, 330 stereoCamera->camera[1]->matrix, 331 stereoCamera->lineCoeffs, 332 &(stereoCamera->needSwapCameras)); 333 return CV_OK; 334 } 335 336 337 338 /*--------------------------------------------------------------------------------------*/ 339 int icvComCoeffForLine( CvPoint2D64d point1, 340 CvPoint2D64d point2, 341 CvPoint2D64d point3, 342 CvPoint2D64d point4, 343 CvMatr64d camMatr1, 344 CvMatr64d rotMatr1, 345 CvMatr64d transVect1, 346 CvMatr64d camMatr2, 347 CvMatr64d rotMatr2, 348 CvMatr64d transVect2, 349 CvStereoLineCoeff* coeffs, 350 int* needSwapCamera) 351 { 352 /* Get direction for all points */ 353 /* Direction for camera 1 */ 354 355 double direct1[3]; 356 double direct2[3]; 357 double camPoint1[3]; 358 359 double directS3[3]; 360 double directS4[3]; 361 double direct3[3]; 362 double direct4[3]; 363 double camPoint2[3]; 364 365 icvGetDirectionForPoint( point1, 366 camMatr1, 367 (CvPoint3D64d*)direct1); 368 369 icvGetDirectionForPoint( point2, 370 camMatr1, 371 (CvPoint3D64d*)direct2); 372 373 /* Direction for camera 2 */ 374 375 icvGetDirectionForPoint( point3, 376 camMatr2, 377 (CvPoint3D64d*)directS3); 378 379 icvGetDirectionForPoint( point4, 380 camMatr2, 381 (CvPoint3D64d*)directS4); 382 383 /* Create convertion for camera 2: two direction and camera point */ 384 385 double convRotMatr[9]; 386 double convTransVect[3]; 387 388 icvCreateConvertMatrVect( rotMatr1, 389 transVect1, 390 rotMatr2, 391 transVect2, 392 convRotMatr, 393 convTransVect); 394 395 double zeroVect[3]; 396 zeroVect[0] = zeroVect[1] = zeroVect[2] = 0.0; 397 camPoint1[0] = camPoint1[1] = camPoint1[2] = 0.0; 398 399 icvConvertPointSystem(*((CvPoint3D64d*)directS3),(CvPoint3D64d*)direct3,convRotMatr,convTransVect); 400 icvConvertPointSystem(*((CvPoint3D64d*)directS4),(CvPoint3D64d*)direct4,convRotMatr,convTransVect); 401 icvConvertPointSystem(*((CvPoint3D64d*)zeroVect),(CvPoint3D64d*)camPoint2,convRotMatr,convTransVect); 402 403 double pointB[3]; 404 405 int postype = 0; 406 407 /* Changed order */ 408 /* Compute point B: xB,yB,zB */ 409 icvGetCrossLines(*((CvPoint3D64d*)camPoint1),*((CvPoint3D64d*)direct2), 410 *((CvPoint3D64d*)camPoint2),*((CvPoint3D64d*)direct3), 411 (CvPoint3D64d*)pointB); 412 413 if( pointB[2] < 0 )/* If negative use other lines for cross */ 414 { 415 postype = 1; 416 icvGetCrossLines(*((CvPoint3D64d*)camPoint1),*((CvPoint3D64d*)direct1), 417 *((CvPoint3D64d*)camPoint2),*((CvPoint3D64d*)direct4), 418 (CvPoint3D64d*)pointB); 419 } 420 421 CvPoint3D64d pointNewA; 422 CvPoint3D64d pointNewC; 423 424 pointNewA.x = pointNewA.y = pointNewA.z = 0; 425 pointNewC.x = pointNewC.y = pointNewC.z = 0; 426 427 if( postype == 0 ) 428 { 429 icvGetSymPoint3D( *((CvPoint3D64d*)camPoint1), 430 *((CvPoint3D64d*)direct1), 431 *((CvPoint3D64d*)pointB), 432 &pointNewA); 433 434 icvGetSymPoint3D( *((CvPoint3D64d*)camPoint2), 435 *((CvPoint3D64d*)direct4), 436 *((CvPoint3D64d*)pointB), 437 &pointNewC); 438 } 439 else 440 {/* In this case we must change cameras */ 441 *needSwapCamera = 1; 442 icvGetSymPoint3D( *((CvPoint3D64d*)camPoint2), 443 *((CvPoint3D64d*)direct3), 444 *((CvPoint3D64d*)pointB), 445 &pointNewA); 446 447 icvGetSymPoint3D( *((CvPoint3D64d*)camPoint1), 448 *((CvPoint3D64d*)direct2), 449 *((CvPoint3D64d*)pointB), 450 &pointNewC); 451 } 452 453 454 double gamma; 455 456 double x1,y1,z1; 457 458 x1 = camPoint1[0]; 459 y1 = camPoint1[1]; 460 z1 = camPoint1[2]; 461 462 double xA,yA,zA; 463 double xB,yB,zB; 464 double xC,yC,zC; 465 466 xA = pointNewA.x; 467 yA = pointNewA.y; 468 zA = pointNewA.z; 469 470 xB = pointB[0]; 471 yB = pointB[1]; 472 zB = pointB[2]; 473 474 xC = pointNewC.x; 475 yC = pointNewC.y; 476 zC = pointNewC.z; 477 478 double len1,len2; 479 len1 = sqrt( (xA-xB)*(xA-xB) + (yA-yB)*(yA-yB) + (zA-zB)*(zA-zB) ); 480 len2 = sqrt( (xB-xC)*(xB-xC) + (yB-yC)*(yB-yC) + (zB-zC)*(zB-zC) ); 481 gamma = len2 / len1; 482 483 icvComputeStereoLineCoeffs( pointNewA, 484 *((CvPoint3D64d*)pointB), 485 *((CvPoint3D64d*)camPoint1), 486 gamma, 487 coeffs); 488 489 return CV_NO_ERR; 490 } 491 492 493 /*--------------------------------------------------------------------------------------*/ 494 495 int icvGetDirectionForPoint( CvPoint2D64d point, 496 CvMatr64d camMatr, 497 CvPoint3D64d* direct) 498 { 499 /* */ 500 double invMatr[9]; 501 502 /* Invert matrix */ 503 504 icvInvertMatrix_64d(camMatr,3,invMatr); 505 /* TEST FOR ERRORS */ 506 507 double vect[3]; 508 vect[0] = point.x; 509 vect[1] = point.y; 510 vect[2] = 1; 511 512 /* Mul matr */ 513 icvMulMatrix_64d( invMatr, 514 3,3, 515 vect, 516 1,3, 517 (double*)direct); 518 519 return CV_NO_ERR; 520 } 521 522 /*--------------------------------------------------------------------------------------*/ 523 524 int icvGetCrossLines(CvPoint3D64d point11,CvPoint3D64d point12, 525 CvPoint3D64d point21,CvPoint3D64d point22, 526 CvPoint3D64d* midPoint) 527 { 528 double xM,yM,zM; 529 double xN,yN,zN; 530 531 double xA,yA,zA; 532 double xB,yB,zB; 533 534 double xC,yC,zC; 535 double xD,yD,zD; 536 537 xA = point11.x; 538 yA = point11.y; 539 zA = point11.z; 540 541 xB = point12.x; 542 yB = point12.y; 543 zB = point12.z; 544 545 xC = point21.x; 546 yC = point21.y; 547 zC = point21.z; 548 549 xD = point22.x; 550 yD = point22.y; 551 zD = point22.z; 552 553 double a11,a12,a21,a22; 554 double b1,b2; 555 556 a11 = (xB-xA)*(xB-xA)+(yB-yA)*(yB-yA)+(zB-zA)*(zB-zA); 557 a12 = -(xD-xC)*(xB-xA)-(yD-yC)*(yB-yA)-(zD-zC)*(zB-zA); 558 a21 = (xB-xA)*(xD-xC)+(yB-yA)*(yD-yC)+(zB-zA)*(zD-zC); 559 a22 = -(xD-xC)*(xD-xC)-(yD-yC)*(yD-yC)-(zD-zC)*(zD-zC); 560 b1 = -( (xA-xC)*(xB-xA)+(yA-yC)*(yB-yA)+(zA-zC)*(zB-zA) ); 561 b2 = -( (xA-xC)*(xD-xC)+(yA-yC)*(yD-yC)+(zA-zC)*(zD-zC) ); 562 563 double delta; 564 double deltaA,deltaB; 565 double alpha,betta; 566 567 delta = a11*a22-a12*a21; 568 569 if( fabs(delta) < EPS64D ) 570 { 571 /*return ERROR;*/ 572 } 573 574 deltaA = b1*a22-b2*a12; 575 deltaB = a11*b2-b1*a21; 576 577 alpha = deltaA / delta; 578 betta = deltaB / delta; 579 580 xM = xA+alpha*(xB-xA); 581 yM = yA+alpha*(yB-yA); 582 zM = zA+alpha*(zB-zA); 583 584 xN = xC+betta*(xD-xC); 585 yN = yC+betta*(yD-yC); 586 zN = zC+betta*(zD-zC); 587 588 /* Compute middle point */ 589 midPoint->x = (xM + xN) * 0.5; 590 midPoint->y = (yM + yN) * 0.5; 591 midPoint->z = (zM + zN) * 0.5; 592 593 return CV_NO_ERR; 594 } 595 596 /*--------------------------------------------------------------------------------------*/ 597 598 int icvComputeStereoLineCoeffs( CvPoint3D64d pointA, 599 CvPoint3D64d pointB, 600 CvPoint3D64d pointCam1, 601 double gamma, 602 CvStereoLineCoeff* coeffs) 603 { 604 double x1,y1,z1; 605 606 x1 = pointCam1.x; 607 y1 = pointCam1.y; 608 z1 = pointCam1.z; 609 610 double xA,yA,zA; 611 double xB,yB,zB; 612 613 xA = pointA.x; 614 yA = pointA.y; 615 zA = pointA.z; 616 617 xB = pointB.x; 618 yB = pointB.y; 619 zB = pointB.z; 620 621 if( gamma > 0 ) 622 { 623 coeffs->Xcoef = -x1 + xA; 624 coeffs->XcoefA = xB + x1 - xA; 625 coeffs->XcoefB = -xA - gamma * x1 + gamma * xA; 626 coeffs->XcoefAB = -xB + xA + gamma * xB - gamma * xA; 627 628 coeffs->Ycoef = -y1 + yA; 629 coeffs->YcoefA = yB + y1 - yA; 630 coeffs->YcoefB = -yA - gamma * y1 + gamma * yA; 631 coeffs->YcoefAB = -yB + yA + gamma * yB - gamma * yA; 632 633 coeffs->Zcoef = -z1 + zA; 634 coeffs->ZcoefA = zB + z1 - zA; 635 coeffs->ZcoefB = -zA - gamma * z1 + gamma * zA; 636 coeffs->ZcoefAB = -zB + zA + gamma * zB - gamma * zA; 637 } 638 else 639 { 640 gamma = - gamma; 641 coeffs->Xcoef = -( -x1 + xA); 642 coeffs->XcoefB = -( xB + x1 - xA); 643 coeffs->XcoefA = -( -xA - gamma * x1 + gamma * xA); 644 coeffs->XcoefAB = -( -xB + xA + gamma * xB - gamma * xA); 645 646 coeffs->Ycoef = -( -y1 + yA); 647 coeffs->YcoefB = -( yB + y1 - yA); 648 coeffs->YcoefA = -( -yA - gamma * y1 + gamma * yA); 649 coeffs->YcoefAB = -( -yB + yA + gamma * yB - gamma * yA); 650 651 coeffs->Zcoef = -( -z1 + zA); 652 coeffs->ZcoefB = -( zB + z1 - zA); 653 coeffs->ZcoefA = -( -zA - gamma * z1 + gamma * zA); 654 coeffs->ZcoefAB = -( -zB + zA + gamma * zB - gamma * zA); 655 } 656 657 658 659 return CV_NO_ERR; 660 } 661 /*--------------------------------------------------------------------------------------*/ 662 663 664 /*---------------------------------------------------------------------------------------*/ 665 666 /* This function get minimum angle started at point which contains rect */ 667 int icvGetAngleLine( CvPoint2D64d startPoint, CvSize imageSize,CvPoint2D64d *point1,CvPoint2D64d *point2) 668 { 669 /* Get crosslines with image corners */ 670 671 /* Find four lines */ 672 673 CvPoint2D64d pa,pb,pc,pd; 674 675 pa.x = 0; 676 pa.y = 0; 677 678 pb.x = imageSize.width-1; 679 pb.y = 0; 680 681 pd.x = imageSize.width-1; 682 pd.y = imageSize.height-1; 683 684 pc.x = 0; 685 pc.y = imageSize.height-1; 686 687 /* We can compute points for angle */ 688 /* Test for place section */ 689 690 if( startPoint.x < 0 ) 691 {/* 1,4,7 */ 692 if( startPoint.y < 0) 693 {/* 1 */ 694 *point1 = pb; 695 *point2 = pc; 696 } 697 else if( startPoint.y > imageSize.height-1 ) 698 {/* 7 */ 699 *point1 = pa; 700 *point2 = pd; 701 } 702 else 703 {/* 4 */ 704 *point1 = pa; 705 *point2 = pc; 706 } 707 } 708 else if ( startPoint.x > imageSize.width-1 ) 709 {/* 3,6,9 */ 710 if( startPoint.y < 0 ) 711 {/* 3 */ 712 *point1 = pa; 713 *point2 = pd; 714 } 715 else if ( startPoint.y > imageSize.height-1 ) 716 {/* 9 */ 717 *point1 = pb; 718 *point2 = pc; 719 } 720 else 721 {/* 6 */ 722 *point1 = pb; 723 *point2 = pd; 724 } 725 } 726 else 727 {/* 2,5,8 */ 728 if( startPoint.y < 0 ) 729 {/* 2 */ 730 if( startPoint.x < imageSize.width/2 ) 731 { 732 *point1 = pb; 733 *point2 = pa; 734 } 735 else 736 { 737 *point1 = pa; 738 *point2 = pb; 739 } 740 } 741 else if( startPoint.y > imageSize.height-1 ) 742 {/* 8 */ 743 if( startPoint.x < imageSize.width/2 ) 744 { 745 *point1 = pc; 746 *point2 = pd; 747 } 748 else 749 { 750 *point1 = pd; 751 *point2 = pc; 752 } 753 } 754 else 755 {/* 5 - point in the image */ 756 return 2; 757 } 758 } 759 return 0; 760 }/* GetAngleLine */ 761 762 /*---------------------------------------------------------------------------------------*/ 763 764 void icvGetCoefForPiece( CvPoint2D64d p_start,CvPoint2D64d p_end, 765 double *a,double *b,double *c, 766 int* result) 767 { 768 double det; 769 double detA,detB,detC; 770 771 det = p_start.x*p_end.y+p_end.x+p_start.y-p_end.y-p_start.y*p_end.x-p_start.x; 772 if( fabs(det) < EPS64D)/* Error */ 773 { 774 *result = 0; 775 return; 776 } 777 778 detA = p_start.y - p_end.y; 779 detB = p_end.x - p_start.x; 780 detC = p_start.x*p_end.y - p_end.x*p_start.y; 781 782 double invDet = 1.0 / det; 783 *a = detA * invDet; 784 *b = detB * invDet; 785 *c = detC * invDet; 786 787 *result = 1; 788 return; 789 } 790 791 /*---------------------------------------------------------------------------------------*/ 792 793 /* Get common area of rectifying */ 794 void icvGetCommonArea( CvSize imageSize, 795 CvPoint3D64d epipole1,CvPoint3D64d epipole2, 796 CvMatr64d fundMatr, 797 CvVect64d coeff11,CvVect64d coeff12, 798 CvVect64d coeff21,CvVect64d coeff22, 799 int* result) 800 { 801 int res = 0; 802 CvPoint2D64d point11; 803 CvPoint2D64d point12; 804 CvPoint2D64d point21; 805 CvPoint2D64d point22; 806 807 double corr11[3]; 808 double corr12[3]; 809 double corr21[3]; 810 double corr22[3]; 811 812 double pointW11[3]; 813 double pointW12[3]; 814 double pointW21[3]; 815 double pointW22[3]; 816 817 double transFundMatr[3*3]; 818 /* Compute transpose of fundamental matrix */ 819 icvTransposeMatrix_64d( fundMatr, 3, 3, transFundMatr ); 820 821 CvPoint2D64d epipole1_2d; 822 CvPoint2D64d epipole2_2d; 823 824 if( fabs(epipole1.z) < 1e-8 ) 825 {/* epipole1 in infinity */ 826 *result = 0; 827 return; 828 } 829 epipole1_2d.x = epipole1.x / epipole1.z; 830 epipole1_2d.y = epipole1.y / epipole1.z; 831 832 if( fabs(epipole2.z) < 1e-8 ) 833 {/* epipole2 in infinity */ 834 *result = 0; 835 return; 836 } 837 epipole2_2d.x = epipole2.x / epipole2.z; 838 epipole2_2d.y = epipole2.y / epipole2.z; 839 840 int stat = icvGetAngleLine( epipole1_2d, imageSize,&point11,&point12); 841 if( stat == 2 ) 842 { 843 /* No angle */ 844 *result = 0; 845 return; 846 } 847 848 stat = icvGetAngleLine( epipole2_2d, imageSize,&point21,&point22); 849 if( stat == 2 ) 850 { 851 /* No angle */ 852 *result = 0; 853 return; 854 } 855 856 /* ============= Computation for line 1 ================ */ 857 /* Find correspondence line for angle points11 */ 858 /* corr21 = Fund'*p1 */ 859 860 pointW11[0] = point11.x; 861 pointW11[1] = point11.y; 862 pointW11[2] = 1.0; 863 864 icvTransformVector_64d( transFundMatr, /* !!! Modified from not transposed */ 865 pointW11, 866 corr21, 867 3,3); 868 869 /* Find crossing of line with image 2 */ 870 CvPoint2D64d start; 871 CvPoint2D64d end; 872 icvGetCrossRectDirect( imageSize, 873 corr21[0],corr21[1],corr21[2], 874 &start,&end, 875 &res); 876 877 if( res == 0 ) 878 {/* We have not cross */ 879 /* We must define new angle */ 880 881 pointW21[0] = point21.x; 882 pointW21[1] = point21.y; 883 pointW21[2] = 1.0; 884 885 /* Find correspondence line for this angle points */ 886 /* We know point and try to get corr line */ 887 /* For point21 */ 888 /* corr11 = Fund * p21 */ 889 890 icvTransformVector_64d( fundMatr, /* !!! Modified */ 891 pointW21, 892 corr11, 893 3,3); 894 895 /* We have cross. And it's result cross for up line. Set result coefs */ 896 897 /* Set coefs for line 1 image 1 */ 898 coeff11[0] = corr11[0]; 899 coeff11[1] = corr11[1]; 900 coeff11[2] = corr11[2]; 901 902 /* Set coefs for line 1 image 2 */ 903 icvGetCoefForPiece( epipole2_2d,point21, 904 &coeff21[0],&coeff21[1],&coeff21[2], 905 &res); 906 if( res == 0 ) 907 { 908 *result = 0; 909 return;/* Error */ 910 } 911 } 912 else 913 {/* Line 1 cross image 2 */ 914 /* Set coefs for line 1 image 1 */ 915 icvGetCoefForPiece( epipole1_2d,point11, 916 &coeff11[0],&coeff11[1],&coeff11[2], 917 &res); 918 if( res == 0 ) 919 { 920 *result = 0; 921 return;/* Error */ 922 } 923 924 /* Set coefs for line 1 image 2 */ 925 coeff21[0] = corr21[0]; 926 coeff21[1] = corr21[1]; 927 coeff21[2] = corr21[2]; 928 929 } 930 931 /* ============= Computation for line 2 ================ */ 932 /* Find correspondence line for angle points11 */ 933 /* corr22 = Fund*p2 */ 934 935 pointW12[0] = point12.x; 936 pointW12[1] = point12.y; 937 pointW12[2] = 1.0; 938 939 icvTransformVector_64d( transFundMatr, 940 pointW12, 941 corr22, 942 3,3); 943 944 /* Find crossing of line with image 2 */ 945 icvGetCrossRectDirect( imageSize, 946 corr22[0],corr22[1],corr22[2], 947 &start,&end, 948 &res); 949 950 if( res == 0 ) 951 {/* We have not cross */ 952 /* We must define new angle */ 953 954 pointW22[0] = point22.x; 955 pointW22[1] = point22.y; 956 pointW22[2] = 1.0; 957 958 /* Find correspondence line for this angle points */ 959 /* We know point and try to get corr line */ 960 /* For point21 */ 961 /* corr2 = Fund' * p1 */ 962 963 icvTransformVector_64d( fundMatr, 964 pointW22, 965 corr12, 966 3,3); 967 968 969 /* We have cross. And it's result cross for down line. Set result coefs */ 970 971 /* Set coefs for line 2 image 1 */ 972 coeff12[0] = corr12[0]; 973 coeff12[1] = corr12[1]; 974 coeff12[2] = corr12[2]; 975 976 /* Set coefs for line 1 image 2 */ 977 icvGetCoefForPiece( epipole2_2d,point22, 978 &coeff22[0],&coeff22[1],&coeff22[2], 979 &res); 980 if( res == 0 ) 981 { 982 *result = 0; 983 return;/* Error */ 984 } 985 } 986 else 987 {/* Line 2 cross image 2 */ 988 /* Set coefs for line 2 image 1 */ 989 icvGetCoefForPiece( epipole1_2d,point12, 990 &coeff12[0],&coeff12[1],&coeff12[2], 991 &res); 992 if( res == 0 ) 993 { 994 *result = 0; 995 return;/* Error */ 996 } 997 998 /* Set coefs for line 1 image 2 */ 999 coeff22[0] = corr22[0]; 1000 coeff22[1] = corr22[1]; 1001 coeff22[2] = corr22[2]; 1002 1003 } 1004 1005 /* Now we know common area */ 1006 1007 return; 1008 1009 }/* GetCommonArea */ 1010 1011 /*---------------------------------------------------------------------------------------*/ 1012 1013 /* Get cross for direction1 and direction2 */ 1014 /* Result = 1 - cross */ 1015 /* Result = 2 - parallel and not equal */ 1016 /* Result = 3 - parallel and equal */ 1017 1018 void icvGetCrossDirectDirect( CvVect64d direct1,CvVect64d direct2, 1019 CvPoint2D64d *cross,int* result) 1020 { 1021 double det = direct1[0]*direct2[1] - direct2[0]*direct1[1]; 1022 double detx = -direct1[2]*direct2[1] + direct1[1]*direct2[2]; 1023 1024 if( fabs(det) > EPS64D ) 1025 {/* Have cross */ 1026 cross->x = detx/det; 1027 cross->y = (-direct1[0]*direct2[2] + direct2[0]*direct1[2])/det; 1028 *result = 1; 1029 } 1030 else 1031 {/* may be parallel */ 1032 if( fabs(detx) > EPS64D ) 1033 {/* parallel and not equal */ 1034 *result = 2; 1035 } 1036 else 1037 {/* equals */ 1038 *result = 3; 1039 } 1040 } 1041 1042 return; 1043 } 1044 1045 /*---------------------------------------------------------------------------------------*/ 1046 1047 /* Get cross for piece p1,p2 and direction a,b,c */ 1048 /* Result = 0 - no cross */ 1049 /* Result = 1 - cross */ 1050 /* Result = 2 - parallel and not equal */ 1051 /* Result = 3 - parallel and equal */ 1052 1053 void icvGetCrossPieceDirect( CvPoint2D64d p_start,CvPoint2D64d p_end, 1054 double a,double b,double c, 1055 CvPoint2D64d *cross,int* result) 1056 { 1057 1058 if( (a*p_start.x + b*p_start.y + c) * (a*p_end.x + b*p_end.y + c) <= 0 ) 1059 {/* Have cross */ 1060 double det; 1061 double detxc,detyc; 1062 1063 det = a * (p_end.x - p_start.x) + b * (p_end.y - p_start.y); 1064 1065 if( fabs(det) < EPS64D ) 1066 {/* lines are parallel and may be equal or line is point */ 1067 if( fabs(a*p_start.x + b*p_start.y + c) < EPS64D ) 1068 {/* line is point or not diff */ 1069 *result = 3; 1070 return; 1071 } 1072 else 1073 { 1074 *result = 2; 1075 } 1076 return; 1077 } 1078 1079 detxc = b*(p_end.y*p_start.x - p_start.y*p_end.x) + c*(p_start.x - p_end.x); 1080 detyc = a*(p_end.x*p_start.y - p_start.x*p_end.y) + c*(p_start.y - p_end.y); 1081 1082 cross->x = detxc / det; 1083 cross->y = detyc / det; 1084 *result = 1; 1085 1086 } 1087 else 1088 { 1089 *result = 0; 1090 } 1091 return; 1092 } 1093 /*--------------------------------------------------------------------------------------*/ 1094 1095 void icvGetCrossPiecePiece( CvPoint2D64d p1_start,CvPoint2D64d p1_end, 1096 CvPoint2D64d p2_start,CvPoint2D64d p2_end, 1097 CvPoint2D64d* cross, 1098 int* result) 1099 { 1100 double ex1,ey1,ex2,ey2; 1101 double px1,py1,px2,py2; 1102 double del; 1103 double delA,delB,delX,delY; 1104 double alpha,betta; 1105 1106 ex1 = p1_start.x; 1107 ey1 = p1_start.y; 1108 ex2 = p1_end.x; 1109 ey2 = p1_end.y; 1110 1111 px1 = p2_start.x; 1112 py1 = p2_start.y; 1113 px2 = p2_end.x; 1114 py2 = p2_end.y; 1115 1116 del = (py1-py2)*(ex1-ex2)-(px1-px2)*(ey1-ey2); 1117 if( fabs(del) <= EPS64D ) 1118 {/* May be they are parallel !!! */ 1119 *result = 0; 1120 return; 1121 } 1122 1123 delA = (ey1-ey2)*(ex1-px1) + (ex1-ex2)*(py1-ey1); 1124 delB = (py1-py2)*(ex1-px1) + (px1-px2)*(py1-ey1); 1125 1126 alpha = delA / del; 1127 betta = delB / del; 1128 1129 if( alpha < 0 || alpha > 1.0 || betta < 0 || betta > 1.0) 1130 { 1131 *result = 0; 1132 return; 1133 } 1134 1135 delX = (px1-px2)*(ey1*(ex1-ex2)-ex1*(ey1-ey2))+ 1136 (ex1-ex2)*(px1*(py1-py2)-py1*(px1-px2)); 1137 1138 delY = (py1-py2)*(ey1*(ex1-ex2)-ex1*(ey1-ey2))+ 1139 (ey1-ey2)*(px1*(py1-py2)-py1*(px1-px2)); 1140 1141 cross->x = delX / del; 1142 cross->y = delY / del; 1143 1144 *result = 1; 1145 return; 1146 } 1147 1148 1149 /*---------------------------------------------------------------------------------------*/ 1150 1151 void icvGetPieceLength(CvPoint2D64d point1,CvPoint2D64d point2,double* dist) 1152 { 1153 double dx = point2.x - point1.x; 1154 double dy = point2.y - point1.y; 1155 *dist = sqrt( dx*dx + dy*dy ); 1156 return; 1157 } 1158 1159 /*---------------------------------------------------------------------------------------*/ 1160 1161 void icvGetPieceLength3D(CvPoint3D64d point1,CvPoint3D64d point2,double* dist) 1162 { 1163 double dx = point2.x - point1.x; 1164 double dy = point2.y - point1.y; 1165 double dz = point2.z - point1.z; 1166 *dist = sqrt( dx*dx + dy*dy + dz*dz ); 1167 return; 1168 } 1169 1170 /*---------------------------------------------------------------------------------------*/ 1171 1172 /* Find line from epipole which cross image rect */ 1173 /* Find points of cross 0 or 1 or 2. Return number of points in cross */ 1174 void icvGetCrossRectDirect( CvSize imageSize, 1175 double a,double b,double c, 1176 CvPoint2D64d *start,CvPoint2D64d *end, 1177 int* result) 1178 { 1179 CvPoint2D64d frameBeg; 1180 CvPoint2D64d frameEnd; 1181 CvPoint2D64d cross[4]; 1182 int haveCross[4]; 1183 1184 haveCross[0] = 0; 1185 haveCross[1] = 0; 1186 haveCross[2] = 0; 1187 haveCross[3] = 0; 1188 1189 frameBeg.x = 0; 1190 frameBeg.y = 0; 1191 frameEnd.x = imageSize.width; 1192 frameEnd.y = 0; 1193 1194 icvGetCrossPieceDirect(frameBeg,frameEnd,a,b,c,&cross[0],&haveCross[0]); 1195 1196 frameBeg.x = imageSize.width; 1197 frameBeg.y = 0; 1198 frameEnd.x = imageSize.width; 1199 frameEnd.y = imageSize.height; 1200 icvGetCrossPieceDirect(frameBeg,frameEnd,a,b,c,&cross[1],&haveCross[1]); 1201 1202 frameBeg.x = imageSize.width; 1203 frameBeg.y = imageSize.height; 1204 frameEnd.x = 0; 1205 frameEnd.y = imageSize.height; 1206 icvGetCrossPieceDirect(frameBeg,frameEnd,a,b,c,&cross[2],&haveCross[2]); 1207 1208 frameBeg.x = 0; 1209 frameBeg.y = imageSize.height; 1210 frameEnd.x = 0; 1211 frameEnd.y = 0; 1212 icvGetCrossPieceDirect(frameBeg,frameEnd,a,b,c,&cross[3],&haveCross[3]); 1213 1214 double maxDist; 1215 1216 int maxI=0,maxJ=0; 1217 1218 1219 int i,j; 1220 1221 maxDist = -1.0; 1222 1223 double distance; 1224 1225 for( i = 0; i < 3; i++ ) 1226 { 1227 if( haveCross[i] == 1 ) 1228 { 1229 for( j = i + 1; j < 4; j++ ) 1230 { 1231 if( haveCross[j] == 1) 1232 {/* Compute dist */ 1233 icvGetPieceLength(cross[i],cross[j],&distance); 1234 if( distance > maxDist ) 1235 { 1236 maxI = i; 1237 maxJ = j; 1238 maxDist = distance; 1239 } 1240 } 1241 } 1242 } 1243 } 1244 1245 if( maxDist >= 0 ) 1246 {/* We have cross */ 1247 *start = cross[maxI]; 1248 *result = 1; 1249 if( maxDist > 0 ) 1250 { 1251 *end = cross[maxJ]; 1252 *result = 2; 1253 } 1254 } 1255 else 1256 { 1257 *result = 0; 1258 } 1259 1260 return; 1261 }/* GetCrossRectDirect */ 1262 1263 /*---------------------------------------------------------------------------------------*/ 1264 void icvProjectPointToImage( CvPoint3D64d point, 1265 CvMatr64d camMatr,CvMatr64d rotMatr,CvVect64d transVect, 1266 CvPoint2D64d* projPoint) 1267 { 1268 1269 double tmpVect1[3]; 1270 double tmpVect2[3]; 1271 1272 icvMulMatrix_64d ( rotMatr, 1273 3,3, 1274 (double*)&point, 1275 1,3, 1276 tmpVect1); 1277 1278 icvAddVector_64d ( tmpVect1, transVect,tmpVect2, 3); 1279 1280 icvMulMatrix_64d ( camMatr, 1281 3,3, 1282 tmpVect2, 1283 1,3, 1284 tmpVect1); 1285 1286 projPoint->x = tmpVect1[0] / tmpVect1[2]; 1287 projPoint->y = tmpVect1[1] / tmpVect1[2]; 1288 1289 return; 1290 } 1291 1292 /*---------------------------------------------------------------------------------------*/ 1293 /* Get quads for transform images */ 1294 void icvGetQuadsTransform( 1295 CvSize imageSize, 1296 CvMatr64d camMatr1, 1297 CvMatr64d rotMatr1, 1298 CvVect64d transVect1, 1299 CvMatr64d camMatr2, 1300 CvMatr64d rotMatr2, 1301 CvVect64d transVect2, 1302 CvSize* warpSize, 1303 double quad1[4][2], 1304 double quad2[4][2], 1305 CvMatr64d fundMatr, 1306 CvPoint3D64d* epipole1, 1307 CvPoint3D64d* epipole2 1308 ) 1309 { 1310 /* First compute fundamental matrix and epipoles */ 1311 int res; 1312 1313 1314 /* Compute epipoles and fundamental matrix using new functions */ 1315 { 1316 double convRotMatr[9]; 1317 double convTransVect[3]; 1318 1319 icvCreateConvertMatrVect( rotMatr1, 1320 transVect1, 1321 rotMatr2, 1322 transVect2, 1323 convRotMatr, 1324 convTransVect); 1325 float convRotMatr_32f[9]; 1326 float convTransVect_32f[3]; 1327 1328 icvCvt_64d_32f(convRotMatr,convRotMatr_32f,9); 1329 icvCvt_64d_32f(convTransVect,convTransVect_32f,3); 1330 1331 /* We know R and t */ 1332 /* Compute essential matrix */ 1333 float essMatr[9]; 1334 float fundMatr_32f[9]; 1335 1336 float camMatr1_32f[9]; 1337 float camMatr2_32f[9]; 1338 1339 icvCvt_64d_32f(camMatr1,camMatr1_32f,9); 1340 icvCvt_64d_32f(camMatr2,camMatr2_32f,9); 1341 1342 cvComputeEssentialMatrix( convRotMatr_32f, 1343 convTransVect_32f, 1344 essMatr); 1345 1346 cvConvertEssential2Fundamental( essMatr, 1347 fundMatr_32f, 1348 camMatr1_32f, 1349 camMatr2_32f); 1350 1351 CvPoint3D32f epipole1_32f; 1352 CvPoint3D32f epipole2_32f; 1353 1354 cvComputeEpipolesFromFundMatrix( fundMatr_32f, 1355 &epipole1_32f, 1356 &epipole2_32f); 1357 /* copy to 64d epipoles */ 1358 epipole1->x = epipole1_32f.x; 1359 epipole1->y = epipole1_32f.y; 1360 epipole1->z = epipole1_32f.z; 1361 1362 epipole2->x = epipole2_32f.x; 1363 epipole2->y = epipole2_32f.y; 1364 epipole2->z = epipole2_32f.z; 1365 1366 /* Convert fundamental matrix */ 1367 icvCvt_32f_64d(fundMatr_32f,fundMatr,9); 1368 } 1369 1370 double coeff11[3]; 1371 double coeff12[3]; 1372 double coeff21[3]; 1373 double coeff22[3]; 1374 1375 icvGetCommonArea( imageSize, 1376 *epipole1,*epipole2, 1377 fundMatr, 1378 coeff11,coeff12, 1379 coeff21,coeff22, 1380 &res); 1381 1382 CvPoint2D64d point11, point12,point21, point22; 1383 double width1,width2; 1384 double height1,height2; 1385 double tmpHeight1,tmpHeight2; 1386 1387 CvPoint2D64d epipole1_2d; 1388 CvPoint2D64d epipole2_2d; 1389 1390 /* ----- Image 1 ----- */ 1391 if( fabs(epipole1->z) < 1e-8 ) 1392 { 1393 return; 1394 } 1395 epipole1_2d.x = epipole1->x / epipole1->z; 1396 epipole1_2d.y = epipole1->y / epipole1->z; 1397 1398 icvGetCutPiece( coeff11,coeff12, 1399 epipole1_2d, 1400 imageSize, 1401 &point11,&point12, 1402 &point21,&point22, 1403 &res); 1404 1405 /* Compute distance */ 1406 icvGetPieceLength(point11,point21,&width1); 1407 icvGetPieceLength(point11,point12,&tmpHeight1); 1408 icvGetPieceLength(point21,point22,&tmpHeight2); 1409 height1 = MAX(tmpHeight1,tmpHeight2); 1410 1411 quad1[0][0] = point11.x; 1412 quad1[0][1] = point11.y; 1413 1414 quad1[1][0] = point21.x; 1415 quad1[1][1] = point21.y; 1416 1417 quad1[2][0] = point22.x; 1418 quad1[2][1] = point22.y; 1419 1420 quad1[3][0] = point12.x; 1421 quad1[3][1] = point12.y; 1422 1423 /* ----- Image 2 ----- */ 1424 if( fabs(epipole2->z) < 1e-8 ) 1425 { 1426 return; 1427 } 1428 epipole2_2d.x = epipole2->x / epipole2->z; 1429 epipole2_2d.y = epipole2->y / epipole2->z; 1430 1431 icvGetCutPiece( coeff21,coeff22, 1432 epipole2_2d, 1433 imageSize, 1434 &point11,&point12, 1435 &point21,&point22, 1436 &res); 1437 1438 /* Compute distance */ 1439 icvGetPieceLength(point11,point21,&width2); 1440 icvGetPieceLength(point11,point12,&tmpHeight1); 1441 icvGetPieceLength(point21,point22,&tmpHeight2); 1442 height2 = MAX(tmpHeight1,tmpHeight2); 1443 1444 quad2[0][0] = point11.x; 1445 quad2[0][1] = point11.y; 1446 1447 quad2[1][0] = point21.x; 1448 quad2[1][1] = point21.y; 1449 1450 quad2[2][0] = point22.x; 1451 quad2[2][1] = point22.y; 1452 1453 quad2[3][0] = point12.x; 1454 quad2[3][1] = point12.y; 1455 1456 1457 /*=======================================================*/ 1458 /* This is a new additional way to compute quads. */ 1459 /* We must correct quads */ 1460 { 1461 double convRotMatr[9]; 1462 double convTransVect[3]; 1463 1464 double newQuad1[4][2]; 1465 double newQuad2[4][2]; 1466 1467 1468 icvCreateConvertMatrVect( rotMatr1, 1469 transVect1, 1470 rotMatr2, 1471 transVect2, 1472 convRotMatr, 1473 convTransVect); 1474 1475 /* -------------Compute for first image-------------- */ 1476 CvPoint2D32f pointb1; 1477 CvPoint2D32f pointe1; 1478 1479 CvPoint2D32f pointb2; 1480 CvPoint2D32f pointe2; 1481 1482 pointb1.x = (float)quad1[0][0]; 1483 pointb1.y = (float)quad1[0][1]; 1484 1485 pointe1.x = (float)quad1[3][0]; 1486 pointe1.y = (float)quad1[3][1]; 1487 1488 icvComputeeInfiniteProject1(convRotMatr, 1489 camMatr1, 1490 camMatr2, 1491 pointb1, 1492 &pointb2); 1493 1494 icvComputeeInfiniteProject1(convRotMatr, 1495 camMatr1, 1496 camMatr2, 1497 pointe1, 1498 &pointe2); 1499 1500 /* JUST TEST FOR POINT */ 1501 1502 /* Compute distances */ 1503 double dxOld,dyOld; 1504 double dxNew,dyNew; 1505 double distOld,distNew; 1506 1507 dxOld = quad2[1][0] - quad2[0][0]; 1508 dyOld = quad2[1][1] - quad2[0][1]; 1509 distOld = dxOld*dxOld + dyOld*dyOld; 1510 1511 dxNew = quad2[1][0] - pointb2.x; 1512 dyNew = quad2[1][1] - pointb2.y; 1513 distNew = dxNew*dxNew + dyNew*dyNew; 1514 1515 if( distNew > distOld ) 1516 {/* Get new points for second quad */ 1517 newQuad2[0][0] = pointb2.x; 1518 newQuad2[0][1] = pointb2.y; 1519 newQuad2[3][0] = pointe2.x; 1520 newQuad2[3][1] = pointe2.y; 1521 newQuad1[0][0] = quad1[0][0]; 1522 newQuad1[0][1] = quad1[0][1]; 1523 newQuad1[3][0] = quad1[3][0]; 1524 newQuad1[3][1] = quad1[3][1]; 1525 } 1526 else 1527 {/* Get new points for first quad */ 1528 1529 pointb2.x = (float)quad2[0][0]; 1530 pointb2.y = (float)quad2[0][1]; 1531 1532 pointe2.x = (float)quad2[3][0]; 1533 pointe2.y = (float)quad2[3][1]; 1534 1535 icvComputeeInfiniteProject2(convRotMatr, 1536 camMatr1, 1537 camMatr2, 1538 &pointb1, 1539 pointb2); 1540 1541 icvComputeeInfiniteProject2(convRotMatr, 1542 camMatr1, 1543 camMatr2, 1544 &pointe1, 1545 pointe2); 1546 1547 1548 /* JUST TEST FOR POINT */ 1549 1550 newQuad2[0][0] = quad2[0][0]; 1551 newQuad2[0][1] = quad2[0][1]; 1552 newQuad2[3][0] = quad2[3][0]; 1553 newQuad2[3][1] = quad2[3][1]; 1554 1555 newQuad1[0][0] = pointb1.x; 1556 newQuad1[0][1] = pointb1.y; 1557 newQuad1[3][0] = pointe1.x; 1558 newQuad1[3][1] = pointe1.y; 1559 } 1560 1561 /* -------------Compute for second image-------------- */ 1562 pointb1.x = (float)quad1[1][0]; 1563 pointb1.y = (float)quad1[1][1]; 1564 1565 pointe1.x = (float)quad1[2][0]; 1566 pointe1.y = (float)quad1[2][1]; 1567 1568 icvComputeeInfiniteProject1(convRotMatr, 1569 camMatr1, 1570 camMatr2, 1571 pointb1, 1572 &pointb2); 1573 1574 icvComputeeInfiniteProject1(convRotMatr, 1575 camMatr1, 1576 camMatr2, 1577 pointe1, 1578 &pointe2); 1579 1580 /* Compute distances */ 1581 1582 dxOld = quad2[0][0] - quad2[1][0]; 1583 dyOld = quad2[0][1] - quad2[1][1]; 1584 distOld = dxOld*dxOld + dyOld*dyOld; 1585 1586 dxNew = quad2[0][0] - pointb2.x; 1587 dyNew = quad2[0][1] - pointb2.y; 1588 distNew = dxNew*dxNew + dyNew*dyNew; 1589 1590 if( distNew > distOld ) 1591 {/* Get new points for second quad */ 1592 newQuad2[1][0] = pointb2.x; 1593 newQuad2[1][1] = pointb2.y; 1594 newQuad2[2][0] = pointe2.x; 1595 newQuad2[2][1] = pointe2.y; 1596 newQuad1[1][0] = quad1[1][0]; 1597 newQuad1[1][1] = quad1[1][1]; 1598 newQuad1[2][0] = quad1[2][0]; 1599 newQuad1[2][1] = quad1[2][1]; 1600 } 1601 else 1602 {/* Get new points for first quad */ 1603 1604 pointb2.x = (float)quad2[1][0]; 1605 pointb2.y = (float)quad2[1][1]; 1606 1607 pointe2.x = (float)quad2[2][0]; 1608 pointe2.y = (float)quad2[2][1]; 1609 1610 icvComputeeInfiniteProject2(convRotMatr, 1611 camMatr1, 1612 camMatr2, 1613 &pointb1, 1614 pointb2); 1615 1616 icvComputeeInfiniteProject2(convRotMatr, 1617 camMatr1, 1618 camMatr2, 1619 &pointe1, 1620 pointe2); 1621 1622 newQuad2[1][0] = quad2[1][0]; 1623 newQuad2[1][1] = quad2[1][1]; 1624 newQuad2[2][0] = quad2[2][0]; 1625 newQuad2[2][1] = quad2[2][1]; 1626 1627 newQuad1[1][0] = pointb1.x; 1628 newQuad1[1][1] = pointb1.y; 1629 newQuad1[2][0] = pointe1.x; 1630 newQuad1[2][1] = pointe1.y; 1631 } 1632 1633 1634 1635 /*-------------------------------------------------------------------------------*/ 1636 1637 /* Copy new quads to old quad */ 1638 int i; 1639 for( i = 0; i < 4; i++ ) 1640 { 1641 { 1642 quad1[i][0] = newQuad1[i][0]; 1643 quad1[i][1] = newQuad1[i][1]; 1644 quad2[i][0] = newQuad2[i][0]; 1645 quad2[i][1] = newQuad2[i][1]; 1646 } 1647 } 1648 } 1649 /*=======================================================*/ 1650 1651 double warpWidth,warpHeight; 1652 1653 warpWidth = MAX(width1,width2); 1654 warpHeight = MAX(height1,height2); 1655 1656 warpSize->width = (int)warpWidth; 1657 warpSize->height = (int)warpHeight; 1658 1659 warpSize->width = cvRound(warpWidth-1); 1660 warpSize->height = cvRound(warpHeight-1); 1661 1662 /* !!! by Valery Mosyagin. this lines added just for test no warp */ 1663 warpSize->width = imageSize.width; 1664 warpSize->height = imageSize.height; 1665 1666 return; 1667 } 1668 1669 1670 /*---------------------------------------------------------------------------------------*/ 1671 1672 void icvGetQuadsTransformNew( CvSize imageSize, 1673 CvMatr32f camMatr1, 1674 CvMatr32f camMatr2, 1675 CvMatr32f rotMatr1, 1676 CvVect32f transVect1, 1677 CvSize* warpSize, 1678 double quad1[4][2], 1679 double quad2[4][2], 1680 CvMatr32f fundMatr, 1681 CvPoint3D32f* epipole1, 1682 CvPoint3D32f* epipole2 1683 ) 1684 { 1685 /* Convert data */ 1686 /* Convert camera matrix */ 1687 double camMatr1_64d[9]; 1688 double camMatr2_64d[9]; 1689 double rotMatr1_64d[9]; 1690 double transVect1_64d[3]; 1691 double rotMatr2_64d[9]; 1692 double transVect2_64d[3]; 1693 double fundMatr_64d[9]; 1694 CvPoint3D64d epipole1_64d; 1695 CvPoint3D64d epipole2_64d; 1696 1697 icvCvt_32f_64d(camMatr1,camMatr1_64d,9); 1698 icvCvt_32f_64d(camMatr2,camMatr2_64d,9); 1699 icvCvt_32f_64d(rotMatr1,rotMatr1_64d,9); 1700 icvCvt_32f_64d(transVect1,transVect1_64d,3); 1701 1702 /* Create vector and matrix */ 1703 1704 rotMatr2_64d[0] = 1; 1705 rotMatr2_64d[1] = 0; 1706 rotMatr2_64d[2] = 0; 1707 rotMatr2_64d[3] = 0; 1708 rotMatr2_64d[4] = 1; 1709 rotMatr2_64d[5] = 0; 1710 rotMatr2_64d[6] = 0; 1711 rotMatr2_64d[7] = 0; 1712 rotMatr2_64d[8] = 1; 1713 1714 transVect2_64d[0] = 0; 1715 transVect2_64d[1] = 0; 1716 transVect2_64d[2] = 0; 1717 1718 icvGetQuadsTransform( imageSize, 1719 camMatr1_64d, 1720 rotMatr1_64d, 1721 transVect1_64d, 1722 camMatr2_64d, 1723 rotMatr2_64d, 1724 transVect2_64d, 1725 warpSize, 1726 quad1, 1727 quad2, 1728 fundMatr_64d, 1729 &epipole1_64d, 1730 &epipole2_64d 1731 ); 1732 1733 /* Convert epipoles */ 1734 epipole1->x = (float)(epipole1_64d.x); 1735 epipole1->y = (float)(epipole1_64d.y); 1736 epipole1->z = (float)(epipole1_64d.z); 1737 1738 epipole2->x = (float)(epipole2_64d.x); 1739 epipole2->y = (float)(epipole2_64d.y); 1740 epipole2->z = (float)(epipole2_64d.z); 1741 1742 /* Convert fundamental matrix */ 1743 icvCvt_64d_32f(fundMatr_64d,fundMatr,9); 1744 1745 return; 1746 } 1747 1748 /*---------------------------------------------------------------------------------------*/ 1749 void icvGetQuadsTransformStruct( CvStereoCamera* stereoCamera) 1750 { 1751 /* Wrapper for icvGetQuadsTransformNew */ 1752 1753 1754 double quad1[4][2]; 1755 double quad2[4][2]; 1756 1757 icvGetQuadsTransformNew( cvSize(cvRound(stereoCamera->camera[0]->imgSize[0]),cvRound(stereoCamera->camera[0]->imgSize[1])), 1758 stereoCamera->camera[0]->matrix, 1759 stereoCamera->camera[1]->matrix, 1760 stereoCamera->rotMatrix, 1761 stereoCamera->transVector, 1762 &(stereoCamera->warpSize), 1763 quad1, 1764 quad2, 1765 stereoCamera->fundMatr, 1766 &(stereoCamera->epipole[0]), 1767 &(stereoCamera->epipole[1]) 1768 ); 1769 1770 int i; 1771 for( i = 0; i < 4; i++ ) 1772 { 1773 stereoCamera->quad[0][i] = cvPoint2D32f(quad1[i][0],quad1[i][1]); 1774 stereoCamera->quad[1][i] = cvPoint2D32f(quad2[i][0],quad2[i][1]); 1775 } 1776 1777 return; 1778 } 1779 1780 /*---------------------------------------------------------------------------------------*/ 1781 void icvComputeStereoParamsForCameras(CvStereoCamera* stereoCamera) 1782 { 1783 /* For given intrinsic and extrinsic parameters computes rest parameters 1784 ** such as fundamental matrix. warping coeffs, epipoles, ... 1785 */ 1786 1787 1788 /* compute rotate matrix and translate vector */ 1789 double rotMatr1[9]; 1790 double rotMatr2[9]; 1791 1792 double transVect1[3]; 1793 double transVect2[3]; 1794 1795 double convRotMatr[9]; 1796 double convTransVect[3]; 1797 1798 /* fill matrices */ 1799 icvCvt_32f_64d(stereoCamera->camera[0]->rotMatr,rotMatr1,9); 1800 icvCvt_32f_64d(stereoCamera->camera[1]->rotMatr,rotMatr2,9); 1801 1802 icvCvt_32f_64d(stereoCamera->camera[0]->transVect,transVect1,3); 1803 icvCvt_32f_64d(stereoCamera->camera[1]->transVect,transVect2,3); 1804 1805 icvCreateConvertMatrVect( rotMatr1, 1806 transVect1, 1807 rotMatr2, 1808 transVect2, 1809 convRotMatr, 1810 convTransVect); 1811 1812 /* copy to stereo camera params */ 1813 icvCvt_64d_32f(convRotMatr,stereoCamera->rotMatrix,9); 1814 icvCvt_64d_32f(convTransVect,stereoCamera->transVector,3); 1815 1816 1817 icvGetQuadsTransformStruct(stereoCamera); 1818 icvComputeRestStereoParams(stereoCamera); 1819 } 1820 1821 1822 1823 /*---------------------------------------------------------------------------------------*/ 1824 1825 /* Get cut line for one image */ 1826 void icvGetCutPiece( CvVect64d areaLineCoef1,CvVect64d areaLineCoef2, 1827 CvPoint2D64d epipole, 1828 CvSize imageSize, 1829 CvPoint2D64d* point11,CvPoint2D64d* point12, 1830 CvPoint2D64d* point21,CvPoint2D64d* point22, 1831 int* result) 1832 { 1833 /* Compute nearest cut line to epipole */ 1834 /* Get corners inside sector */ 1835 /* Collect all candidate point */ 1836 1837 CvPoint2D64d candPoints[8]; 1838 CvPoint2D64d midPoint; 1839 int numPoints = 0; 1840 int res; 1841 int i; 1842 1843 double cutLine1[3]; 1844 double cutLine2[3]; 1845 1846 /* Find middle line of sector */ 1847 double midLine[3]; 1848 1849 1850 /* Different way */ 1851 CvPoint2D64d pointOnLine1; pointOnLine1.x = pointOnLine1.y = 0; 1852 CvPoint2D64d pointOnLine2; pointOnLine2.x = pointOnLine2.y = 0; 1853 1854 CvPoint2D64d start1,end1; 1855 1856 icvGetCrossRectDirect( imageSize, 1857 areaLineCoef1[0],areaLineCoef1[1],areaLineCoef1[2], 1858 &start1,&end1,&res); 1859 if( res > 0 ) 1860 { 1861 pointOnLine1 = start1; 1862 } 1863 1864 icvGetCrossRectDirect( imageSize, 1865 areaLineCoef2[0],areaLineCoef2[1],areaLineCoef2[2], 1866 &start1,&end1,&res); 1867 if( res > 0 ) 1868 { 1869 pointOnLine2 = start1; 1870 } 1871 1872 icvGetMiddleAnglePoint(epipole,pointOnLine1,pointOnLine2,&midPoint); 1873 1874 icvGetCoefForPiece(epipole,midPoint,&midLine[0],&midLine[1],&midLine[2],&res); 1875 1876 /* Test corner points */ 1877 CvPoint2D64d cornerPoint; 1878 CvPoint2D64d tmpPoints[2]; 1879 1880 cornerPoint.x = 0; 1881 cornerPoint.y = 0; 1882 icvTestPoint( cornerPoint, areaLineCoef1, areaLineCoef2, epipole, &res); 1883 if( res == 1 ) 1884 {/* Add point */ 1885 candPoints[numPoints] = cornerPoint; 1886 numPoints++; 1887 } 1888 1889 cornerPoint.x = imageSize.width; 1890 cornerPoint.y = 0; 1891 icvTestPoint( cornerPoint, areaLineCoef1, areaLineCoef2, epipole, &res); 1892 if( res == 1 ) 1893 {/* Add point */ 1894 candPoints[numPoints] = cornerPoint; 1895 numPoints++; 1896 } 1897 1898 cornerPoint.x = imageSize.width; 1899 cornerPoint.y = imageSize.height; 1900 icvTestPoint( cornerPoint, areaLineCoef1, areaLineCoef2, epipole, &res); 1901 if( res == 1 ) 1902 {/* Add point */ 1903 candPoints[numPoints] = cornerPoint; 1904 numPoints++; 1905 } 1906 1907 cornerPoint.x = 0; 1908 cornerPoint.y = imageSize.height; 1909 icvTestPoint( cornerPoint, areaLineCoef1, areaLineCoef2, epipole, &res); 1910 if( res == 1 ) 1911 {/* Add point */ 1912 candPoints[numPoints] = cornerPoint; 1913 numPoints++; 1914 } 1915 1916 /* Find cross line 1 with image border */ 1917 icvGetCrossRectDirect( imageSize, 1918 areaLineCoef1[0],areaLineCoef1[1],areaLineCoef1[2], 1919 &tmpPoints[0], &tmpPoints[1], 1920 &res); 1921 for( i = 0; i < res; i++ ) 1922 { 1923 candPoints[numPoints++] = tmpPoints[i]; 1924 } 1925 1926 /* Find cross line 2 with image border */ 1927 icvGetCrossRectDirect( imageSize, 1928 areaLineCoef2[0],areaLineCoef2[1],areaLineCoef2[2], 1929 &tmpPoints[0], &tmpPoints[1], 1930 &res); 1931 1932 for( i = 0; i < res; i++ ) 1933 { 1934 candPoints[numPoints++] = tmpPoints[i]; 1935 } 1936 1937 if( numPoints < 2 ) 1938 { 1939 *result = 0; 1940 return;/* Error. Not enought points */ 1941 } 1942 /* Project all points to middle line and get max and min */ 1943 1944 CvPoint2D64d projPoint; 1945 CvPoint2D64d minPoint; minPoint.x = minPoint.y = FLT_MAX; 1946 CvPoint2D64d maxPoint; maxPoint.x = maxPoint.y = -FLT_MAX; 1947 1948 1949 double dist; 1950 double maxDist = 0; 1951 double minDist = 10000000; 1952 1953 1954 for( i = 0; i < numPoints; i++ ) 1955 { 1956 icvProjectPointToDirect(candPoints[i], midLine, &projPoint); 1957 icvGetPieceLength(epipole,projPoint,&dist); 1958 if( dist < minDist) 1959 { 1960 minDist = dist; 1961 minPoint = projPoint; 1962 } 1963 1964 if( dist > maxDist) 1965 { 1966 maxDist = dist; 1967 maxPoint = projPoint; 1968 } 1969 } 1970 1971 /* We know maximum and minimum points. Now we can compute cut lines */ 1972 1973 icvGetNormalDirect(midLine,minPoint,cutLine1); 1974 icvGetNormalDirect(midLine,maxPoint,cutLine2); 1975 1976 /* Test for begin of line. */ 1977 CvPoint2D64d tmpPoint2; 1978 1979 /* Get cross with */ 1980 icvGetCrossDirectDirect(areaLineCoef1,cutLine1,point11,&res); 1981 icvGetCrossDirectDirect(areaLineCoef2,cutLine1,point12,&res); 1982 1983 icvGetCrossDirectDirect(areaLineCoef1,cutLine2,point21,&res); 1984 icvGetCrossDirectDirect(areaLineCoef2,cutLine2,point22,&res); 1985 1986 if( epipole.x > imageSize.width * 0.5 ) 1987 {/* Need to change points */ 1988 tmpPoint2 = *point11; 1989 *point11 = *point21; 1990 *point21 = tmpPoint2; 1991 1992 tmpPoint2 = *point12; 1993 *point12 = *point22; 1994 *point22 = tmpPoint2; 1995 } 1996 1997 return; 1998 } 1999 /*---------------------------------------------------------------------------------------*/ 2000 /* Get middle angle */ 2001 void icvGetMiddleAnglePoint( CvPoint2D64d basePoint, 2002 CvPoint2D64d point1,CvPoint2D64d point2, 2003 CvPoint2D64d* midPoint) 2004 {/* !!! May be need to return error */ 2005 2006 double dist1; 2007 double dist2; 2008 icvGetPieceLength(basePoint,point1,&dist1); 2009 icvGetPieceLength(basePoint,point2,&dist2); 2010 CvPoint2D64d pointNew1; 2011 CvPoint2D64d pointNew2; 2012 double alpha = dist2/dist1; 2013 2014 pointNew1.x = basePoint.x + (1.0/alpha) * ( point2.x - basePoint.x ); 2015 pointNew1.y = basePoint.y + (1.0/alpha) * ( point2.y - basePoint.y ); 2016 2017 pointNew2.x = basePoint.x + alpha * ( point1.x - basePoint.x ); 2018 pointNew2.y = basePoint.y + alpha * ( point1.y - basePoint.y ); 2019 2020 int res; 2021 icvGetCrossPiecePiece(point1,point2,pointNew1,pointNew2,midPoint,&res); 2022 2023 return; 2024 } 2025 2026 /*---------------------------------------------------------------------------------------*/ 2027 /* Get normal direct to direct in line */ 2028 void icvGetNormalDirect(CvVect64d direct,CvPoint2D64d point,CvVect64d normDirect) 2029 { 2030 normDirect[0] = direct[1]; 2031 normDirect[1] = - direct[0]; 2032 normDirect[2] = -(normDirect[0]*point.x + normDirect[1]*point.y); 2033 return; 2034 } 2035 2036 /*---------------------------------------------------------------------------------------*/ 2037 CV_IMPL double icvGetVect(CvPoint2D64d basePoint,CvPoint2D64d point1,CvPoint2D64d point2) 2038 { 2039 return (point1.x - basePoint.x)*(point2.y - basePoint.y) - 2040 (point2.x - basePoint.x)*(point1.y - basePoint.y); 2041 } 2042 /*---------------------------------------------------------------------------------------*/ 2043 /* Test for point in sector */ 2044 /* Return 0 - point not inside sector */ 2045 /* Return 1 - point inside sector */ 2046 void icvTestPoint( CvPoint2D64d testPoint, 2047 CvVect64d line1,CvVect64d line2, 2048 CvPoint2D64d basePoint, 2049 int* result) 2050 { 2051 CvPoint2D64d point1,point2; 2052 2053 icvProjectPointToDirect(testPoint,line1,&point1); 2054 icvProjectPointToDirect(testPoint,line2,&point2); 2055 2056 double sign1 = icvGetVect(basePoint,point1,point2); 2057 double sign2 = icvGetVect(basePoint,point1,testPoint); 2058 if( sign1 * sign2 > 0 ) 2059 {/* Correct for first line */ 2060 sign1 = - sign1; 2061 sign2 = icvGetVect(basePoint,point2,testPoint); 2062 if( sign1 * sign2 > 0 ) 2063 {/* Correct for both lines */ 2064 *result = 1; 2065 } 2066 else 2067 { 2068 *result = 0; 2069 } 2070 } 2071 else 2072 { 2073 *result = 0; 2074 } 2075 2076 return; 2077 } 2078 2079 /*---------------------------------------------------------------------------------------*/ 2080 /* Project point to line */ 2081 void icvProjectPointToDirect( CvPoint2D64d point,CvVect64d lineCoeff, 2082 CvPoint2D64d* projectPoint) 2083 { 2084 double a = lineCoeff[0]; 2085 double b = lineCoeff[1]; 2086 2087 double det = 1.0 / ( a*a + b*b ); 2088 double delta = a*point.y - b*point.x; 2089 2090 projectPoint->x = ( -a*lineCoeff[2] - b * delta ) * det; 2091 projectPoint->y = ( -b*lineCoeff[2] + a * delta ) * det ; 2092 2093 return; 2094 } 2095 2096 /*---------------------------------------------------------------------------------------*/ 2097 /* Get distance from point to direction */ 2098 void icvGetDistanceFromPointToDirect( CvPoint2D64d point,CvVect64d lineCoef,double*dist) 2099 { 2100 CvPoint2D64d tmpPoint; 2101 icvProjectPointToDirect(point,lineCoef,&tmpPoint); 2102 double dx = point.x - tmpPoint.x; 2103 double dy = point.y - tmpPoint.y; 2104 *dist = sqrt(dx*dx+dy*dy); 2105 return; 2106 } 2107 /*---------------------------------------------------------------------------------------*/ 2108 2109 CV_IMPL IplImage* icvCreateIsometricImage( IplImage* src, IplImage* dst, 2110 int desired_depth, int desired_num_channels ) 2111 { 2112 CvSize src_size ; 2113 src_size.width = src->width; 2114 src_size.height = src->height; 2115 2116 CvSize dst_size = src_size; 2117 2118 if( dst ) 2119 { 2120 dst_size.width = dst->width; 2121 dst_size.height = dst->height; 2122 } 2123 2124 if( !dst || dst->depth != desired_depth || 2125 dst->nChannels != desired_num_channels || 2126 dst_size.width != src_size.width || 2127 dst_size.height != dst_size.height ) 2128 { 2129 cvReleaseImage( &dst ); 2130 dst = cvCreateImage( src_size, desired_depth, desired_num_channels ); 2131 CvRect rect = cvRect(0,0,src_size.width,src_size.height); 2132 cvSetImageROI( dst, rect ); 2133 2134 } 2135 2136 return dst; 2137 } 2138 2139 int 2140 icvCvt_32f_64d( float *src, double *dst, int size ) 2141 { 2142 int t; 2143 2144 if( !src || !dst ) 2145 return CV_NULLPTR_ERR; 2146 if( size <= 0 ) 2147 return CV_BADRANGE_ERR; 2148 2149 for( t = 0; t < size; t++ ) 2150 { 2151 dst[t] = (double) (src[t]); 2152 } 2153 2154 return CV_OK; 2155 } 2156 2157 /*======================================================================================*/ 2158 /* Type conversion double -> float */ 2159 int 2160 icvCvt_64d_32f( double *src, float *dst, int size ) 2161 { 2162 int t; 2163 2164 if( !src || !dst ) 2165 return CV_NULLPTR_ERR; 2166 if( size <= 0 ) 2167 return CV_BADRANGE_ERR; 2168 2169 for( t = 0; t < size; t++ ) 2170 { 2171 dst[t] = (float) (src[t]); 2172 } 2173 2174 return CV_OK; 2175 } 2176 2177 /*----------------------------------------------------------------------------------*/ 2178 2179 2180 /* Find line which cross frame by line(a,b,c) */ 2181 void FindLineForEpiline( CvSize imageSize, 2182 float a,float b,float c, 2183 CvPoint2D32f *start,CvPoint2D32f *end, 2184 int* result) 2185 { 2186 result = result; 2187 CvPoint2D32f frameBeg; 2188 2189 CvPoint2D32f frameEnd; 2190 CvPoint2D32f cross[4]; 2191 int haveCross[4]; 2192 float dist; 2193 2194 haveCross[0] = 0; 2195 haveCross[1] = 0; 2196 haveCross[2] = 0; 2197 haveCross[3] = 0; 2198 2199 frameBeg.x = 0; 2200 frameBeg.y = 0; 2201 frameEnd.x = (float)(imageSize.width); 2202 frameEnd.y = 0; 2203 haveCross[0] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[0]); 2204 2205 frameBeg.x = (float)(imageSize.width); 2206 frameBeg.y = 0; 2207 frameEnd.x = (float)(imageSize.width); 2208 frameEnd.y = (float)(imageSize.height); 2209 haveCross[1] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[1]); 2210 2211 frameBeg.x = (float)(imageSize.width); 2212 frameBeg.y = (float)(imageSize.height); 2213 frameEnd.x = 0; 2214 frameEnd.y = (float)(imageSize.height); 2215 haveCross[2] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[2]); 2216 2217 frameBeg.x = 0; 2218 frameBeg.y = (float)(imageSize.height); 2219 frameEnd.x = 0; 2220 frameEnd.y = 0; 2221 haveCross[3] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[3]); 2222 2223 int n; 2224 float minDist = (float)(INT_MAX); 2225 float maxDist = (float)(INT_MIN); 2226 2227 int maxN = -1; 2228 int minN = -1; 2229 2230 double midPointX = imageSize.width / 2.0; 2231 double midPointY = imageSize.height / 2.0; 2232 2233 for( n = 0; n < 4; n++ ) 2234 { 2235 if( haveCross[n] > 0 ) 2236 { 2237 dist = (float)((midPointX - cross[n].x)*(midPointX - cross[n].x) + 2238 (midPointY - cross[n].y)*(midPointY - cross[n].y)); 2239 2240 if( dist < minDist ) 2241 { 2242 minDist = dist; 2243 minN = n; 2244 } 2245 2246 if( dist > maxDist ) 2247 { 2248 maxDist = dist; 2249 maxN = n; 2250 } 2251 } 2252 } 2253 2254 if( minN >= 0 && maxN >= 0 && (minN != maxN) ) 2255 { 2256 *start = cross[minN]; 2257 *end = cross[maxN]; 2258 } 2259 else 2260 { 2261 start->x = 0; 2262 start->y = 0; 2263 end->x = 0; 2264 end->y = 0; 2265 } 2266 2267 return; 2268 2269 } 2270 2271 2272 /*----------------------------------------------------------------------------------*/ 2273 2274 int GetAngleLinee( CvPoint2D32f epipole, CvSize imageSize,CvPoint2D32f point1,CvPoint2D32f point2) 2275 { 2276 float width = (float)(imageSize.width); 2277 float height = (float)(imageSize.height); 2278 2279 /* Get crosslines with image corners */ 2280 2281 /* Find four lines */ 2282 2283 CvPoint2D32f pa,pb,pc,pd; 2284 2285 pa.x = 0; 2286 pa.y = 0; 2287 2288 pb.x = width; 2289 pb.y = 0; 2290 2291 pd.x = width; 2292 pd.y = height; 2293 2294 pc.x = 0; 2295 pc.y = height; 2296 2297 /* We can compute points for angle */ 2298 /* Test for place section */ 2299 2300 float x,y; 2301 x = epipole.x; 2302 y = epipole.y; 2303 2304 if( x < 0 ) 2305 {/* 1,4,7 */ 2306 if( y < 0) 2307 {/* 1 */ 2308 point1 = pb; 2309 point2 = pc; 2310 } 2311 else if( y > height ) 2312 {/* 7 */ 2313 point1 = pa; 2314 point2 = pd; 2315 } 2316 else 2317 {/* 4 */ 2318 point1 = pa; 2319 point2 = pc; 2320 } 2321 } 2322 else if ( x > width ) 2323 {/* 3,6,9 */ 2324 if( y < 0 ) 2325 {/* 3 */ 2326 point1 = pa; 2327 point2 = pd; 2328 } 2329 else if ( y > height ) 2330 {/* 9 */ 2331 point1 = pc; 2332 point2 = pb; 2333 } 2334 else 2335 {/* 6 */ 2336 point1 = pb; 2337 point2 = pd; 2338 } 2339 } 2340 else 2341 {/* 2,5,8 */ 2342 if( y < 0 ) 2343 {/* 2 */ 2344 point1 = pa; 2345 point2 = pb; 2346 } 2347 else if( y > height ) 2348 {/* 8 */ 2349 point1 = pc; 2350 point2 = pd; 2351 } 2352 else 2353 {/* 5 - point in the image */ 2354 return 2; 2355 } 2356 2357 2358 } 2359 2360 2361 return 0; 2362 } 2363 2364 /*--------------------------------------------------------------------------------------*/ 2365 void icvComputePerspectiveCoeffs(const CvPoint2D32f srcQuad[4],const CvPoint2D32f dstQuad[4],double coeffs[3][3]) 2366 {/* Computes perspective coeffs for transformation from src to dst quad */ 2367 2368 2369 CV_FUNCNAME( "icvComputePerspectiveCoeffs" ); 2370 2371 __BEGIN__; 2372 2373 double A[64]; 2374 double b[8]; 2375 double c[8]; 2376 CvPoint2D32f pt[4]; 2377 int i; 2378 2379 pt[0] = srcQuad[0]; 2380 pt[1] = srcQuad[1]; 2381 pt[2] = srcQuad[2]; 2382 pt[3] = srcQuad[3]; 2383 2384 for( i = 0; i < 4; i++ ) 2385 { 2386 #if 0 2387 double x = dstQuad[i].x; 2388 double y = dstQuad[i].y; 2389 double X = pt[i].x; 2390 double Y = pt[i].y; 2391 #else 2392 double x = pt[i].x; 2393 double y = pt[i].y; 2394 double X = dstQuad[i].x; 2395 double Y = dstQuad[i].y; 2396 #endif 2397 double* a = A + i*16; 2398 2399 a[0] = x; 2400 a[1] = y; 2401 a[2] = 1; 2402 a[3] = 0; 2403 a[4] = 0; 2404 a[5] = 0; 2405 a[6] = -X*x; 2406 a[7] = -X*y; 2407 2408 a += 8; 2409 2410 a[0] = 0; 2411 a[1] = 0; 2412 a[2] = 0; 2413 a[3] = x; 2414 a[4] = y; 2415 a[5] = 1; 2416 a[6] = -Y*x; 2417 a[7] = -Y*y; 2418 2419 b[i*2] = X; 2420 b[i*2 + 1] = Y; 2421 } 2422 2423 { 2424 double invA[64]; 2425 CvMat matA = cvMat( 8, 8, CV_64F, A ); 2426 CvMat matInvA = cvMat( 8, 8, CV_64F, invA ); 2427 CvMat matB = cvMat( 8, 1, CV_64F, b ); 2428 CvMat matX = cvMat( 8, 1, CV_64F, c ); 2429 2430 CV_CALL( cvPseudoInverse( &matA, &matInvA )); 2431 CV_CALL( cvMatMulAdd( &matInvA, &matB, 0, &matX )); 2432 } 2433 2434 coeffs[0][0] = c[0]; 2435 coeffs[0][1] = c[1]; 2436 coeffs[0][2] = c[2]; 2437 coeffs[1][0] = c[3]; 2438 coeffs[1][1] = c[4]; 2439 coeffs[1][2] = c[5]; 2440 coeffs[2][0] = c[6]; 2441 coeffs[2][1] = c[7]; 2442 coeffs[2][2] = 1.0; 2443 2444 __END__; 2445 2446 return; 2447 } 2448 2449 /*--------------------------------------------------------------------------------------*/ 2450 2451 CV_IMPL void cvComputePerspectiveMap(const double c[3][3], CvArr* rectMapX, CvArr* rectMapY ) 2452 { 2453 CV_FUNCNAME( "cvComputePerspectiveMap" ); 2454 2455 __BEGIN__; 2456 2457 CvSize size; 2458 CvMat stubx, *mapx = (CvMat*)rectMapX; 2459 CvMat stuby, *mapy = (CvMat*)rectMapY; 2460 int i, j; 2461 2462 CV_CALL( mapx = cvGetMat( mapx, &stubx )); 2463 CV_CALL( mapy = cvGetMat( mapy, &stuby )); 2464 2465 if( CV_MAT_TYPE( mapx->type ) != CV_32FC1 || CV_MAT_TYPE( mapy->type ) != CV_32FC1 ) 2466 CV_ERROR( CV_StsUnsupportedFormat, "" ); 2467 2468 size = cvGetMatSize(mapx); 2469 assert( fabs(c[2][2] - 1.) < FLT_EPSILON ); 2470 2471 for( i = 0; i < size.height; i++ ) 2472 { 2473 float* mx = (float*)(mapx->data.ptr + mapx->step*i); 2474 float* my = (float*)(mapy->data.ptr + mapy->step*i); 2475 2476 for( j = 0; j < size.width; j++ ) 2477 { 2478 double w = 1./(c[2][0]*j + c[2][1]*i + 1.); 2479 double x = (c[0][0]*j + c[0][1]*i + c[0][2])*w; 2480 double y = (c[1][0]*j + c[1][1]*i + c[1][2])*w; 2481 2482 mx[j] = (float)x; 2483 my[j] = (float)y; 2484 } 2485 } 2486 2487 __END__; 2488 } 2489 2490 /*--------------------------------------------------------------------------------------*/ 2491 2492 CV_IMPL void cvInitPerspectiveTransform( CvSize size, const CvPoint2D32f quad[4], double matrix[3][3], 2493 CvArr* rectMap ) 2494 { 2495 /* Computes Perspective Transform coeffs and map if need 2496 for given image size and given result quad */ 2497 CV_FUNCNAME( "cvInitPerspectiveTransform" ); 2498 2499 __BEGIN__; 2500 2501 double A[64]; 2502 double b[8]; 2503 double c[8]; 2504 CvPoint2D32f pt[4]; 2505 CvMat mapstub, *map = (CvMat*)rectMap; 2506 int i, j; 2507 2508 if( map ) 2509 { 2510 CV_CALL( map = cvGetMat( map, &mapstub )); 2511 2512 if( CV_MAT_TYPE( map->type ) != CV_32FC2 ) 2513 CV_ERROR( CV_StsUnsupportedFormat, "" ); 2514 2515 if( map->width != size.width || map->height != size.height ) 2516 CV_ERROR( CV_StsUnmatchedSizes, "" ); 2517 } 2518 2519 pt[0] = cvPoint2D32f( 0, 0 ); 2520 pt[1] = cvPoint2D32f( size.width, 0 ); 2521 pt[2] = cvPoint2D32f( size.width, size.height ); 2522 pt[3] = cvPoint2D32f( 0, size.height ); 2523 2524 for( i = 0; i < 4; i++ ) 2525 { 2526 #if 0 2527 double x = quad[i].x; 2528 double y = quad[i].y; 2529 double X = pt[i].x; 2530 double Y = pt[i].y; 2531 #else 2532 double x = pt[i].x; 2533 double y = pt[i].y; 2534 double X = quad[i].x; 2535 double Y = quad[i].y; 2536 #endif 2537 double* a = A + i*16; 2538 2539 a[0] = x; 2540 a[1] = y; 2541 a[2] = 1; 2542 a[3] = 0; 2543 a[4] = 0; 2544 a[5] = 0; 2545 a[6] = -X*x; 2546 a[7] = -X*y; 2547 2548 a += 8; 2549 2550 a[0] = 0; 2551 a[1] = 0; 2552 a[2] = 0; 2553 a[3] = x; 2554 a[4] = y; 2555 a[5] = 1; 2556 a[6] = -Y*x; 2557 a[7] = -Y*y; 2558 2559 b[i*2] = X; 2560 b[i*2 + 1] = Y; 2561 } 2562 2563 { 2564 double invA[64]; 2565 CvMat matA = cvMat( 8, 8, CV_64F, A ); 2566 CvMat matInvA = cvMat( 8, 8, CV_64F, invA ); 2567 CvMat matB = cvMat( 8, 1, CV_64F, b ); 2568 CvMat matX = cvMat( 8, 1, CV_64F, c ); 2569 2570 CV_CALL( cvPseudoInverse( &matA, &matInvA )); 2571 CV_CALL( cvMatMulAdd( &matInvA, &matB, 0, &matX )); 2572 } 2573 2574 matrix[0][0] = c[0]; 2575 matrix[0][1] = c[1]; 2576 matrix[0][2] = c[2]; 2577 matrix[1][0] = c[3]; 2578 matrix[1][1] = c[4]; 2579 matrix[1][2] = c[5]; 2580 matrix[2][0] = c[6]; 2581 matrix[2][1] = c[7]; 2582 matrix[2][2] = 1.0; 2583 2584 if( map ) 2585 { 2586 for( i = 0; i < size.height; i++ ) 2587 { 2588 CvPoint2D32f* maprow = (CvPoint2D32f*)(map->data.ptr + map->step*i); 2589 for( j = 0; j < size.width; j++ ) 2590 { 2591 double w = 1./(c[6]*j + c[7]*i + 1.); 2592 double x = (c[0]*j + c[1]*i + c[2])*w; 2593 double y = (c[3]*j + c[4]*i + c[5])*w; 2594 2595 maprow[j].x = (float)x; 2596 maprow[j].y = (float)y; 2597 } 2598 } 2599 } 2600 2601 __END__; 2602 2603 return; 2604 } 2605 2606 2607 /*-----------------------------------------------------------------------*/ 2608 /* Compute projected infinite point for second image if first image point is known */ 2609 void icvComputeeInfiniteProject1( CvMatr64d rotMatr, 2610 CvMatr64d camMatr1, 2611 CvMatr64d camMatr2, 2612 CvPoint2D32f point1, 2613 CvPoint2D32f* point2) 2614 { 2615 double invMatr1[9]; 2616 icvInvertMatrix_64d(camMatr1,3,invMatr1); 2617 double P1[3]; 2618 double p1[3]; 2619 p1[0] = (double)(point1.x); 2620 p1[1] = (double)(point1.y); 2621 p1[2] = 1; 2622 2623 icvMulMatrix_64d( invMatr1, 2624 3,3, 2625 p1, 2626 1,3, 2627 P1); 2628 2629 double invR[9]; 2630 icvTransposeMatrix_64d( rotMatr, 3, 3, invR ); 2631 2632 /* Change system 1 to system 2 */ 2633 double P2[3]; 2634 icvMulMatrix_64d( invR, 2635 3,3, 2636 P1, 2637 1,3, 2638 P2); 2639 2640 /* Now we can project this point to image 2 */ 2641 double projP[3]; 2642 2643 icvMulMatrix_64d( camMatr2, 2644 3,3, 2645 P2, 2646 1,3, 2647 projP); 2648 2649 point2->x = (float)(projP[0] / projP[2]); 2650 point2->y = (float)(projP[1] / projP[2]); 2651 2652 return; 2653 } 2654 2655 /*-----------------------------------------------------------------------*/ 2656 /* Compute projected infinite point for second image if first image point is known */ 2657 void icvComputeeInfiniteProject2( CvMatr64d rotMatr, 2658 CvMatr64d camMatr1, 2659 CvMatr64d camMatr2, 2660 CvPoint2D32f* point1, 2661 CvPoint2D32f point2) 2662 { 2663 double invMatr2[9]; 2664 icvInvertMatrix_64d(camMatr2,3,invMatr2); 2665 double P2[3]; 2666 double p2[3]; 2667 p2[0] = (double)(point2.x); 2668 p2[1] = (double)(point2.y); 2669 p2[2] = 1; 2670 2671 icvMulMatrix_64d( invMatr2, 2672 3,3, 2673 p2, 2674 1,3, 2675 P2); 2676 2677 /* Change system 1 to system 2 */ 2678 2679 double P1[3]; 2680 icvMulMatrix_64d( rotMatr, 2681 3,3, 2682 P2, 2683 1,3, 2684 P1); 2685 2686 /* Now we can project this point to image 2 */ 2687 double projP[3]; 2688 2689 icvMulMatrix_64d( camMatr1, 2690 3,3, 2691 P1, 2692 1,3, 2693 projP); 2694 2695 point1->x = (float)(projP[0] / projP[2]); 2696 point1->y = (float)(projP[1] / projP[2]); 2697 2698 return; 2699 } 2700 2701 /* Select best R and t for given cameras, points, ... */ 2702 /* For both cameras */ 2703 int icvSelectBestRt( int numImages, 2704 int* numPoints, 2705 CvPoint2D32f* imagePoints1, 2706 CvPoint2D32f* imagePoints2, 2707 CvPoint3D32f* objectPoints, 2708 2709 CvMatr32f cameraMatrix1, 2710 CvVect32f distortion1, 2711 CvMatr32f rotMatrs1, 2712 CvVect32f transVects1, 2713 2714 CvMatr32f cameraMatrix2, 2715 CvVect32f distortion2, 2716 CvMatr32f rotMatrs2, 2717 CvVect32f transVects2, 2718 2719 CvMatr32f bestRotMatr, 2720 CvVect32f bestTransVect 2721 ) 2722 { 2723 2724 /* Need to convert input data 32 -> 64 */ 2725 CvPoint3D64d* objectPoints_64d; 2726 2727 double* rotMatrs1_64d; 2728 double* rotMatrs2_64d; 2729 2730 double* transVects1_64d; 2731 double* transVects2_64d; 2732 2733 double cameraMatrix1_64d[9]; 2734 double cameraMatrix2_64d[9]; 2735 2736 double distortion1_64d[4]; 2737 double distortion2_64d[4]; 2738 2739 /* allocate memory for 64d data */ 2740 int totalNum = 0; 2741 2742 int i; 2743 for( i = 0; i < numImages; i++ ) 2744 { 2745 totalNum += numPoints[i]; 2746 } 2747 2748 objectPoints_64d = (CvPoint3D64d*)calloc(totalNum,sizeof(CvPoint3D64d)); 2749 2750 rotMatrs1_64d = (double*)calloc(numImages,sizeof(double)*9); 2751 rotMatrs2_64d = (double*)calloc(numImages,sizeof(double)*9); 2752 2753 transVects1_64d = (double*)calloc(numImages,sizeof(double)*3); 2754 transVects2_64d = (double*)calloc(numImages,sizeof(double)*3); 2755 2756 /* Convert input data to 64d */ 2757 2758 icvCvt_32f_64d((float*)objectPoints, (double*)objectPoints_64d, totalNum*3); 2759 2760 icvCvt_32f_64d(rotMatrs1, rotMatrs1_64d, numImages*9); 2761 icvCvt_32f_64d(rotMatrs2, rotMatrs2_64d, numImages*9); 2762 2763 icvCvt_32f_64d(transVects1, transVects1_64d, numImages*3); 2764 icvCvt_32f_64d(transVects2, transVects2_64d, numImages*3); 2765 2766 /* Convert to arrays */ 2767 icvCvt_32f_64d(cameraMatrix1, cameraMatrix1_64d, 9); 2768 icvCvt_32f_64d(cameraMatrix2, cameraMatrix2_64d, 9); 2769 2770 icvCvt_32f_64d(distortion1, distortion1_64d, 4); 2771 icvCvt_32f_64d(distortion2, distortion2_64d, 4); 2772 2773 2774 /* for each R and t compute error for image pair */ 2775 float* errors; 2776 2777 errors = (float*)calloc(numImages*numImages,sizeof(float)); 2778 if( errors == 0 ) 2779 { 2780 return CV_OUTOFMEM_ERR; 2781 } 2782 2783 int currImagePair; 2784 int currRt; 2785 for( currRt = 0; currRt < numImages; currRt++ ) 2786 { 2787 int begPoint = 0; 2788 for(currImagePair = 0; currImagePair < numImages; currImagePair++ ) 2789 { 2790 /* For current R,t R,t compute relative position of cameras */ 2791 2792 double convRotMatr[9]; 2793 double convTransVect[3]; 2794 2795 icvCreateConvertMatrVect( rotMatrs1_64d + currRt*9, 2796 transVects1_64d + currRt*3, 2797 rotMatrs2_64d + currRt*9, 2798 transVects2_64d + currRt*3, 2799 convRotMatr, 2800 convTransVect); 2801 2802 /* Project points using relative position of cameras */ 2803 2804 double convRotMatr2[9]; 2805 double convTransVect2[3]; 2806 2807 convRotMatr2[0] = 1; 2808 convRotMatr2[1] = 0; 2809 convRotMatr2[2] = 0; 2810 2811 convRotMatr2[3] = 0; 2812 convRotMatr2[4] = 1; 2813 convRotMatr2[5] = 0; 2814 2815 convRotMatr2[6] = 0; 2816 convRotMatr2[7] = 0; 2817 convRotMatr2[8] = 1; 2818 2819 convTransVect2[0] = 0; 2820 convTransVect2[1] = 0; 2821 convTransVect2[2] = 0; 2822 2823 /* Compute error for given pair and Rt */ 2824 /* We must project points to image and compute error */ 2825 2826 CvPoint2D64d* projImagePoints1; 2827 CvPoint2D64d* projImagePoints2; 2828 2829 CvPoint3D64d* points1; 2830 CvPoint3D64d* points2; 2831 2832 int numberPnt; 2833 numberPnt = numPoints[currImagePair]; 2834 projImagePoints1 = (CvPoint2D64d*)calloc(numberPnt,sizeof(CvPoint2D64d)); 2835 projImagePoints2 = (CvPoint2D64d*)calloc(numberPnt,sizeof(CvPoint2D64d)); 2836 2837 points1 = (CvPoint3D64d*)calloc(numberPnt,sizeof(CvPoint3D64d)); 2838 points2 = (CvPoint3D64d*)calloc(numberPnt,sizeof(CvPoint3D64d)); 2839 2840 /* Transform object points to first camera position */ 2841 int i; 2842 for( i = 0; i < numberPnt; i++ ) 2843 { 2844 /* Create second camera point */ 2845 CvPoint3D64d tmpPoint; 2846 tmpPoint.x = (double)(objectPoints[i].x); 2847 tmpPoint.y = (double)(objectPoints[i].y); 2848 tmpPoint.z = (double)(objectPoints[i].z); 2849 2850 icvConvertPointSystem( tmpPoint, 2851 points2+i, 2852 rotMatrs2_64d + currImagePair*9, 2853 transVects2_64d + currImagePair*3); 2854 2855 /* Create first camera point using R, t */ 2856 icvConvertPointSystem( points2[i], 2857 points1+i, 2858 convRotMatr, 2859 convTransVect); 2860 2861 CvPoint3D64d tmpPoint2 = { 0, 0, 0 }; 2862 icvConvertPointSystem( tmpPoint, 2863 &tmpPoint2, 2864 rotMatrs1_64d + currImagePair*9, 2865 transVects1_64d + currImagePair*3); 2866 double err; 2867 double dx,dy,dz; 2868 dx = tmpPoint2.x - points1[i].x; 2869 dy = tmpPoint2.y - points1[i].y; 2870 dz = tmpPoint2.z - points1[i].z; 2871 err = sqrt(dx*dx + dy*dy + dz*dz); 2872 2873 2874 } 2875 2876 #if 0 2877 cvProjectPointsSimple( numPoints[currImagePair], 2878 objectPoints_64d + begPoint, 2879 rotMatrs1_64d + currRt*9, 2880 transVects1_64d + currRt*3, 2881 cameraMatrix1_64d, 2882 distortion1_64d, 2883 projImagePoints1); 2884 2885 cvProjectPointsSimple( numPoints[currImagePair], 2886 objectPoints_64d + begPoint, 2887 rotMatrs2_64d + currRt*9, 2888 transVects2_64d + currRt*3, 2889 cameraMatrix2_64d, 2890 distortion2_64d, 2891 projImagePoints2); 2892 #endif 2893 2894 /* Project with no translate and no rotation */ 2895 2896 #if 0 2897 { 2898 double nodist[4] = {0,0,0,0}; 2899 cvProjectPointsSimple( numPoints[currImagePair], 2900 points1, 2901 convRotMatr2, 2902 convTransVect2, 2903 cameraMatrix1_64d, 2904 nodist, 2905 projImagePoints1); 2906 2907 cvProjectPointsSimple( numPoints[currImagePair], 2908 points2, 2909 convRotMatr2, 2910 convTransVect2, 2911 cameraMatrix2_64d, 2912 nodist, 2913 projImagePoints2); 2914 2915 } 2916 #endif 2917 2918 cvProjectPointsSimple( numPoints[currImagePair], 2919 points1, 2920 convRotMatr2, 2921 convTransVect2, 2922 cameraMatrix1_64d, 2923 distortion1_64d, 2924 projImagePoints1); 2925 2926 cvProjectPointsSimple( numPoints[currImagePair], 2927 points2, 2928 convRotMatr2, 2929 convTransVect2, 2930 cameraMatrix2_64d, 2931 distortion2_64d, 2932 projImagePoints2); 2933 2934 /* points are projected. Compute error */ 2935 2936 int currPoint; 2937 double err1 = 0; 2938 double err2 = 0; 2939 double err; 2940 for( currPoint = 0; currPoint < numberPnt; currPoint++ ) 2941 { 2942 double len1,len2; 2943 double dx1,dy1; 2944 dx1 = imagePoints1[begPoint+currPoint].x - projImagePoints1[currPoint].x; 2945 dy1 = imagePoints1[begPoint+currPoint].y - projImagePoints1[currPoint].y; 2946 len1 = sqrt(dx1*dx1 + dy1*dy1); 2947 err1 += len1; 2948 2949 double dx2,dy2; 2950 dx2 = imagePoints2[begPoint+currPoint].x - projImagePoints2[currPoint].x; 2951 dy2 = imagePoints2[begPoint+currPoint].y - projImagePoints2[currPoint].y; 2952 len2 = sqrt(dx2*dx2 + dy2*dy2); 2953 err2 += len2; 2954 } 2955 2956 err1 /= (float)(numberPnt); 2957 err2 /= (float)(numberPnt); 2958 2959 err = (err1+err2) * 0.5; 2960 begPoint += numberPnt; 2961 2962 /* Set this error to */ 2963 errors[numImages*currImagePair+currRt] = (float)err; 2964 2965 free(points1); 2966 free(points2); 2967 free(projImagePoints1); 2968 free(projImagePoints2); 2969 } 2970 } 2971 2972 /* Just select R and t with minimal average error */ 2973 2974 int bestnumRt = 0; 2975 float minError = 0;/* Just for no warnings. Uses 'first' flag. */ 2976 int first = 1; 2977 for( currRt = 0; currRt < numImages; currRt++ ) 2978 { 2979 float avErr = 0; 2980 for(currImagePair = 0; currImagePair < numImages; currImagePair++ ) 2981 { 2982 avErr += errors[numImages*currImagePair+currRt]; 2983 } 2984 avErr /= (float)(numImages); 2985 2986 if( first ) 2987 { 2988 bestnumRt = 0; 2989 minError = avErr; 2990 first = 0; 2991 } 2992 else 2993 { 2994 if( avErr < minError ) 2995 { 2996 bestnumRt = currRt; 2997 minError = avErr; 2998 } 2999 } 3000 3001 } 3002 3003 double bestRotMatr_64d[9]; 3004 double bestTransVect_64d[3]; 3005 3006 icvCreateConvertMatrVect( rotMatrs1_64d + bestnumRt * 9, 3007 transVects1_64d + bestnumRt * 3, 3008 rotMatrs2_64d + bestnumRt * 9, 3009 transVects2_64d + bestnumRt * 3, 3010 bestRotMatr_64d, 3011 bestTransVect_64d); 3012 3013 icvCvt_64d_32f(bestRotMatr_64d,bestRotMatr,9); 3014 icvCvt_64d_32f(bestTransVect_64d,bestTransVect,3); 3015 3016 3017 free(errors); 3018 3019 return CV_OK; 3020 } 3021 3022 3023 /* ----------------- Stereo calibration functions --------------------- */ 3024 3025 float icvDefinePointPosition(CvPoint2D32f point1,CvPoint2D32f point2,CvPoint2D32f point) 3026 { 3027 float ax = point2.x - point1.x; 3028 float ay = point2.y - point1.y; 3029 3030 float bx = point.x - point1.x; 3031 float by = point.y - point1.y; 3032 3033 return (ax*by - ay*bx); 3034 } 3035 3036 /* Convert function for stereo warping */ 3037 int icvConvertWarpCoordinates(double coeffs[3][3], 3038 CvPoint2D32f* cameraPoint, 3039 CvPoint2D32f* warpPoint, 3040 int direction) 3041 { 3042 double x,y; 3043 double det; 3044 if( direction == CV_WARP_TO_CAMERA ) 3045 {/* convert from camera image to warped image coordinates */ 3046 x = warpPoint->x; 3047 y = warpPoint->y; 3048 3049 det = (coeffs[2][0] * x + coeffs[2][1] * y + coeffs[2][2]); 3050 if( fabs(det) > 1e-8 ) 3051 { 3052 cameraPoint->x = (float)((coeffs[0][0] * x + coeffs[0][1] * y + coeffs[0][2]) / det); 3053 cameraPoint->y = (float)((coeffs[1][0] * x + coeffs[1][1] * y + coeffs[1][2]) / det); 3054 return CV_OK; 3055 } 3056 } 3057 else if( direction == CV_CAMERA_TO_WARP ) 3058 {/* convert from warped image to camera image coordinates */ 3059 x = cameraPoint->x; 3060 y = cameraPoint->y; 3061 3062 det = (coeffs[2][0]*x-coeffs[0][0])*(coeffs[2][1]*y-coeffs[1][1])-(coeffs[2][1]*x-coeffs[0][1])*(coeffs[2][0]*y-coeffs[1][0]); 3063 3064 if( fabs(det) > 1e-8 ) 3065 { 3066 warpPoint->x = (float)(((coeffs[0][2]-coeffs[2][2]*x)*(coeffs[2][1]*y-coeffs[1][1])-(coeffs[2][1]*x-coeffs[0][1])*(coeffs[1][2]-coeffs[2][2]*y))/det); 3067 warpPoint->y = (float)(((coeffs[2][0]*x-coeffs[0][0])*(coeffs[1][2]-coeffs[2][2]*y)-(coeffs[0][2]-coeffs[2][2]*x)*(coeffs[2][0]*y-coeffs[1][0]))/det); 3068 return CV_OK; 3069 } 3070 } 3071 3072 return CV_BADFACTOR_ERR; 3073 } 3074 3075 /* Compute stereo params using some camera params */ 3076 /* by Valery Mosyagin. int ComputeRestStereoParams(StereoParams *stereoparams) */ 3077 int icvComputeRestStereoParams(CvStereoCamera *stereoparams) 3078 { 3079 3080 3081 icvGetQuadsTransformStruct(stereoparams); 3082 3083 cvInitPerspectiveTransform( stereoparams->warpSize, 3084 stereoparams->quad[0], 3085 stereoparams->coeffs[0], 3086 0); 3087 3088 cvInitPerspectiveTransform( stereoparams->warpSize, 3089 stereoparams->quad[1], 3090 stereoparams->coeffs[1], 3091 0); 3092 3093 /* Create border for warped images */ 3094 CvPoint2D32f corns[4]; 3095 corns[0].x = 0; 3096 corns[0].y = 0; 3097 3098 corns[1].x = (float)(stereoparams->camera[0]->imgSize[0]-1); 3099 corns[1].y = 0; 3100 3101 corns[2].x = (float)(stereoparams->camera[0]->imgSize[0]-1); 3102 corns[2].y = (float)(stereoparams->camera[0]->imgSize[1]-1); 3103 3104 corns[3].x = 0; 3105 corns[3].y = (float)(stereoparams->camera[0]->imgSize[1]-1); 3106 3107 int i; 3108 for( i = 0; i < 4; i++ ) 3109 { 3110 /* For first camera */ 3111 icvConvertWarpCoordinates( stereoparams->coeffs[0], 3112 corns+i, 3113 stereoparams->border[0]+i, 3114 CV_CAMERA_TO_WARP); 3115 3116 /* For second camera */ 3117 icvConvertWarpCoordinates( stereoparams->coeffs[1], 3118 corns+i, 3119 stereoparams->border[1]+i, 3120 CV_CAMERA_TO_WARP); 3121 } 3122 3123 /* Test compute */ 3124 { 3125 CvPoint2D32f warpPoints[4]; 3126 warpPoints[0] = cvPoint2D32f(0,0); 3127 warpPoints[1] = cvPoint2D32f(stereoparams->warpSize.width-1,0); 3128 warpPoints[2] = cvPoint2D32f(stereoparams->warpSize.width-1,stereoparams->warpSize.height-1); 3129 warpPoints[3] = cvPoint2D32f(0,stereoparams->warpSize.height-1); 3130 3131 CvPoint2D32f camPoints1[4]; 3132 CvPoint2D32f camPoints2[4]; 3133 3134 for( int i = 0; i < 4; i++ ) 3135 { 3136 icvConvertWarpCoordinates(stereoparams->coeffs[0], 3137 camPoints1+i, 3138 warpPoints+i, 3139 CV_WARP_TO_CAMERA); 3140 3141 icvConvertWarpCoordinates(stereoparams->coeffs[1], 3142 camPoints2+i, 3143 warpPoints+i, 3144 CV_WARP_TO_CAMERA); 3145 } 3146 } 3147 3148 3149 /* Allocate memory for scanlines coeffs */ 3150 3151 stereoparams->lineCoeffs = (CvStereoLineCoeff*)calloc(stereoparams->warpSize.height,sizeof(CvStereoLineCoeff)); 3152 3153 /* Compute coeffs for epilines */ 3154 3155 icvComputeCoeffForStereo( stereoparams); 3156 3157 /* all coeffs are known */ 3158 return CV_OK; 3159 } 3160 3161 /*-------------------------------------------------------------------------------------------*/ 3162 3163 int icvStereoCalibration( int numImages, 3164 int* nums, 3165 CvSize imageSize, 3166 CvPoint2D32f* imagePoints1, 3167 CvPoint2D32f* imagePoints2, 3168 CvPoint3D32f* objectPoints, 3169 CvStereoCamera* stereoparams 3170 ) 3171 { 3172 /* Firstly we must calibrate both cameras */ 3173 /* Alocate memory for data */ 3174 /* Allocate for translate vectors */ 3175 float* transVects1; 3176 float* transVects2; 3177 float* rotMatrs1; 3178 float* rotMatrs2; 3179 3180 transVects1 = (float*)calloc(numImages,sizeof(float)*3); 3181 transVects2 = (float*)calloc(numImages,sizeof(float)*3); 3182 3183 rotMatrs1 = (float*)calloc(numImages,sizeof(float)*9); 3184 rotMatrs2 = (float*)calloc(numImages,sizeof(float)*9); 3185 3186 /* Calibrate first camera */ 3187 cvCalibrateCamera( numImages, 3188 nums, 3189 imageSize, 3190 imagePoints1, 3191 objectPoints, 3192 stereoparams->camera[0]->distortion, 3193 stereoparams->camera[0]->matrix, 3194 transVects1, 3195 rotMatrs1, 3196 1); 3197 3198 /* Calibrate second camera */ 3199 cvCalibrateCamera( numImages, 3200 nums, 3201 imageSize, 3202 imagePoints2, 3203 objectPoints, 3204 stereoparams->camera[1]->distortion, 3205 stereoparams->camera[1]->matrix, 3206 transVects2, 3207 rotMatrs2, 3208 1); 3209 3210 /* Cameras are calibrated */ 3211 3212 stereoparams->camera[0]->imgSize[0] = (float)imageSize.width; 3213 stereoparams->camera[0]->imgSize[1] = (float)imageSize.height; 3214 3215 stereoparams->camera[1]->imgSize[0] = (float)imageSize.width; 3216 stereoparams->camera[1]->imgSize[1] = (float)imageSize.height; 3217 3218 icvSelectBestRt( numImages, 3219 nums, 3220 imagePoints1, 3221 imagePoints2, 3222 objectPoints, 3223 stereoparams->camera[0]->matrix, 3224 stereoparams->camera[0]->distortion, 3225 rotMatrs1, 3226 transVects1, 3227 stereoparams->camera[1]->matrix, 3228 stereoparams->camera[1]->distortion, 3229 rotMatrs2, 3230 transVects2, 3231 stereoparams->rotMatrix, 3232 stereoparams->transVector 3233 ); 3234 3235 /* Free memory */ 3236 free(transVects1); 3237 free(transVects2); 3238 free(rotMatrs1); 3239 free(rotMatrs2); 3240 3241 icvComputeRestStereoParams(stereoparams); 3242 3243 return CV_NO_ERR; 3244 } 3245 3246 /* Find line from epipole */ 3247 void FindLine(CvPoint2D32f epipole,CvSize imageSize,CvPoint2D32f point,CvPoint2D32f *start,CvPoint2D32f *end) 3248 { 3249 CvPoint2D32f frameBeg; 3250 CvPoint2D32f frameEnd; 3251 CvPoint2D32f cross[4]; 3252 int haveCross[4]; 3253 float dist; 3254 3255 haveCross[0] = 0; 3256 haveCross[1] = 0; 3257 haveCross[2] = 0; 3258 haveCross[3] = 0; 3259 3260 frameBeg.x = 0; 3261 frameBeg.y = 0; 3262 frameEnd.x = (float)(imageSize.width); 3263 frameEnd.y = 0; 3264 haveCross[0] = icvGetCrossPieceVector(frameBeg,frameEnd,epipole,point,&cross[0]); 3265 3266 frameBeg.x = (float)(imageSize.width); 3267 frameBeg.y = 0; 3268 frameEnd.x = (float)(imageSize.width); 3269 frameEnd.y = (float)(imageSize.height); 3270 haveCross[1] = icvGetCrossPieceVector(frameBeg,frameEnd,epipole,point,&cross[1]); 3271 3272 frameBeg.x = (float)(imageSize.width); 3273 frameBeg.y = (float)(imageSize.height); 3274 frameEnd.x = 0; 3275 frameEnd.y = (float)(imageSize.height); 3276 haveCross[2] = icvGetCrossPieceVector(frameBeg,frameEnd,epipole,point,&cross[2]); 3277 3278 frameBeg.x = 0; 3279 frameBeg.y = (float)(imageSize.height); 3280 frameEnd.x = 0; 3281 frameEnd.y = 0; 3282 haveCross[3] = icvGetCrossPieceVector(frameBeg,frameEnd,epipole,point,&cross[3]); 3283 3284 int n; 3285 float minDist = (float)(INT_MAX); 3286 float maxDist = (float)(INT_MIN); 3287 3288 int maxN = -1; 3289 int minN = -1; 3290 3291 for( n = 0; n < 4; n++ ) 3292 { 3293 if( haveCross[n] > 0 ) 3294 { 3295 dist = (epipole.x - cross[n].x)*(epipole.x - cross[n].x) + 3296 (epipole.y - cross[n].y)*(epipole.y - cross[n].y); 3297 3298 if( dist < minDist ) 3299 { 3300 minDist = dist; 3301 minN = n; 3302 } 3303 3304 if( dist > maxDist ) 3305 { 3306 maxDist = dist; 3307 maxN = n; 3308 } 3309 } 3310 } 3311 3312 if( minN >= 0 && maxN >= 0 && (minN != maxN) ) 3313 { 3314 *start = cross[minN]; 3315 *end = cross[maxN]; 3316 } 3317 else 3318 { 3319 start->x = 0; 3320 start->y = 0; 3321 end->x = 0; 3322 end->y = 0; 3323 } 3324 3325 return; 3326 } 3327 3328 3329 /* Find line which cross frame by line(a,b,c) */ 3330 void FindLineForEpiline(CvSize imageSize,float a,float b,float c,CvPoint2D32f *start,CvPoint2D32f *end) 3331 { 3332 CvPoint2D32f frameBeg; 3333 CvPoint2D32f frameEnd; 3334 CvPoint2D32f cross[4]; 3335 int haveCross[4]; 3336 float dist; 3337 3338 haveCross[0] = 0; 3339 haveCross[1] = 0; 3340 haveCross[2] = 0; 3341 haveCross[3] = 0; 3342 3343 frameBeg.x = 0; 3344 frameBeg.y = 0; 3345 frameEnd.x = (float)(imageSize.width); 3346 frameEnd.y = 0; 3347 haveCross[0] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[0]); 3348 3349 frameBeg.x = (float)(imageSize.width); 3350 frameBeg.y = 0; 3351 frameEnd.x = (float)(imageSize.width); 3352 frameEnd.y = (float)(imageSize.height); 3353 haveCross[1] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[1]); 3354 3355 frameBeg.x = (float)(imageSize.width); 3356 frameBeg.y = (float)(imageSize.height); 3357 frameEnd.x = 0; 3358 frameEnd.y = (float)(imageSize.height); 3359 haveCross[2] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[2]); 3360 3361 frameBeg.x = 0; 3362 frameBeg.y = (float)(imageSize.height); 3363 frameEnd.x = 0; 3364 frameEnd.y = 0; 3365 haveCross[3] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[3]); 3366 3367 int n; 3368 float minDist = (float)(INT_MAX); 3369 float maxDist = (float)(INT_MIN); 3370 3371 int maxN = -1; 3372 int minN = -1; 3373 3374 double midPointX = imageSize.width / 2.0; 3375 double midPointY = imageSize.height / 2.0; 3376 3377 for( n = 0; n < 4; n++ ) 3378 { 3379 if( haveCross[n] > 0 ) 3380 { 3381 dist = (float)((midPointX - cross[n].x)*(midPointX - cross[n].x) + 3382 (midPointY - cross[n].y)*(midPointY - cross[n].y)); 3383 3384 if( dist < minDist ) 3385 { 3386 minDist = dist; 3387 minN = n; 3388 } 3389 3390 if( dist > maxDist ) 3391 { 3392 maxDist = dist; 3393 maxN = n; 3394 } 3395 } 3396 } 3397 3398 if( minN >= 0 && maxN >= 0 && (minN != maxN) ) 3399 { 3400 *start = cross[minN]; 3401 *end = cross[maxN]; 3402 } 3403 else 3404 { 3405 start->x = 0; 3406 start->y = 0; 3407 end->x = 0; 3408 end->y = 0; 3409 } 3410 3411 return; 3412 3413 } 3414 3415 /* Cross lines */ 3416 int GetCrossLines(CvPoint2D32f p1_start,CvPoint2D32f p1_end,CvPoint2D32f p2_start,CvPoint2D32f p2_end,CvPoint2D32f *cross) 3417 { 3418 double ex1,ey1,ex2,ey2; 3419 double px1,py1,px2,py2; 3420 double del; 3421 double delA,delB,delX,delY; 3422 double alpha,betta; 3423 3424 ex1 = p1_start.x; 3425 ey1 = p1_start.y; 3426 ex2 = p1_end.x; 3427 ey2 = p1_end.y; 3428 3429 px1 = p2_start.x; 3430 py1 = p2_start.y; 3431 px2 = p2_end.x; 3432 py2 = p2_end.y; 3433 3434 del = (ex1-ex2)*(py2-py1)+(ey2-ey1)*(px2-px1); 3435 if( del == 0) 3436 { 3437 return -1; 3438 } 3439 3440 delA = (px1-ex1)*(py1-py2) + (ey1-py1)*(px1-px2); 3441 delB = (ex1-px1)*(ey1-ey2) + (py1-ey1)*(ex1-ex2); 3442 3443 alpha = delA / del; 3444 betta = -delB / del; 3445 3446 if( alpha < 0 || alpha > 1.0 || betta < 0 || betta > 1.0) 3447 { 3448 return -1; 3449 } 3450 3451 delX = (ex1-ex2)*(py1*(px1-px2)-px1*(py1-py2))+ 3452 (px1-px2)*(ex1*(ey1-ey2)-ey1*(ex1-ex2)); 3453 3454 delY = (ey1-ey2)*(px1*(py1-py2)-py1*(px1-px2))+ 3455 (py1-py2)*(ey1*(ex1-ex2)-ex1*(ey1-ey2)); 3456 3457 cross->x = (float)( delX / del); 3458 cross->y = (float)(-delY / del); 3459 return 1; 3460 } 3461 3462 3463 int icvGetCrossPieceVector(CvPoint2D32f p1_start,CvPoint2D32f p1_end,CvPoint2D32f v2_start,CvPoint2D32f v2_end,CvPoint2D32f *cross) 3464 { 3465 double ex1,ey1,ex2,ey2; 3466 double px1,py1,px2,py2; 3467 double del; 3468 double delA,delB,delX,delY; 3469 double alpha,betta; 3470 3471 ex1 = p1_start.x; 3472 ey1 = p1_start.y; 3473 ex2 = p1_end.x; 3474 ey2 = p1_end.y; 3475 3476 px1 = v2_start.x; 3477 py1 = v2_start.y; 3478 px2 = v2_end.x; 3479 py2 = v2_end.y; 3480 3481 del = (ex1-ex2)*(py2-py1)+(ey2-ey1)*(px2-px1); 3482 if( del == 0) 3483 { 3484 return -1; 3485 } 3486 3487 delA = (px1-ex1)*(py1-py2) + (ey1-py1)*(px1-px2); 3488 delB = (ex1-px1)*(ey1-ey2) + (py1-ey1)*(ex1-ex2); 3489 3490 alpha = delA / del; 3491 betta = -delB / del; 3492 3493 if( alpha < 0 || alpha > 1.0 ) 3494 { 3495 return -1; 3496 } 3497 3498 delX = (ex1-ex2)*(py1*(px1-px2)-px1*(py1-py2))+ 3499 (px1-px2)*(ex1*(ey1-ey2)-ey1*(ex1-ex2)); 3500 3501 delY = (ey1-ey2)*(px1*(py1-py2)-py1*(px1-px2))+ 3502 (py1-py2)*(ey1*(ex1-ex2)-ex1*(ey1-ey2)); 3503 3504 cross->x = (float)( delX / del); 3505 cross->y = (float)(-delY / del); 3506 return 1; 3507 } 3508 3509 3510 int icvGetCrossLineDirect(CvPoint2D32f p1,CvPoint2D32f p2,float a,float b,float c,CvPoint2D32f* cross) 3511 { 3512 double del; 3513 double delX,delY,delA; 3514 3515 double px1,px2,py1,py2; 3516 double X,Y,alpha; 3517 3518 px1 = p1.x; 3519 py1 = p1.y; 3520 3521 px2 = p2.x; 3522 py2 = p2.y; 3523 3524 del = a * (px2 - px1) + b * (py2-py1); 3525 if( del == 0 ) 3526 { 3527 return -1; 3528 } 3529 3530 delA = - c - a*px1 - b*py1; 3531 alpha = delA / del; 3532 3533 if( alpha < 0 || alpha > 1.0 ) 3534 { 3535 return -1;/* no cross */ 3536 } 3537 3538 delX = b * (py1*(px1-px2) - px1*(py1-py2)) + c * (px1-px2); 3539 delY = a * (px1*(py1-py2) - py1*(px1-px2)) + c * (py1-py2); 3540 3541 X = delX / del; 3542 Y = delY / del; 3543 3544 cross->x = (float)X; 3545 cross->y = (float)Y; 3546 3547 return 1; 3548 } 3549 3550 int cvComputeEpipoles( CvMatr32f camMatr1, CvMatr32f camMatr2, 3551 CvMatr32f rotMatr1, CvMatr32f rotMatr2, 3552 CvVect32f transVect1,CvVect32f transVect2, 3553 CvVect32f epipole1, 3554 CvVect32f epipole2) 3555 { 3556 3557 /* Copy matrix */ 3558 3559 CvMat ccamMatr1 = cvMat(3,3,CV_MAT32F,camMatr1); 3560 CvMat ccamMatr2 = cvMat(3,3,CV_MAT32F,camMatr2); 3561 CvMat crotMatr1 = cvMat(3,3,CV_MAT32F,rotMatr1); 3562 CvMat crotMatr2 = cvMat(3,3,CV_MAT32F,rotMatr2); 3563 CvMat ctransVect1 = cvMat(3,1,CV_MAT32F,transVect1); 3564 CvMat ctransVect2 = cvMat(3,1,CV_MAT32F,transVect2); 3565 CvMat cepipole1 = cvMat(3,1,CV_MAT32F,epipole1); 3566 CvMat cepipole2 = cvMat(3,1,CV_MAT32F,epipole2); 3567 3568 3569 CvMat cmatrP1 = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&cmatrP1); 3570 CvMat cmatrP2 = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&cmatrP2); 3571 CvMat cvectp1 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&cvectp1); 3572 CvMat cvectp2 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&cvectp2); 3573 CvMat ctmpF1 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&ctmpF1); 3574 CvMat ctmpM1 = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&ctmpM1); 3575 CvMat ctmpM2 = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&ctmpM2); 3576 CvMat cinvP1 = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&cinvP1); 3577 CvMat cinvP2 = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&cinvP2); 3578 CvMat ctmpMatr = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&ctmpMatr); 3579 CvMat ctmpVect1 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&ctmpVect1); 3580 CvMat ctmpVect2 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&ctmpVect2); 3581 CvMat cmatrF1 = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&cmatrF1); 3582 CvMat ctmpF = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&ctmpF); 3583 CvMat ctmpE1 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&ctmpE1); 3584 CvMat ctmpE2 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&ctmpE2); 3585 3586 /* Compute first */ 3587 cvmMul( &ccamMatr1, &crotMatr1, &cmatrP1); 3588 cvmInvert( &cmatrP1,&cinvP1 ); 3589 cvmMul( &ccamMatr1, &ctransVect1, &cvectp1 ); 3590 3591 /* Compute second */ 3592 cvmMul( &ccamMatr2, &crotMatr2, &cmatrP2 ); 3593 cvmInvert( &cmatrP2,&cinvP2 ); 3594 cvmMul( &ccamMatr2, &ctransVect2, &cvectp2 ); 3595 3596 cvmMul( &cmatrP1, &cinvP2, &ctmpM1); 3597 cvmMul( &ctmpM1, &cvectp2, &ctmpVect1); 3598 cvmSub( &cvectp1,&ctmpVect1,&ctmpE1); 3599 3600 cvmMul( &cmatrP2, &cinvP1, &ctmpM2); 3601 cvmMul( &ctmpM2, &cvectp1, &ctmpVect2); 3602 cvmSub( &cvectp2, &ctmpVect2, &ctmpE2); 3603 3604 3605 /* Need scale */ 3606 3607 cvmScale(&ctmpE1,&cepipole1,1.0); 3608 cvmScale(&ctmpE2,&cepipole2,1.0); 3609 3610 cvmFree(&cmatrP1); 3611 cvmFree(&cmatrP1); 3612 cvmFree(&cvectp1); 3613 cvmFree(&cvectp2); 3614 cvmFree(&ctmpF1); 3615 cvmFree(&ctmpM1); 3616 cvmFree(&ctmpM2); 3617 cvmFree(&cinvP1); 3618 cvmFree(&cinvP2); 3619 cvmFree(&ctmpMatr); 3620 cvmFree(&ctmpVect1); 3621 cvmFree(&ctmpVect2); 3622 cvmFree(&cmatrF1); 3623 cvmFree(&ctmpF); 3624 cvmFree(&ctmpE1); 3625 cvmFree(&ctmpE2); 3626 3627 return CV_NO_ERR; 3628 }/* cvComputeEpipoles */ 3629 3630 3631 /* Compute epipoles for fundamental matrix */ 3632 int cvComputeEpipolesFromFundMatrix(CvMatr32f fundMatr, 3633 CvPoint3D32f* epipole1, 3634 CvPoint3D32f* epipole2) 3635 { 3636 /* Decompose fundamental matrix using SVD ( A = U W V') */ 3637 CvMat fundMatrC = cvMat(3,3,CV_MAT32F,fundMatr); 3638 3639 CvMat* matrW = cvCreateMat(3,3,CV_MAT32F); 3640 CvMat* matrU = cvCreateMat(3,3,CV_MAT32F); 3641 CvMat* matrV = cvCreateMat(3,3,CV_MAT32F); 3642 3643 /* From svd we need just last vector of U and V or last row from U' and V' */ 3644 /* We get transposed matrixes U and V */ 3645 cvSVD(&fundMatrC,matrW,matrU,matrV,CV_SVD_V_T|CV_SVD_U_T); 3646 3647 /* Get last row from U' and compute epipole1 */ 3648 epipole1->x = matrU->data.fl[6]; 3649 epipole1->y = matrU->data.fl[7]; 3650 epipole1->z = matrU->data.fl[8]; 3651 3652 /* Get last row from V' and compute epipole2 */ 3653 epipole2->x = matrV->data.fl[6]; 3654 epipole2->y = matrV->data.fl[7]; 3655 epipole2->z = matrV->data.fl[8]; 3656 3657 cvReleaseMat(&matrW); 3658 cvReleaseMat(&matrU); 3659 cvReleaseMat(&matrV); 3660 return CV_OK; 3661 } 3662 3663 int cvConvertEssential2Fundamental( CvMatr32f essMatr, 3664 CvMatr32f fundMatr, 3665 CvMatr32f cameraMatr1, 3666 CvMatr32f cameraMatr2) 3667 {/* Fund = inv(CM1') * Ess * inv(CM2) */ 3668 3669 CvMat essMatrC = cvMat(3,3,CV_MAT32F,essMatr); 3670 CvMat fundMatrC = cvMat(3,3,CV_MAT32F,fundMatr); 3671 CvMat cameraMatr1C = cvMat(3,3,CV_MAT32F,cameraMatr1); 3672 CvMat cameraMatr2C = cvMat(3,3,CV_MAT32F,cameraMatr2); 3673 3674 CvMat* invCM2 = cvCreateMat(3,3,CV_MAT32F); 3675 CvMat* tmpMatr = cvCreateMat(3,3,CV_MAT32F); 3676 CvMat* invCM1T = cvCreateMat(3,3,CV_MAT32F); 3677 3678 cvTranspose(&cameraMatr1C,tmpMatr); 3679 cvInvert(tmpMatr,invCM1T); 3680 cvmMul(invCM1T,&essMatrC,tmpMatr); 3681 cvInvert(&cameraMatr2C,invCM2); 3682 cvmMul(tmpMatr,invCM2,&fundMatrC); 3683 3684 /* Scale fundamental matrix */ 3685 double scale; 3686 scale = 1.0/fundMatrC.data.fl[8]; 3687 cvConvertScale(&fundMatrC,&fundMatrC,scale); 3688 3689 cvReleaseMat(&invCM2); 3690 cvReleaseMat(&tmpMatr); 3691 cvReleaseMat(&invCM1T); 3692 3693 return CV_OK; 3694 } 3695 3696 /* Compute essential matrix */ 3697 3698 int cvComputeEssentialMatrix( CvMatr32f rotMatr, 3699 CvMatr32f transVect, 3700 CvMatr32f essMatr) 3701 { 3702 float transMatr[9]; 3703 3704 /* Make antisymmetric matrix from transpose vector */ 3705 transMatr[0] = 0; 3706 transMatr[1] = - transVect[2]; 3707 transMatr[2] = transVect[1]; 3708 3709 transMatr[3] = transVect[2]; 3710 transMatr[4] = 0; 3711 transMatr[5] = - transVect[0]; 3712 3713 transMatr[6] = - transVect[1]; 3714 transMatr[7] = transVect[0]; 3715 transMatr[8] = 0; 3716 3717 icvMulMatrix_32f(transMatr,3,3,rotMatr,3,3,essMatr); 3718 3719 return CV_OK; 3720 } 3721 3722 3723