/*M/////////////////////////////////////////////////////////////////////////////////////// // // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. // // By downloading, copying, installing or using the software you agree to this license. // If you do not agree to this license, do not download, install, // copy or use the software. // // // Intel License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000, Intel Corporation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistribution's of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // * Redistribution's in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // * The name of Intel Corporation may not be used to endorse or promote products // derived from this software without specific prior written permission. // // This software is provided by the copyright holders and contributors "as is" and // any express or implied warranties, including, but not limited to, the implied // warranties of merchantability and fitness for a particular purpose are disclaimed. // In no event shall the Intel Corporation or contributors be liable for any direct, // indirect, incidental, special, exemplary, or consequential damages // (including, but not limited to, procurement of substitute goods or services; // loss of use, data, or profits; or business interruption) however caused // and on any theory of liability, whether in contract, strict liability, // or tort (including negligence or otherwise) arising in any way out of // the use of this software, even if advised of the possibility of such damage. // //M*/ #include "_cvaux.h" #include "cvtypes.h" #include <float.h> #include <limits.h> #include "cv.h" /* Valery Mosyagin */ #undef quad #define EPS64D 1e-9 int cvComputeEssentialMatrix( CvMatr32f rotMatr, CvMatr32f transVect, CvMatr32f essMatr); int cvConvertEssential2Fundamental( CvMatr32f essMatr, CvMatr32f fundMatr, CvMatr32f cameraMatr1, CvMatr32f cameraMatr2); int cvComputeEpipolesFromFundMatrix(CvMatr32f fundMatr, CvPoint3D32f* epipole1, CvPoint3D32f* epipole2); void icvTestPoint( CvPoint2D64d testPoint, CvVect64d line1,CvVect64d line2, CvPoint2D64d basePoint, int* result); int icvGetSymPoint3D( CvPoint3D64d pointCorner, CvPoint3D64d point1, CvPoint3D64d point2, CvPoint3D64d *pointSym2) { double len1,len2; double alpha; icvGetPieceLength3D(pointCorner,point1,&len1); if( len1 < EPS64D ) { return CV_BADARG_ERR; } icvGetPieceLength3D(pointCorner,point2,&len2); alpha = len2 / len1; pointSym2->x = pointCorner.x + alpha*(point1.x - pointCorner.x); pointSym2->y = pointCorner.y + alpha*(point1.y - pointCorner.y); pointSym2->z = pointCorner.z + alpha*(point1.z - pointCorner.z); return CV_NO_ERR; } /* author Valery Mosyagin */ /* Compute 3D point for scanline and alpha betta */ int icvCompute3DPoint( double alpha,double betta, CvStereoLineCoeff* coeffs, CvPoint3D64d* point) { double partX; double partY; double partZ; double partAll; double invPartAll; double alphabetta = alpha*betta; partAll = alpha - betta; if( fabs(partAll) > 0.00001 ) /* alpha must be > betta */ { partX = coeffs->Xcoef + coeffs->XcoefA *alpha + coeffs->XcoefB*betta + coeffs->XcoefAB*alphabetta; partY = coeffs->Ycoef + coeffs->YcoefA *alpha + coeffs->YcoefB*betta + coeffs->YcoefAB*alphabetta; partZ = coeffs->Zcoef + coeffs->ZcoefA *alpha + coeffs->ZcoefB*betta + coeffs->ZcoefAB*alphabetta; invPartAll = 1.0 / partAll; point->x = partX * invPartAll; point->y = partY * invPartAll; point->z = partZ * invPartAll; return CV_NO_ERR; } else { return CV_BADFACTOR_ERR; } } /*--------------------------------------------------------------------------------------*/ /* Compute rotate matrix and trans vector for change system */ int icvCreateConvertMatrVect( CvMatr64d rotMatr1, CvMatr64d transVect1, CvMatr64d rotMatr2, CvMatr64d transVect2, CvMatr64d convRotMatr, CvMatr64d convTransVect) { double invRotMatr2[9]; double tmpVect[3]; icvInvertMatrix_64d(rotMatr2,3,invRotMatr2); /* Test for error */ icvMulMatrix_64d( rotMatr1, 3,3, invRotMatr2, 3,3, convRotMatr); icvMulMatrix_64d( convRotMatr, 3,3, transVect2, 1,3, tmpVect); icvSubVector_64d(transVect1,tmpVect,convTransVect,3); return CV_NO_ERR; } /*--------------------------------------------------------------------------------------*/ /* Compute point coordinates in other system */ int icvConvertPointSystem(CvPoint3D64d M2, CvPoint3D64d* M1, CvMatr64d rotMatr, CvMatr64d transVect ) { double tmpVect[3]; icvMulMatrix_64d( rotMatr, 3,3, (double*)&M2, 1,3, tmpVect); icvAddVector_64d(tmpVect,transVect,(double*)M1,3); return CV_NO_ERR; } /*--------------------------------------------------------------------------------------*/ int icvComputeCoeffForStereoV3( double quad1[4][2], double quad2[4][2], int numScanlines, CvMatr64d camMatr1, CvMatr64d rotMatr1, CvMatr64d transVect1, CvMatr64d camMatr2, CvMatr64d rotMatr2, CvMatr64d transVect2, CvStereoLineCoeff* startCoeffs, int* needSwapCamera) { /* For each pair */ /* In this function we must define position of cameras */ CvPoint2D64d point1; CvPoint2D64d point2; CvPoint2D64d point3; CvPoint2D64d point4; int currLine; *needSwapCamera = 0; for( currLine = 0; currLine < numScanlines; currLine++ ) { /* Compute points */ double alpha = ((double)currLine)/((double)(numScanlines)); /* maybe - 1 */ point1.x = (1.0 - alpha) * quad1[0][0] + alpha * quad1[3][0]; point1.y = (1.0 - alpha) * quad1[0][1] + alpha * quad1[3][1]; point2.x = (1.0 - alpha) * quad1[1][0] + alpha * quad1[2][0]; point2.y = (1.0 - alpha) * quad1[1][1] + alpha * quad1[2][1]; point3.x = (1.0 - alpha) * quad2[0][0] + alpha * quad2[3][0]; point3.y = (1.0 - alpha) * quad2[0][1] + alpha * quad2[3][1]; point4.x = (1.0 - alpha) * quad2[1][0] + alpha * quad2[2][0]; point4.y = (1.0 - alpha) * quad2[1][1] + alpha * quad2[2][1]; /* We can compute coeffs for this line */ icvComCoeffForLine( point1, point2, point3, point4, camMatr1, rotMatr1, transVect1, camMatr2, rotMatr2, transVect2, &startCoeffs[currLine], needSwapCamera); } return CV_NO_ERR; } /*--------------------------------------------------------------------------------------*/ int icvComputeCoeffForStereoNew( double quad1[4][2], double quad2[4][2], int numScanlines, CvMatr32f camMatr1, CvMatr32f rotMatr1, CvMatr32f transVect1, CvMatr32f camMatr2, CvStereoLineCoeff* startCoeffs, int* needSwapCamera) { /* Convert data */ double camMatr1_64d[9]; double camMatr2_64d[9]; double rotMatr1_64d[9]; double transVect1_64d[3]; double rotMatr2_64d[9]; double transVect2_64d[3]; icvCvt_32f_64d(camMatr1,camMatr1_64d,9); icvCvt_32f_64d(camMatr2,camMatr2_64d,9); icvCvt_32f_64d(rotMatr1,rotMatr1_64d,9); icvCvt_32f_64d(transVect1,transVect1_64d,3); rotMatr2_64d[0] = 1; rotMatr2_64d[1] = 0; rotMatr2_64d[2] = 0; rotMatr2_64d[3] = 0; rotMatr2_64d[4] = 1; rotMatr2_64d[5] = 0; rotMatr2_64d[6] = 0; rotMatr2_64d[7] = 0; rotMatr2_64d[8] = 1; transVect2_64d[0] = 0; transVect2_64d[1] = 0; transVect2_64d[2] = 0; int status = icvComputeCoeffForStereoV3( quad1, quad2, numScanlines, camMatr1_64d, rotMatr1_64d, transVect1_64d, camMatr2_64d, rotMatr2_64d, transVect2_64d, startCoeffs, needSwapCamera); return status; } /*--------------------------------------------------------------------------------------*/ int icvComputeCoeffForStereo( CvStereoCamera* stereoCamera) { double quad1[4][2]; double quad2[4][2]; int i; for( i = 0; i < 4; i++ ) { quad1[i][0] = stereoCamera->quad[0][i].x; quad1[i][1] = stereoCamera->quad[0][i].y; quad2[i][0] = stereoCamera->quad[1][i].x; quad2[i][1] = stereoCamera->quad[1][i].y; } icvComputeCoeffForStereoNew( quad1, quad2, stereoCamera->warpSize.height, stereoCamera->camera[0]->matrix, stereoCamera->rotMatrix, stereoCamera->transVector, stereoCamera->camera[1]->matrix, stereoCamera->lineCoeffs, &(stereoCamera->needSwapCameras)); return CV_OK; } /*--------------------------------------------------------------------------------------*/ int icvComCoeffForLine( CvPoint2D64d point1, CvPoint2D64d point2, CvPoint2D64d point3, CvPoint2D64d point4, CvMatr64d camMatr1, CvMatr64d rotMatr1, CvMatr64d transVect1, CvMatr64d camMatr2, CvMatr64d rotMatr2, CvMatr64d transVect2, CvStereoLineCoeff* coeffs, int* needSwapCamera) { /* Get direction for all points */ /* Direction for camera 1 */ double direct1[3]; double direct2[3]; double camPoint1[3]; double directS3[3]; double directS4[3]; double direct3[3]; double direct4[3]; double camPoint2[3]; icvGetDirectionForPoint( point1, camMatr1, (CvPoint3D64d*)direct1); icvGetDirectionForPoint( point2, camMatr1, (CvPoint3D64d*)direct2); /* Direction for camera 2 */ icvGetDirectionForPoint( point3, camMatr2, (CvPoint3D64d*)directS3); icvGetDirectionForPoint( point4, camMatr2, (CvPoint3D64d*)directS4); /* Create convertion for camera 2: two direction and camera point */ double convRotMatr[9]; double convTransVect[3]; icvCreateConvertMatrVect( rotMatr1, transVect1, rotMatr2, transVect2, convRotMatr, convTransVect); double zeroVect[3]; zeroVect[0] = zeroVect[1] = zeroVect[2] = 0.0; camPoint1[0] = camPoint1[1] = camPoint1[2] = 0.0; icvConvertPointSystem(*((CvPoint3D64d*)directS3),(CvPoint3D64d*)direct3,convRotMatr,convTransVect); icvConvertPointSystem(*((CvPoint3D64d*)directS4),(CvPoint3D64d*)direct4,convRotMatr,convTransVect); icvConvertPointSystem(*((CvPoint3D64d*)zeroVect),(CvPoint3D64d*)camPoint2,convRotMatr,convTransVect); double pointB[3]; int postype = 0; /* Changed order */ /* Compute point B: xB,yB,zB */ icvGetCrossLines(*((CvPoint3D64d*)camPoint1),*((CvPoint3D64d*)direct2), *((CvPoint3D64d*)camPoint2),*((CvPoint3D64d*)direct3), (CvPoint3D64d*)pointB); if( pointB[2] < 0 )/* If negative use other lines for cross */ { postype = 1; icvGetCrossLines(*((CvPoint3D64d*)camPoint1),*((CvPoint3D64d*)direct1), *((CvPoint3D64d*)camPoint2),*((CvPoint3D64d*)direct4), (CvPoint3D64d*)pointB); } CvPoint3D64d pointNewA; CvPoint3D64d pointNewC; pointNewA.x = pointNewA.y = pointNewA.z = 0; pointNewC.x = pointNewC.y = pointNewC.z = 0; if( postype == 0 ) { icvGetSymPoint3D( *((CvPoint3D64d*)camPoint1), *((CvPoint3D64d*)direct1), *((CvPoint3D64d*)pointB), &pointNewA); icvGetSymPoint3D( *((CvPoint3D64d*)camPoint2), *((CvPoint3D64d*)direct4), *((CvPoint3D64d*)pointB), &pointNewC); } else {/* In this case we must change cameras */ *needSwapCamera = 1; icvGetSymPoint3D( *((CvPoint3D64d*)camPoint2), *((CvPoint3D64d*)direct3), *((CvPoint3D64d*)pointB), &pointNewA); icvGetSymPoint3D( *((CvPoint3D64d*)camPoint1), *((CvPoint3D64d*)direct2), *((CvPoint3D64d*)pointB), &pointNewC); } double gamma; double x1,y1,z1; x1 = camPoint1[0]; y1 = camPoint1[1]; z1 = camPoint1[2]; double xA,yA,zA; double xB,yB,zB; double xC,yC,zC; xA = pointNewA.x; yA = pointNewA.y; zA = pointNewA.z; xB = pointB[0]; yB = pointB[1]; zB = pointB[2]; xC = pointNewC.x; yC = pointNewC.y; zC = pointNewC.z; double len1,len2; len1 = sqrt( (xA-xB)*(xA-xB) + (yA-yB)*(yA-yB) + (zA-zB)*(zA-zB) ); len2 = sqrt( (xB-xC)*(xB-xC) + (yB-yC)*(yB-yC) + (zB-zC)*(zB-zC) ); gamma = len2 / len1; icvComputeStereoLineCoeffs( pointNewA, *((CvPoint3D64d*)pointB), *((CvPoint3D64d*)camPoint1), gamma, coeffs); return CV_NO_ERR; } /*--------------------------------------------------------------------------------------*/ int icvGetDirectionForPoint( CvPoint2D64d point, CvMatr64d camMatr, CvPoint3D64d* direct) { /* */ double invMatr[9]; /* Invert matrix */ icvInvertMatrix_64d(camMatr,3,invMatr); /* TEST FOR ERRORS */ double vect[3]; vect[0] = point.x; vect[1] = point.y; vect[2] = 1; /* Mul matr */ icvMulMatrix_64d( invMatr, 3,3, vect, 1,3, (double*)direct); return CV_NO_ERR; } /*--------------------------------------------------------------------------------------*/ int icvGetCrossLines(CvPoint3D64d point11,CvPoint3D64d point12, CvPoint3D64d point21,CvPoint3D64d point22, CvPoint3D64d* midPoint) { double xM,yM,zM; double xN,yN,zN; double xA,yA,zA; double xB,yB,zB; double xC,yC,zC; double xD,yD,zD; xA = point11.x; yA = point11.y; zA = point11.z; xB = point12.x; yB = point12.y; zB = point12.z; xC = point21.x; yC = point21.y; zC = point21.z; xD = point22.x; yD = point22.y; zD = point22.z; double a11,a12,a21,a22; double b1,b2; a11 = (xB-xA)*(xB-xA)+(yB-yA)*(yB-yA)+(zB-zA)*(zB-zA); a12 = -(xD-xC)*(xB-xA)-(yD-yC)*(yB-yA)-(zD-zC)*(zB-zA); a21 = (xB-xA)*(xD-xC)+(yB-yA)*(yD-yC)+(zB-zA)*(zD-zC); a22 = -(xD-xC)*(xD-xC)-(yD-yC)*(yD-yC)-(zD-zC)*(zD-zC); b1 = -( (xA-xC)*(xB-xA)+(yA-yC)*(yB-yA)+(zA-zC)*(zB-zA) ); b2 = -( (xA-xC)*(xD-xC)+(yA-yC)*(yD-yC)+(zA-zC)*(zD-zC) ); double delta; double deltaA,deltaB; double alpha,betta; delta = a11*a22-a12*a21; if( fabs(delta) < EPS64D ) { /*return ERROR;*/ } deltaA = b1*a22-b2*a12; deltaB = a11*b2-b1*a21; alpha = deltaA / delta; betta = deltaB / delta; xM = xA+alpha*(xB-xA); yM = yA+alpha*(yB-yA); zM = zA+alpha*(zB-zA); xN = xC+betta*(xD-xC); yN = yC+betta*(yD-yC); zN = zC+betta*(zD-zC); /* Compute middle point */ midPoint->x = (xM + xN) * 0.5; midPoint->y = (yM + yN) * 0.5; midPoint->z = (zM + zN) * 0.5; return CV_NO_ERR; } /*--------------------------------------------------------------------------------------*/ int icvComputeStereoLineCoeffs( CvPoint3D64d pointA, CvPoint3D64d pointB, CvPoint3D64d pointCam1, double gamma, CvStereoLineCoeff* coeffs) { double x1,y1,z1; x1 = pointCam1.x; y1 = pointCam1.y; z1 = pointCam1.z; double xA,yA,zA; double xB,yB,zB; xA = pointA.x; yA = pointA.y; zA = pointA.z; xB = pointB.x; yB = pointB.y; zB = pointB.z; if( gamma > 0 ) { coeffs->Xcoef = -x1 + xA; coeffs->XcoefA = xB + x1 - xA; coeffs->XcoefB = -xA - gamma * x1 + gamma * xA; coeffs->XcoefAB = -xB + xA + gamma * xB - gamma * xA; coeffs->Ycoef = -y1 + yA; coeffs->YcoefA = yB + y1 - yA; coeffs->YcoefB = -yA - gamma * y1 + gamma * yA; coeffs->YcoefAB = -yB + yA + gamma * yB - gamma * yA; coeffs->Zcoef = -z1 + zA; coeffs->ZcoefA = zB + z1 - zA; coeffs->ZcoefB = -zA - gamma * z1 + gamma * zA; coeffs->ZcoefAB = -zB + zA + gamma * zB - gamma * zA; } else { gamma = - gamma; coeffs->Xcoef = -( -x1 + xA); coeffs->XcoefB = -( xB + x1 - xA); coeffs->XcoefA = -( -xA - gamma * x1 + gamma * xA); coeffs->XcoefAB = -( -xB + xA + gamma * xB - gamma * xA); coeffs->Ycoef = -( -y1 + yA); coeffs->YcoefB = -( yB + y1 - yA); coeffs->YcoefA = -( -yA - gamma * y1 + gamma * yA); coeffs->YcoefAB = -( -yB + yA + gamma * yB - gamma * yA); coeffs->Zcoef = -( -z1 + zA); coeffs->ZcoefB = -( zB + z1 - zA); coeffs->ZcoefA = -( -zA - gamma * z1 + gamma * zA); coeffs->ZcoefAB = -( -zB + zA + gamma * zB - gamma * zA); } return CV_NO_ERR; } /*--------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------*/ /* This function get minimum angle started at point which contains rect */ int icvGetAngleLine( CvPoint2D64d startPoint, CvSize imageSize,CvPoint2D64d *point1,CvPoint2D64d *point2) { /* Get crosslines with image corners */ /* Find four lines */ CvPoint2D64d pa,pb,pc,pd; pa.x = 0; pa.y = 0; pb.x = imageSize.width-1; pb.y = 0; pd.x = imageSize.width-1; pd.y = imageSize.height-1; pc.x = 0; pc.y = imageSize.height-1; /* We can compute points for angle */ /* Test for place section */ if( startPoint.x < 0 ) {/* 1,4,7 */ if( startPoint.y < 0) {/* 1 */ *point1 = pb; *point2 = pc; } else if( startPoint.y > imageSize.height-1 ) {/* 7 */ *point1 = pa; *point2 = pd; } else {/* 4 */ *point1 = pa; *point2 = pc; } } else if ( startPoint.x > imageSize.width-1 ) {/* 3,6,9 */ if( startPoint.y < 0 ) {/* 3 */ *point1 = pa; *point2 = pd; } else if ( startPoint.y > imageSize.height-1 ) {/* 9 */ *point1 = pb; *point2 = pc; } else {/* 6 */ *point1 = pb; *point2 = pd; } } else {/* 2,5,8 */ if( startPoint.y < 0 ) {/* 2 */ if( startPoint.x < imageSize.width/2 ) { *point1 = pb; *point2 = pa; } else { *point1 = pa; *point2 = pb; } } else if( startPoint.y > imageSize.height-1 ) {/* 8 */ if( startPoint.x < imageSize.width/2 ) { *point1 = pc; *point2 = pd; } else { *point1 = pd; *point2 = pc; } } else {/* 5 - point in the image */ return 2; } } return 0; }/* GetAngleLine */ /*---------------------------------------------------------------------------------------*/ void icvGetCoefForPiece( CvPoint2D64d p_start,CvPoint2D64d p_end, double *a,double *b,double *c, int* result) { double det; double detA,detB,detC; 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; if( fabs(det) < EPS64D)/* Error */ { *result = 0; return; } detA = p_start.y - p_end.y; detB = p_end.x - p_start.x; detC = p_start.x*p_end.y - p_end.x*p_start.y; double invDet = 1.0 / det; *a = detA * invDet; *b = detB * invDet; *c = detC * invDet; *result = 1; return; } /*---------------------------------------------------------------------------------------*/ /* Get common area of rectifying */ void icvGetCommonArea( CvSize imageSize, CvPoint3D64d epipole1,CvPoint3D64d epipole2, CvMatr64d fundMatr, CvVect64d coeff11,CvVect64d coeff12, CvVect64d coeff21,CvVect64d coeff22, int* result) { int res = 0; CvPoint2D64d point11; CvPoint2D64d point12; CvPoint2D64d point21; CvPoint2D64d point22; double corr11[3]; double corr12[3]; double corr21[3]; double corr22[3]; double pointW11[3]; double pointW12[3]; double pointW21[3]; double pointW22[3]; double transFundMatr[3*3]; /* Compute transpose of fundamental matrix */ icvTransposeMatrix_64d( fundMatr, 3, 3, transFundMatr ); CvPoint2D64d epipole1_2d; CvPoint2D64d epipole2_2d; if( fabs(epipole1.z) < 1e-8 ) {/* epipole1 in infinity */ *result = 0; return; } epipole1_2d.x = epipole1.x / epipole1.z; epipole1_2d.y = epipole1.y / epipole1.z; if( fabs(epipole2.z) < 1e-8 ) {/* epipole2 in infinity */ *result = 0; return; } epipole2_2d.x = epipole2.x / epipole2.z; epipole2_2d.y = epipole2.y / epipole2.z; int stat = icvGetAngleLine( epipole1_2d, imageSize,&point11,&point12); if( stat == 2 ) { /* No angle */ *result = 0; return; } stat = icvGetAngleLine( epipole2_2d, imageSize,&point21,&point22); if( stat == 2 ) { /* No angle */ *result = 0; return; } /* ============= Computation for line 1 ================ */ /* Find correspondence line for angle points11 */ /* corr21 = Fund'*p1 */ pointW11[0] = point11.x; pointW11[1] = point11.y; pointW11[2] = 1.0; icvTransformVector_64d( transFundMatr, /* !!! Modified from not transposed */ pointW11, corr21, 3,3); /* Find crossing of line with image 2 */ CvPoint2D64d start; CvPoint2D64d end; icvGetCrossRectDirect( imageSize, corr21[0],corr21[1],corr21[2], &start,&end, &res); if( res == 0 ) {/* We have not cross */ /* We must define new angle */ pointW21[0] = point21.x; pointW21[1] = point21.y; pointW21[2] = 1.0; /* Find correspondence line for this angle points */ /* We know point and try to get corr line */ /* For point21 */ /* corr11 = Fund * p21 */ icvTransformVector_64d( fundMatr, /* !!! Modified */ pointW21, corr11, 3,3); /* We have cross. And it's result cross for up line. Set result coefs */ /* Set coefs for line 1 image 1 */ coeff11[0] = corr11[0]; coeff11[1] = corr11[1]; coeff11[2] = corr11[2]; /* Set coefs for line 1 image 2 */ icvGetCoefForPiece( epipole2_2d,point21, &coeff21[0],&coeff21[1],&coeff21[2], &res); if( res == 0 ) { *result = 0; return;/* Error */ } } else {/* Line 1 cross image 2 */ /* Set coefs for line 1 image 1 */ icvGetCoefForPiece( epipole1_2d,point11, &coeff11[0],&coeff11[1],&coeff11[2], &res); if( res == 0 ) { *result = 0; return;/* Error */ } /* Set coefs for line 1 image 2 */ coeff21[0] = corr21[0]; coeff21[1] = corr21[1]; coeff21[2] = corr21[2]; } /* ============= Computation for line 2 ================ */ /* Find correspondence line for angle points11 */ /* corr22 = Fund*p2 */ pointW12[0] = point12.x; pointW12[1] = point12.y; pointW12[2] = 1.0; icvTransformVector_64d( transFundMatr, pointW12, corr22, 3,3); /* Find crossing of line with image 2 */ icvGetCrossRectDirect( imageSize, corr22[0],corr22[1],corr22[2], &start,&end, &res); if( res == 0 ) {/* We have not cross */ /* We must define new angle */ pointW22[0] = point22.x; pointW22[1] = point22.y; pointW22[2] = 1.0; /* Find correspondence line for this angle points */ /* We know point and try to get corr line */ /* For point21 */ /* corr2 = Fund' * p1 */ icvTransformVector_64d( fundMatr, pointW22, corr12, 3,3); /* We have cross. And it's result cross for down line. Set result coefs */ /* Set coefs for line 2 image 1 */ coeff12[0] = corr12[0]; coeff12[1] = corr12[1]; coeff12[2] = corr12[2]; /* Set coefs for line 1 image 2 */ icvGetCoefForPiece( epipole2_2d,point22, &coeff22[0],&coeff22[1],&coeff22[2], &res); if( res == 0 ) { *result = 0; return;/* Error */ } } else {/* Line 2 cross image 2 */ /* Set coefs for line 2 image 1 */ icvGetCoefForPiece( epipole1_2d,point12, &coeff12[0],&coeff12[1],&coeff12[2], &res); if( res == 0 ) { *result = 0; return;/* Error */ } /* Set coefs for line 1 image 2 */ coeff22[0] = corr22[0]; coeff22[1] = corr22[1]; coeff22[2] = corr22[2]; } /* Now we know common area */ return; }/* GetCommonArea */ /*---------------------------------------------------------------------------------------*/ /* Get cross for direction1 and direction2 */ /* Result = 1 - cross */ /* Result = 2 - parallel and not equal */ /* Result = 3 - parallel and equal */ void icvGetCrossDirectDirect( CvVect64d direct1,CvVect64d direct2, CvPoint2D64d *cross,int* result) { double det = direct1[0]*direct2[1] - direct2[0]*direct1[1]; double detx = -direct1[2]*direct2[1] + direct1[1]*direct2[2]; if( fabs(det) > EPS64D ) {/* Have cross */ cross->x = detx/det; cross->y = (-direct1[0]*direct2[2] + direct2[0]*direct1[2])/det; *result = 1; } else {/* may be parallel */ if( fabs(detx) > EPS64D ) {/* parallel and not equal */ *result = 2; } else {/* equals */ *result = 3; } } return; } /*---------------------------------------------------------------------------------------*/ /* Get cross for piece p1,p2 and direction a,b,c */ /* Result = 0 - no cross */ /* Result = 1 - cross */ /* Result = 2 - parallel and not equal */ /* Result = 3 - parallel and equal */ void icvGetCrossPieceDirect( CvPoint2D64d p_start,CvPoint2D64d p_end, double a,double b,double c, CvPoint2D64d *cross,int* result) { if( (a*p_start.x + b*p_start.y + c) * (a*p_end.x + b*p_end.y + c) <= 0 ) {/* Have cross */ double det; double detxc,detyc; det = a * (p_end.x - p_start.x) + b * (p_end.y - p_start.y); if( fabs(det) < EPS64D ) {/* lines are parallel and may be equal or line is point */ if( fabs(a*p_start.x + b*p_start.y + c) < EPS64D ) {/* line is point or not diff */ *result = 3; return; } else { *result = 2; } return; } detxc = b*(p_end.y*p_start.x - p_start.y*p_end.x) + c*(p_start.x - p_end.x); detyc = a*(p_end.x*p_start.y - p_start.x*p_end.y) + c*(p_start.y - p_end.y); cross->x = detxc / det; cross->y = detyc / det; *result = 1; } else { *result = 0; } return; } /*--------------------------------------------------------------------------------------*/ void icvGetCrossPiecePiece( CvPoint2D64d p1_start,CvPoint2D64d p1_end, CvPoint2D64d p2_start,CvPoint2D64d p2_end, CvPoint2D64d* cross, int* result) { double ex1,ey1,ex2,ey2; double px1,py1,px2,py2; double del; double delA,delB,delX,delY; double alpha,betta; ex1 = p1_start.x; ey1 = p1_start.y; ex2 = p1_end.x; ey2 = p1_end.y; px1 = p2_start.x; py1 = p2_start.y; px2 = p2_end.x; py2 = p2_end.y; del = (py1-py2)*(ex1-ex2)-(px1-px2)*(ey1-ey2); if( fabs(del) <= EPS64D ) {/* May be they are parallel !!! */ *result = 0; return; } delA = (ey1-ey2)*(ex1-px1) + (ex1-ex2)*(py1-ey1); delB = (py1-py2)*(ex1-px1) + (px1-px2)*(py1-ey1); alpha = delA / del; betta = delB / del; if( alpha < 0 || alpha > 1.0 || betta < 0 || betta > 1.0) { *result = 0; return; } delX = (px1-px2)*(ey1*(ex1-ex2)-ex1*(ey1-ey2))+ (ex1-ex2)*(px1*(py1-py2)-py1*(px1-px2)); delY = (py1-py2)*(ey1*(ex1-ex2)-ex1*(ey1-ey2))+ (ey1-ey2)*(px1*(py1-py2)-py1*(px1-px2)); cross->x = delX / del; cross->y = delY / del; *result = 1; return; } /*---------------------------------------------------------------------------------------*/ void icvGetPieceLength(CvPoint2D64d point1,CvPoint2D64d point2,double* dist) { double dx = point2.x - point1.x; double dy = point2.y - point1.y; *dist = sqrt( dx*dx + dy*dy ); return; } /*---------------------------------------------------------------------------------------*/ void icvGetPieceLength3D(CvPoint3D64d point1,CvPoint3D64d point2,double* dist) { double dx = point2.x - point1.x; double dy = point2.y - point1.y; double dz = point2.z - point1.z; *dist = sqrt( dx*dx + dy*dy + dz*dz ); return; } /*---------------------------------------------------------------------------------------*/ /* Find line from epipole which cross image rect */ /* Find points of cross 0 or 1 or 2. Return number of points in cross */ void icvGetCrossRectDirect( CvSize imageSize, double a,double b,double c, CvPoint2D64d *start,CvPoint2D64d *end, int* result) { CvPoint2D64d frameBeg; CvPoint2D64d frameEnd; CvPoint2D64d cross[4]; int haveCross[4]; haveCross[0] = 0; haveCross[1] = 0; haveCross[2] = 0; haveCross[3] = 0; frameBeg.x = 0; frameBeg.y = 0; frameEnd.x = imageSize.width; frameEnd.y = 0; icvGetCrossPieceDirect(frameBeg,frameEnd,a,b,c,&cross[0],&haveCross[0]); frameBeg.x = imageSize.width; frameBeg.y = 0; frameEnd.x = imageSize.width; frameEnd.y = imageSize.height; icvGetCrossPieceDirect(frameBeg,frameEnd,a,b,c,&cross[1],&haveCross[1]); frameBeg.x = imageSize.width; frameBeg.y = imageSize.height; frameEnd.x = 0; frameEnd.y = imageSize.height; icvGetCrossPieceDirect(frameBeg,frameEnd,a,b,c,&cross[2],&haveCross[2]); frameBeg.x = 0; frameBeg.y = imageSize.height; frameEnd.x = 0; frameEnd.y = 0; icvGetCrossPieceDirect(frameBeg,frameEnd,a,b,c,&cross[3],&haveCross[3]); double maxDist; int maxI=0,maxJ=0; int i,j; maxDist = -1.0; double distance; for( i = 0; i < 3; i++ ) { if( haveCross[i] == 1 ) { for( j = i + 1; j < 4; j++ ) { if( haveCross[j] == 1) {/* Compute dist */ icvGetPieceLength(cross[i],cross[j],&distance); if( distance > maxDist ) { maxI = i; maxJ = j; maxDist = distance; } } } } } if( maxDist >= 0 ) {/* We have cross */ *start = cross[maxI]; *result = 1; if( maxDist > 0 ) { *end = cross[maxJ]; *result = 2; } } else { *result = 0; } return; }/* GetCrossRectDirect */ /*---------------------------------------------------------------------------------------*/ void icvProjectPointToImage( CvPoint3D64d point, CvMatr64d camMatr,CvMatr64d rotMatr,CvVect64d transVect, CvPoint2D64d* projPoint) { double tmpVect1[3]; double tmpVect2[3]; icvMulMatrix_64d ( rotMatr, 3,3, (double*)&point, 1,3, tmpVect1); icvAddVector_64d ( tmpVect1, transVect,tmpVect2, 3); icvMulMatrix_64d ( camMatr, 3,3, tmpVect2, 1,3, tmpVect1); projPoint->x = tmpVect1[0] / tmpVect1[2]; projPoint->y = tmpVect1[1] / tmpVect1[2]; return; } /*---------------------------------------------------------------------------------------*/ /* Get quads for transform images */ void icvGetQuadsTransform( CvSize imageSize, CvMatr64d camMatr1, CvMatr64d rotMatr1, CvVect64d transVect1, CvMatr64d camMatr2, CvMatr64d rotMatr2, CvVect64d transVect2, CvSize* warpSize, double quad1[4][2], double quad2[4][2], CvMatr64d fundMatr, CvPoint3D64d* epipole1, CvPoint3D64d* epipole2 ) { /* First compute fundamental matrix and epipoles */ int res; /* Compute epipoles and fundamental matrix using new functions */ { double convRotMatr[9]; double convTransVect[3]; icvCreateConvertMatrVect( rotMatr1, transVect1, rotMatr2, transVect2, convRotMatr, convTransVect); float convRotMatr_32f[9]; float convTransVect_32f[3]; icvCvt_64d_32f(convRotMatr,convRotMatr_32f,9); icvCvt_64d_32f(convTransVect,convTransVect_32f,3); /* We know R and t */ /* Compute essential matrix */ float essMatr[9]; float fundMatr_32f[9]; float camMatr1_32f[9]; float camMatr2_32f[9]; icvCvt_64d_32f(camMatr1,camMatr1_32f,9); icvCvt_64d_32f(camMatr2,camMatr2_32f,9); cvComputeEssentialMatrix( convRotMatr_32f, convTransVect_32f, essMatr); cvConvertEssential2Fundamental( essMatr, fundMatr_32f, camMatr1_32f, camMatr2_32f); CvPoint3D32f epipole1_32f; CvPoint3D32f epipole2_32f; cvComputeEpipolesFromFundMatrix( fundMatr_32f, &epipole1_32f, &epipole2_32f); /* copy to 64d epipoles */ epipole1->x = epipole1_32f.x; epipole1->y = epipole1_32f.y; epipole1->z = epipole1_32f.z; epipole2->x = epipole2_32f.x; epipole2->y = epipole2_32f.y; epipole2->z = epipole2_32f.z; /* Convert fundamental matrix */ icvCvt_32f_64d(fundMatr_32f,fundMatr,9); } double coeff11[3]; double coeff12[3]; double coeff21[3]; double coeff22[3]; icvGetCommonArea( imageSize, *epipole1,*epipole2, fundMatr, coeff11,coeff12, coeff21,coeff22, &res); CvPoint2D64d point11, point12,point21, point22; double width1,width2; double height1,height2; double tmpHeight1,tmpHeight2; CvPoint2D64d epipole1_2d; CvPoint2D64d epipole2_2d; /* ----- Image 1 ----- */ if( fabs(epipole1->z) < 1e-8 ) { return; } epipole1_2d.x = epipole1->x / epipole1->z; epipole1_2d.y = epipole1->y / epipole1->z; icvGetCutPiece( coeff11,coeff12, epipole1_2d, imageSize, &point11,&point12, &point21,&point22, &res); /* Compute distance */ icvGetPieceLength(point11,point21,&width1); icvGetPieceLength(point11,point12,&tmpHeight1); icvGetPieceLength(point21,point22,&tmpHeight2); height1 = MAX(tmpHeight1,tmpHeight2); quad1[0][0] = point11.x; quad1[0][1] = point11.y; quad1[1][0] = point21.x; quad1[1][1] = point21.y; quad1[2][0] = point22.x; quad1[2][1] = point22.y; quad1[3][0] = point12.x; quad1[3][1] = point12.y; /* ----- Image 2 ----- */ if( fabs(epipole2->z) < 1e-8 ) { return; } epipole2_2d.x = epipole2->x / epipole2->z; epipole2_2d.y = epipole2->y / epipole2->z; icvGetCutPiece( coeff21,coeff22, epipole2_2d, imageSize, &point11,&point12, &point21,&point22, &res); /* Compute distance */ icvGetPieceLength(point11,point21,&width2); icvGetPieceLength(point11,point12,&tmpHeight1); icvGetPieceLength(point21,point22,&tmpHeight2); height2 = MAX(tmpHeight1,tmpHeight2); quad2[0][0] = point11.x; quad2[0][1] = point11.y; quad2[1][0] = point21.x; quad2[1][1] = point21.y; quad2[2][0] = point22.x; quad2[2][1] = point22.y; quad2[3][0] = point12.x; quad2[3][1] = point12.y; /*=======================================================*/ /* This is a new additional way to compute quads. */ /* We must correct quads */ { double convRotMatr[9]; double convTransVect[3]; double newQuad1[4][2]; double newQuad2[4][2]; icvCreateConvertMatrVect( rotMatr1, transVect1, rotMatr2, transVect2, convRotMatr, convTransVect); /* -------------Compute for first image-------------- */ CvPoint2D32f pointb1; CvPoint2D32f pointe1; CvPoint2D32f pointb2; CvPoint2D32f pointe2; pointb1.x = (float)quad1[0][0]; pointb1.y = (float)quad1[0][1]; pointe1.x = (float)quad1[3][0]; pointe1.y = (float)quad1[3][1]; icvComputeeInfiniteProject1(convRotMatr, camMatr1, camMatr2, pointb1, &pointb2); icvComputeeInfiniteProject1(convRotMatr, camMatr1, camMatr2, pointe1, &pointe2); /* JUST TEST FOR POINT */ /* Compute distances */ double dxOld,dyOld; double dxNew,dyNew; double distOld,distNew; dxOld = quad2[1][0] - quad2[0][0]; dyOld = quad2[1][1] - quad2[0][1]; distOld = dxOld*dxOld + dyOld*dyOld; dxNew = quad2[1][0] - pointb2.x; dyNew = quad2[1][1] - pointb2.y; distNew = dxNew*dxNew + dyNew*dyNew; if( distNew > distOld ) {/* Get new points for second quad */ newQuad2[0][0] = pointb2.x; newQuad2[0][1] = pointb2.y; newQuad2[3][0] = pointe2.x; newQuad2[3][1] = pointe2.y; newQuad1[0][0] = quad1[0][0]; newQuad1[0][1] = quad1[0][1]; newQuad1[3][0] = quad1[3][0]; newQuad1[3][1] = quad1[3][1]; } else {/* Get new points for first quad */ pointb2.x = (float)quad2[0][0]; pointb2.y = (float)quad2[0][1]; pointe2.x = (float)quad2[3][0]; pointe2.y = (float)quad2[3][1]; icvComputeeInfiniteProject2(convRotMatr, camMatr1, camMatr2, &pointb1, pointb2); icvComputeeInfiniteProject2(convRotMatr, camMatr1, camMatr2, &pointe1, pointe2); /* JUST TEST FOR POINT */ newQuad2[0][0] = quad2[0][0]; newQuad2[0][1] = quad2[0][1]; newQuad2[3][0] = quad2[3][0]; newQuad2[3][1] = quad2[3][1]; newQuad1[0][0] = pointb1.x; newQuad1[0][1] = pointb1.y; newQuad1[3][0] = pointe1.x; newQuad1[3][1] = pointe1.y; } /* -------------Compute for second image-------------- */ pointb1.x = (float)quad1[1][0]; pointb1.y = (float)quad1[1][1]; pointe1.x = (float)quad1[2][0]; pointe1.y = (float)quad1[2][1]; icvComputeeInfiniteProject1(convRotMatr, camMatr1, camMatr2, pointb1, &pointb2); icvComputeeInfiniteProject1(convRotMatr, camMatr1, camMatr2, pointe1, &pointe2); /* Compute distances */ dxOld = quad2[0][0] - quad2[1][0]; dyOld = quad2[0][1] - quad2[1][1]; distOld = dxOld*dxOld + dyOld*dyOld; dxNew = quad2[0][0] - pointb2.x; dyNew = quad2[0][1] - pointb2.y; distNew = dxNew*dxNew + dyNew*dyNew; if( distNew > distOld ) {/* Get new points for second quad */ newQuad2[1][0] = pointb2.x; newQuad2[1][1] = pointb2.y; newQuad2[2][0] = pointe2.x; newQuad2[2][1] = pointe2.y; newQuad1[1][0] = quad1[1][0]; newQuad1[1][1] = quad1[1][1]; newQuad1[2][0] = quad1[2][0]; newQuad1[2][1] = quad1[2][1]; } else {/* Get new points for first quad */ pointb2.x = (float)quad2[1][0]; pointb2.y = (float)quad2[1][1]; pointe2.x = (float)quad2[2][0]; pointe2.y = (float)quad2[2][1]; icvComputeeInfiniteProject2(convRotMatr, camMatr1, camMatr2, &pointb1, pointb2); icvComputeeInfiniteProject2(convRotMatr, camMatr1, camMatr2, &pointe1, pointe2); newQuad2[1][0] = quad2[1][0]; newQuad2[1][1] = quad2[1][1]; newQuad2[2][0] = quad2[2][0]; newQuad2[2][1] = quad2[2][1]; newQuad1[1][0] = pointb1.x; newQuad1[1][1] = pointb1.y; newQuad1[2][0] = pointe1.x; newQuad1[2][1] = pointe1.y; } /*-------------------------------------------------------------------------------*/ /* Copy new quads to old quad */ int i; for( i = 0; i < 4; i++ ) { { quad1[i][0] = newQuad1[i][0]; quad1[i][1] = newQuad1[i][1]; quad2[i][0] = newQuad2[i][0]; quad2[i][1] = newQuad2[i][1]; } } } /*=======================================================*/ double warpWidth,warpHeight; warpWidth = MAX(width1,width2); warpHeight = MAX(height1,height2); warpSize->width = (int)warpWidth; warpSize->height = (int)warpHeight; warpSize->width = cvRound(warpWidth-1); warpSize->height = cvRound(warpHeight-1); /* !!! by Valery Mosyagin. this lines added just for test no warp */ warpSize->width = imageSize.width; warpSize->height = imageSize.height; return; } /*---------------------------------------------------------------------------------------*/ void icvGetQuadsTransformNew( CvSize imageSize, CvMatr32f camMatr1, CvMatr32f camMatr2, CvMatr32f rotMatr1, CvVect32f transVect1, CvSize* warpSize, double quad1[4][2], double quad2[4][2], CvMatr32f fundMatr, CvPoint3D32f* epipole1, CvPoint3D32f* epipole2 ) { /* Convert data */ /* Convert camera matrix */ double camMatr1_64d[9]; double camMatr2_64d[9]; double rotMatr1_64d[9]; double transVect1_64d[3]; double rotMatr2_64d[9]; double transVect2_64d[3]; double fundMatr_64d[9]; CvPoint3D64d epipole1_64d; CvPoint3D64d epipole2_64d; icvCvt_32f_64d(camMatr1,camMatr1_64d,9); icvCvt_32f_64d(camMatr2,camMatr2_64d,9); icvCvt_32f_64d(rotMatr1,rotMatr1_64d,9); icvCvt_32f_64d(transVect1,transVect1_64d,3); /* Create vector and matrix */ rotMatr2_64d[0] = 1; rotMatr2_64d[1] = 0; rotMatr2_64d[2] = 0; rotMatr2_64d[3] = 0; rotMatr2_64d[4] = 1; rotMatr2_64d[5] = 0; rotMatr2_64d[6] = 0; rotMatr2_64d[7] = 0; rotMatr2_64d[8] = 1; transVect2_64d[0] = 0; transVect2_64d[1] = 0; transVect2_64d[2] = 0; icvGetQuadsTransform( imageSize, camMatr1_64d, rotMatr1_64d, transVect1_64d, camMatr2_64d, rotMatr2_64d, transVect2_64d, warpSize, quad1, quad2, fundMatr_64d, &epipole1_64d, &epipole2_64d ); /* Convert epipoles */ epipole1->x = (float)(epipole1_64d.x); epipole1->y = (float)(epipole1_64d.y); epipole1->z = (float)(epipole1_64d.z); epipole2->x = (float)(epipole2_64d.x); epipole2->y = (float)(epipole2_64d.y); epipole2->z = (float)(epipole2_64d.z); /* Convert fundamental matrix */ icvCvt_64d_32f(fundMatr_64d,fundMatr,9); return; } /*---------------------------------------------------------------------------------------*/ void icvGetQuadsTransformStruct( CvStereoCamera* stereoCamera) { /* Wrapper for icvGetQuadsTransformNew */ double quad1[4][2]; double quad2[4][2]; icvGetQuadsTransformNew( cvSize(cvRound(stereoCamera->camera[0]->imgSize[0]),cvRound(stereoCamera->camera[0]->imgSize[1])), stereoCamera->camera[0]->matrix, stereoCamera->camera[1]->matrix, stereoCamera->rotMatrix, stereoCamera->transVector, &(stereoCamera->warpSize), quad1, quad2, stereoCamera->fundMatr, &(stereoCamera->epipole[0]), &(stereoCamera->epipole[1]) ); int i; for( i = 0; i < 4; i++ ) { stereoCamera->quad[0][i] = cvPoint2D32f(quad1[i][0],quad1[i][1]); stereoCamera->quad[1][i] = cvPoint2D32f(quad2[i][0],quad2[i][1]); } return; } /*---------------------------------------------------------------------------------------*/ void icvComputeStereoParamsForCameras(CvStereoCamera* stereoCamera) { /* For given intrinsic and extrinsic parameters computes rest parameters ** such as fundamental matrix. warping coeffs, epipoles, ... */ /* compute rotate matrix and translate vector */ double rotMatr1[9]; double rotMatr2[9]; double transVect1[3]; double transVect2[3]; double convRotMatr[9]; double convTransVect[3]; /* fill matrices */ icvCvt_32f_64d(stereoCamera->camera[0]->rotMatr,rotMatr1,9); icvCvt_32f_64d(stereoCamera->camera[1]->rotMatr,rotMatr2,9); icvCvt_32f_64d(stereoCamera->camera[0]->transVect,transVect1,3); icvCvt_32f_64d(stereoCamera->camera[1]->transVect,transVect2,3); icvCreateConvertMatrVect( rotMatr1, transVect1, rotMatr2, transVect2, convRotMatr, convTransVect); /* copy to stereo camera params */ icvCvt_64d_32f(convRotMatr,stereoCamera->rotMatrix,9); icvCvt_64d_32f(convTransVect,stereoCamera->transVector,3); icvGetQuadsTransformStruct(stereoCamera); icvComputeRestStereoParams(stereoCamera); } /*---------------------------------------------------------------------------------------*/ /* Get cut line for one image */ void icvGetCutPiece( CvVect64d areaLineCoef1,CvVect64d areaLineCoef2, CvPoint2D64d epipole, CvSize imageSize, CvPoint2D64d* point11,CvPoint2D64d* point12, CvPoint2D64d* point21,CvPoint2D64d* point22, int* result) { /* Compute nearest cut line to epipole */ /* Get corners inside sector */ /* Collect all candidate point */ CvPoint2D64d candPoints[8]; CvPoint2D64d midPoint; int numPoints = 0; int res; int i; double cutLine1[3]; double cutLine2[3]; /* Find middle line of sector */ double midLine[3]; /* Different way */ CvPoint2D64d pointOnLine1; pointOnLine1.x = pointOnLine1.y = 0; CvPoint2D64d pointOnLine2; pointOnLine2.x = pointOnLine2.y = 0; CvPoint2D64d start1,end1; icvGetCrossRectDirect( imageSize, areaLineCoef1[0],areaLineCoef1[1],areaLineCoef1[2], &start1,&end1,&res); if( res > 0 ) { pointOnLine1 = start1; } icvGetCrossRectDirect( imageSize, areaLineCoef2[0],areaLineCoef2[1],areaLineCoef2[2], &start1,&end1,&res); if( res > 0 ) { pointOnLine2 = start1; } icvGetMiddleAnglePoint(epipole,pointOnLine1,pointOnLine2,&midPoint); icvGetCoefForPiece(epipole,midPoint,&midLine[0],&midLine[1],&midLine[2],&res); /* Test corner points */ CvPoint2D64d cornerPoint; CvPoint2D64d tmpPoints[2]; cornerPoint.x = 0; cornerPoint.y = 0; icvTestPoint( cornerPoint, areaLineCoef1, areaLineCoef2, epipole, &res); if( res == 1 ) {/* Add point */ candPoints[numPoints] = cornerPoint; numPoints++; } cornerPoint.x = imageSize.width; cornerPoint.y = 0; icvTestPoint( cornerPoint, areaLineCoef1, areaLineCoef2, epipole, &res); if( res == 1 ) {/* Add point */ candPoints[numPoints] = cornerPoint; numPoints++; } cornerPoint.x = imageSize.width; cornerPoint.y = imageSize.height; icvTestPoint( cornerPoint, areaLineCoef1, areaLineCoef2, epipole, &res); if( res == 1 ) {/* Add point */ candPoints[numPoints] = cornerPoint; numPoints++; } cornerPoint.x = 0; cornerPoint.y = imageSize.height; icvTestPoint( cornerPoint, areaLineCoef1, areaLineCoef2, epipole, &res); if( res == 1 ) {/* Add point */ candPoints[numPoints] = cornerPoint; numPoints++; } /* Find cross line 1 with image border */ icvGetCrossRectDirect( imageSize, areaLineCoef1[0],areaLineCoef1[1],areaLineCoef1[2], &tmpPoints[0], &tmpPoints[1], &res); for( i = 0; i < res; i++ ) { candPoints[numPoints++] = tmpPoints[i]; } /* Find cross line 2 with image border */ icvGetCrossRectDirect( imageSize, areaLineCoef2[0],areaLineCoef2[1],areaLineCoef2[2], &tmpPoints[0], &tmpPoints[1], &res); for( i = 0; i < res; i++ ) { candPoints[numPoints++] = tmpPoints[i]; } if( numPoints < 2 ) { *result = 0; return;/* Error. Not enought points */ } /* Project all points to middle line and get max and min */ CvPoint2D64d projPoint; CvPoint2D64d minPoint; minPoint.x = minPoint.y = FLT_MAX; CvPoint2D64d maxPoint; maxPoint.x = maxPoint.y = -FLT_MAX; double dist; double maxDist = 0; double minDist = 10000000; for( i = 0; i < numPoints; i++ ) { icvProjectPointToDirect(candPoints[i], midLine, &projPoint); icvGetPieceLength(epipole,projPoint,&dist); if( dist < minDist) { minDist = dist; minPoint = projPoint; } if( dist > maxDist) { maxDist = dist; maxPoint = projPoint; } } /* We know maximum and minimum points. Now we can compute cut lines */ icvGetNormalDirect(midLine,minPoint,cutLine1); icvGetNormalDirect(midLine,maxPoint,cutLine2); /* Test for begin of line. */ CvPoint2D64d tmpPoint2; /* Get cross with */ icvGetCrossDirectDirect(areaLineCoef1,cutLine1,point11,&res); icvGetCrossDirectDirect(areaLineCoef2,cutLine1,point12,&res); icvGetCrossDirectDirect(areaLineCoef1,cutLine2,point21,&res); icvGetCrossDirectDirect(areaLineCoef2,cutLine2,point22,&res); if( epipole.x > imageSize.width * 0.5 ) {/* Need to change points */ tmpPoint2 = *point11; *point11 = *point21; *point21 = tmpPoint2; tmpPoint2 = *point12; *point12 = *point22; *point22 = tmpPoint2; } return; } /*---------------------------------------------------------------------------------------*/ /* Get middle angle */ void icvGetMiddleAnglePoint( CvPoint2D64d basePoint, CvPoint2D64d point1,CvPoint2D64d point2, CvPoint2D64d* midPoint) {/* !!! May be need to return error */ double dist1; double dist2; icvGetPieceLength(basePoint,point1,&dist1); icvGetPieceLength(basePoint,point2,&dist2); CvPoint2D64d pointNew1; CvPoint2D64d pointNew2; double alpha = dist2/dist1; pointNew1.x = basePoint.x + (1.0/alpha) * ( point2.x - basePoint.x ); pointNew1.y = basePoint.y + (1.0/alpha) * ( point2.y - basePoint.y ); pointNew2.x = basePoint.x + alpha * ( point1.x - basePoint.x ); pointNew2.y = basePoint.y + alpha * ( point1.y - basePoint.y ); int res; icvGetCrossPiecePiece(point1,point2,pointNew1,pointNew2,midPoint,&res); return; } /*---------------------------------------------------------------------------------------*/ /* Get normal direct to direct in line */ void icvGetNormalDirect(CvVect64d direct,CvPoint2D64d point,CvVect64d normDirect) { normDirect[0] = direct[1]; normDirect[1] = - direct[0]; normDirect[2] = -(normDirect[0]*point.x + normDirect[1]*point.y); return; } /*---------------------------------------------------------------------------------------*/ CV_IMPL double icvGetVect(CvPoint2D64d basePoint,CvPoint2D64d point1,CvPoint2D64d point2) { return (point1.x - basePoint.x)*(point2.y - basePoint.y) - (point2.x - basePoint.x)*(point1.y - basePoint.y); } /*---------------------------------------------------------------------------------------*/ /* Test for point in sector */ /* Return 0 - point not inside sector */ /* Return 1 - point inside sector */ void icvTestPoint( CvPoint2D64d testPoint, CvVect64d line1,CvVect64d line2, CvPoint2D64d basePoint, int* result) { CvPoint2D64d point1,point2; icvProjectPointToDirect(testPoint,line1,&point1); icvProjectPointToDirect(testPoint,line2,&point2); double sign1 = icvGetVect(basePoint,point1,point2); double sign2 = icvGetVect(basePoint,point1,testPoint); if( sign1 * sign2 > 0 ) {/* Correct for first line */ sign1 = - sign1; sign2 = icvGetVect(basePoint,point2,testPoint); if( sign1 * sign2 > 0 ) {/* Correct for both lines */ *result = 1; } else { *result = 0; } } else { *result = 0; } return; } /*---------------------------------------------------------------------------------------*/ /* Project point to line */ void icvProjectPointToDirect( CvPoint2D64d point,CvVect64d lineCoeff, CvPoint2D64d* projectPoint) { double a = lineCoeff[0]; double b = lineCoeff[1]; double det = 1.0 / ( a*a + b*b ); double delta = a*point.y - b*point.x; projectPoint->x = ( -a*lineCoeff[2] - b * delta ) * det; projectPoint->y = ( -b*lineCoeff[2] + a * delta ) * det ; return; } /*---------------------------------------------------------------------------------------*/ /* Get distance from point to direction */ void icvGetDistanceFromPointToDirect( CvPoint2D64d point,CvVect64d lineCoef,double*dist) { CvPoint2D64d tmpPoint; icvProjectPointToDirect(point,lineCoef,&tmpPoint); double dx = point.x - tmpPoint.x; double dy = point.y - tmpPoint.y; *dist = sqrt(dx*dx+dy*dy); return; } /*---------------------------------------------------------------------------------------*/ CV_IMPL IplImage* icvCreateIsometricImage( IplImage* src, IplImage* dst, int desired_depth, int desired_num_channels ) { CvSize src_size ; src_size.width = src->width; src_size.height = src->height; CvSize dst_size = src_size; if( dst ) { dst_size.width = dst->width; dst_size.height = dst->height; } if( !dst || dst->depth != desired_depth || dst->nChannels != desired_num_channels || dst_size.width != src_size.width || dst_size.height != dst_size.height ) { cvReleaseImage( &dst ); dst = cvCreateImage( src_size, desired_depth, desired_num_channels ); CvRect rect = cvRect(0,0,src_size.width,src_size.height); cvSetImageROI( dst, rect ); } return dst; } int icvCvt_32f_64d( float *src, double *dst, int size ) { int t; if( !src || !dst ) return CV_NULLPTR_ERR; if( size <= 0 ) return CV_BADRANGE_ERR; for( t = 0; t < size; t++ ) { dst[t] = (double) (src[t]); } return CV_OK; } /*======================================================================================*/ /* Type conversion double -> float */ int icvCvt_64d_32f( double *src, float *dst, int size ) { int t; if( !src || !dst ) return CV_NULLPTR_ERR; if( size <= 0 ) return CV_BADRANGE_ERR; for( t = 0; t < size; t++ ) { dst[t] = (float) (src[t]); } return CV_OK; } /*----------------------------------------------------------------------------------*/ /* Find line which cross frame by line(a,b,c) */ void FindLineForEpiline( CvSize imageSize, float a,float b,float c, CvPoint2D32f *start,CvPoint2D32f *end, int* result) { result = result; CvPoint2D32f frameBeg; CvPoint2D32f frameEnd; CvPoint2D32f cross[4]; int haveCross[4]; float dist; haveCross[0] = 0; haveCross[1] = 0; haveCross[2] = 0; haveCross[3] = 0; frameBeg.x = 0; frameBeg.y = 0; frameEnd.x = (float)(imageSize.width); frameEnd.y = 0; haveCross[0] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[0]); frameBeg.x = (float)(imageSize.width); frameBeg.y = 0; frameEnd.x = (float)(imageSize.width); frameEnd.y = (float)(imageSize.height); haveCross[1] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[1]); frameBeg.x = (float)(imageSize.width); frameBeg.y = (float)(imageSize.height); frameEnd.x = 0; frameEnd.y = (float)(imageSize.height); haveCross[2] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[2]); frameBeg.x = 0; frameBeg.y = (float)(imageSize.height); frameEnd.x = 0; frameEnd.y = 0; haveCross[3] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[3]); int n; float minDist = (float)(INT_MAX); float maxDist = (float)(INT_MIN); int maxN = -1; int minN = -1; double midPointX = imageSize.width / 2.0; double midPointY = imageSize.height / 2.0; for( n = 0; n < 4; n++ ) { if( haveCross[n] > 0 ) { dist = (float)((midPointX - cross[n].x)*(midPointX - cross[n].x) + (midPointY - cross[n].y)*(midPointY - cross[n].y)); if( dist < minDist ) { minDist = dist; minN = n; } if( dist > maxDist ) { maxDist = dist; maxN = n; } } } if( minN >= 0 && maxN >= 0 && (minN != maxN) ) { *start = cross[minN]; *end = cross[maxN]; } else { start->x = 0; start->y = 0; end->x = 0; end->y = 0; } return; } /*----------------------------------------------------------------------------------*/ int GetAngleLinee( CvPoint2D32f epipole, CvSize imageSize,CvPoint2D32f point1,CvPoint2D32f point2) { float width = (float)(imageSize.width); float height = (float)(imageSize.height); /* Get crosslines with image corners */ /* Find four lines */ CvPoint2D32f pa,pb,pc,pd; pa.x = 0; pa.y = 0; pb.x = width; pb.y = 0; pd.x = width; pd.y = height; pc.x = 0; pc.y = height; /* We can compute points for angle */ /* Test for place section */ float x,y; x = epipole.x; y = epipole.y; if( x < 0 ) {/* 1,4,7 */ if( y < 0) {/* 1 */ point1 = pb; point2 = pc; } else if( y > height ) {/* 7 */ point1 = pa; point2 = pd; } else {/* 4 */ point1 = pa; point2 = pc; } } else if ( x > width ) {/* 3,6,9 */ if( y < 0 ) {/* 3 */ point1 = pa; point2 = pd; } else if ( y > height ) {/* 9 */ point1 = pc; point2 = pb; } else {/* 6 */ point1 = pb; point2 = pd; } } else {/* 2,5,8 */ if( y < 0 ) {/* 2 */ point1 = pa; point2 = pb; } else if( y > height ) {/* 8 */ point1 = pc; point2 = pd; } else {/* 5 - point in the image */ return 2; } } return 0; } /*--------------------------------------------------------------------------------------*/ void icvComputePerspectiveCoeffs(const CvPoint2D32f srcQuad[4],const CvPoint2D32f dstQuad[4],double coeffs[3][3]) {/* Computes perspective coeffs for transformation from src to dst quad */ CV_FUNCNAME( "icvComputePerspectiveCoeffs" ); __BEGIN__; double A[64]; double b[8]; double c[8]; CvPoint2D32f pt[4]; int i; pt[0] = srcQuad[0]; pt[1] = srcQuad[1]; pt[2] = srcQuad[2]; pt[3] = srcQuad[3]; for( i = 0; i < 4; i++ ) { #if 0 double x = dstQuad[i].x; double y = dstQuad[i].y; double X = pt[i].x; double Y = pt[i].y; #else double x = pt[i].x; double y = pt[i].y; double X = dstQuad[i].x; double Y = dstQuad[i].y; #endif double* a = A + i*16; a[0] = x; a[1] = y; a[2] = 1; a[3] = 0; a[4] = 0; a[5] = 0; a[6] = -X*x; a[7] = -X*y; a += 8; a[0] = 0; a[1] = 0; a[2] = 0; a[3] = x; a[4] = y; a[5] = 1; a[6] = -Y*x; a[7] = -Y*y; b[i*2] = X; b[i*2 + 1] = Y; } { double invA[64]; CvMat matA = cvMat( 8, 8, CV_64F, A ); CvMat matInvA = cvMat( 8, 8, CV_64F, invA ); CvMat matB = cvMat( 8, 1, CV_64F, b ); CvMat matX = cvMat( 8, 1, CV_64F, c ); CV_CALL( cvPseudoInverse( &matA, &matInvA )); CV_CALL( cvMatMulAdd( &matInvA, &matB, 0, &matX )); } coeffs[0][0] = c[0]; coeffs[0][1] = c[1]; coeffs[0][2] = c[2]; coeffs[1][0] = c[3]; coeffs[1][1] = c[4]; coeffs[1][2] = c[5]; coeffs[2][0] = c[6]; coeffs[2][1] = c[7]; coeffs[2][2] = 1.0; __END__; return; } /*--------------------------------------------------------------------------------------*/ CV_IMPL void cvComputePerspectiveMap(const double c[3][3], CvArr* rectMapX, CvArr* rectMapY ) { CV_FUNCNAME( "cvComputePerspectiveMap" ); __BEGIN__; CvSize size; CvMat stubx, *mapx = (CvMat*)rectMapX; CvMat stuby, *mapy = (CvMat*)rectMapY; int i, j; CV_CALL( mapx = cvGetMat( mapx, &stubx )); CV_CALL( mapy = cvGetMat( mapy, &stuby )); if( CV_MAT_TYPE( mapx->type ) != CV_32FC1 || CV_MAT_TYPE( mapy->type ) != CV_32FC1 ) CV_ERROR( CV_StsUnsupportedFormat, "" ); size = cvGetMatSize(mapx); assert( fabs(c[2][2] - 1.) < FLT_EPSILON ); for( i = 0; i < size.height; i++ ) { float* mx = (float*)(mapx->data.ptr + mapx->step*i); float* my = (float*)(mapy->data.ptr + mapy->step*i); for( j = 0; j < size.width; j++ ) { double w = 1./(c[2][0]*j + c[2][1]*i + 1.); double x = (c[0][0]*j + c[0][1]*i + c[0][2])*w; double y = (c[1][0]*j + c[1][1]*i + c[1][2])*w; mx[j] = (float)x; my[j] = (float)y; } } __END__; } /*--------------------------------------------------------------------------------------*/ CV_IMPL void cvInitPerspectiveTransform( CvSize size, const CvPoint2D32f quad[4], double matrix[3][3], CvArr* rectMap ) { /* Computes Perspective Transform coeffs and map if need for given image size and given result quad */ CV_FUNCNAME( "cvInitPerspectiveTransform" ); __BEGIN__; double A[64]; double b[8]; double c[8]; CvPoint2D32f pt[4]; CvMat mapstub, *map = (CvMat*)rectMap; int i, j; if( map ) { CV_CALL( map = cvGetMat( map, &mapstub )); if( CV_MAT_TYPE( map->type ) != CV_32FC2 ) CV_ERROR( CV_StsUnsupportedFormat, "" ); if( map->width != size.width || map->height != size.height ) CV_ERROR( CV_StsUnmatchedSizes, "" ); } pt[0] = cvPoint2D32f( 0, 0 ); pt[1] = cvPoint2D32f( size.width, 0 ); pt[2] = cvPoint2D32f( size.width, size.height ); pt[3] = cvPoint2D32f( 0, size.height ); for( i = 0; i < 4; i++ ) { #if 0 double x = quad[i].x; double y = quad[i].y; double X = pt[i].x; double Y = pt[i].y; #else double x = pt[i].x; double y = pt[i].y; double X = quad[i].x; double Y = quad[i].y; #endif double* a = A + i*16; a[0] = x; a[1] = y; a[2] = 1; a[3] = 0; a[4] = 0; a[5] = 0; a[6] = -X*x; a[7] = -X*y; a += 8; a[0] = 0; a[1] = 0; a[2] = 0; a[3] = x; a[4] = y; a[5] = 1; a[6] = -Y*x; a[7] = -Y*y; b[i*2] = X; b[i*2 + 1] = Y; } { double invA[64]; CvMat matA = cvMat( 8, 8, CV_64F, A ); CvMat matInvA = cvMat( 8, 8, CV_64F, invA ); CvMat matB = cvMat( 8, 1, CV_64F, b ); CvMat matX = cvMat( 8, 1, CV_64F, c ); CV_CALL( cvPseudoInverse( &matA, &matInvA )); CV_CALL( cvMatMulAdd( &matInvA, &matB, 0, &matX )); } matrix[0][0] = c[0]; matrix[0][1] = c[1]; matrix[0][2] = c[2]; matrix[1][0] = c[3]; matrix[1][1] = c[4]; matrix[1][2] = c[5]; matrix[2][0] = c[6]; matrix[2][1] = c[7]; matrix[2][2] = 1.0; if( map ) { for( i = 0; i < size.height; i++ ) { CvPoint2D32f* maprow = (CvPoint2D32f*)(map->data.ptr + map->step*i); for( j = 0; j < size.width; j++ ) { double w = 1./(c[6]*j + c[7]*i + 1.); double x = (c[0]*j + c[1]*i + c[2])*w; double y = (c[3]*j + c[4]*i + c[5])*w; maprow[j].x = (float)x; maprow[j].y = (float)y; } } } __END__; return; } /*-----------------------------------------------------------------------*/ /* Compute projected infinite point for second image if first image point is known */ void icvComputeeInfiniteProject1( CvMatr64d rotMatr, CvMatr64d camMatr1, CvMatr64d camMatr2, CvPoint2D32f point1, CvPoint2D32f* point2) { double invMatr1[9]; icvInvertMatrix_64d(camMatr1,3,invMatr1); double P1[3]; double p1[3]; p1[0] = (double)(point1.x); p1[1] = (double)(point1.y); p1[2] = 1; icvMulMatrix_64d( invMatr1, 3,3, p1, 1,3, P1); double invR[9]; icvTransposeMatrix_64d( rotMatr, 3, 3, invR ); /* Change system 1 to system 2 */ double P2[3]; icvMulMatrix_64d( invR, 3,3, P1, 1,3, P2); /* Now we can project this point to image 2 */ double projP[3]; icvMulMatrix_64d( camMatr2, 3,3, P2, 1,3, projP); point2->x = (float)(projP[0] / projP[2]); point2->y = (float)(projP[1] / projP[2]); return; } /*-----------------------------------------------------------------------*/ /* Compute projected infinite point for second image if first image point is known */ void icvComputeeInfiniteProject2( CvMatr64d rotMatr, CvMatr64d camMatr1, CvMatr64d camMatr2, CvPoint2D32f* point1, CvPoint2D32f point2) { double invMatr2[9]; icvInvertMatrix_64d(camMatr2,3,invMatr2); double P2[3]; double p2[3]; p2[0] = (double)(point2.x); p2[1] = (double)(point2.y); p2[2] = 1; icvMulMatrix_64d( invMatr2, 3,3, p2, 1,3, P2); /* Change system 1 to system 2 */ double P1[3]; icvMulMatrix_64d( rotMatr, 3,3, P2, 1,3, P1); /* Now we can project this point to image 2 */ double projP[3]; icvMulMatrix_64d( camMatr1, 3,3, P1, 1,3, projP); point1->x = (float)(projP[0] / projP[2]); point1->y = (float)(projP[1] / projP[2]); return; } /* Select best R and t for given cameras, points, ... */ /* For both cameras */ int icvSelectBestRt( int numImages, int* numPoints, CvPoint2D32f* imagePoints1, CvPoint2D32f* imagePoints2, CvPoint3D32f* objectPoints, CvMatr32f cameraMatrix1, CvVect32f distortion1, CvMatr32f rotMatrs1, CvVect32f transVects1, CvMatr32f cameraMatrix2, CvVect32f distortion2, CvMatr32f rotMatrs2, CvVect32f transVects2, CvMatr32f bestRotMatr, CvVect32f bestTransVect ) { /* Need to convert input data 32 -> 64 */ CvPoint3D64d* objectPoints_64d; double* rotMatrs1_64d; double* rotMatrs2_64d; double* transVects1_64d; double* transVects2_64d; double cameraMatrix1_64d[9]; double cameraMatrix2_64d[9]; double distortion1_64d[4]; double distortion2_64d[4]; /* allocate memory for 64d data */ int totalNum = 0; int i; for( i = 0; i < numImages; i++ ) { totalNum += numPoints[i]; } objectPoints_64d = (CvPoint3D64d*)calloc(totalNum,sizeof(CvPoint3D64d)); rotMatrs1_64d = (double*)calloc(numImages,sizeof(double)*9); rotMatrs2_64d = (double*)calloc(numImages,sizeof(double)*9); transVects1_64d = (double*)calloc(numImages,sizeof(double)*3); transVects2_64d = (double*)calloc(numImages,sizeof(double)*3); /* Convert input data to 64d */ icvCvt_32f_64d((float*)objectPoints, (double*)objectPoints_64d, totalNum*3); icvCvt_32f_64d(rotMatrs1, rotMatrs1_64d, numImages*9); icvCvt_32f_64d(rotMatrs2, rotMatrs2_64d, numImages*9); icvCvt_32f_64d(transVects1, transVects1_64d, numImages*3); icvCvt_32f_64d(transVects2, transVects2_64d, numImages*3); /* Convert to arrays */ icvCvt_32f_64d(cameraMatrix1, cameraMatrix1_64d, 9); icvCvt_32f_64d(cameraMatrix2, cameraMatrix2_64d, 9); icvCvt_32f_64d(distortion1, distortion1_64d, 4); icvCvt_32f_64d(distortion2, distortion2_64d, 4); /* for each R and t compute error for image pair */ float* errors; errors = (float*)calloc(numImages*numImages,sizeof(float)); if( errors == 0 ) { return CV_OUTOFMEM_ERR; } int currImagePair; int currRt; for( currRt = 0; currRt < numImages; currRt++ ) { int begPoint = 0; for(currImagePair = 0; currImagePair < numImages; currImagePair++ ) { /* For current R,t R,t compute relative position of cameras */ double convRotMatr[9]; double convTransVect[3]; icvCreateConvertMatrVect( rotMatrs1_64d + currRt*9, transVects1_64d + currRt*3, rotMatrs2_64d + currRt*9, transVects2_64d + currRt*3, convRotMatr, convTransVect); /* Project points using relative position of cameras */ double convRotMatr2[9]; double convTransVect2[3]; convRotMatr2[0] = 1; convRotMatr2[1] = 0; convRotMatr2[2] = 0; convRotMatr2[3] = 0; convRotMatr2[4] = 1; convRotMatr2[5] = 0; convRotMatr2[6] = 0; convRotMatr2[7] = 0; convRotMatr2[8] = 1; convTransVect2[0] = 0; convTransVect2[1] = 0; convTransVect2[2] = 0; /* Compute error for given pair and Rt */ /* We must project points to image and compute error */ CvPoint2D64d* projImagePoints1; CvPoint2D64d* projImagePoints2; CvPoint3D64d* points1; CvPoint3D64d* points2; int numberPnt; numberPnt = numPoints[currImagePair]; projImagePoints1 = (CvPoint2D64d*)calloc(numberPnt,sizeof(CvPoint2D64d)); projImagePoints2 = (CvPoint2D64d*)calloc(numberPnt,sizeof(CvPoint2D64d)); points1 = (CvPoint3D64d*)calloc(numberPnt,sizeof(CvPoint3D64d)); points2 = (CvPoint3D64d*)calloc(numberPnt,sizeof(CvPoint3D64d)); /* Transform object points to first camera position */ int i; for( i = 0; i < numberPnt; i++ ) { /* Create second camera point */ CvPoint3D64d tmpPoint; tmpPoint.x = (double)(objectPoints[i].x); tmpPoint.y = (double)(objectPoints[i].y); tmpPoint.z = (double)(objectPoints[i].z); icvConvertPointSystem( tmpPoint, points2+i, rotMatrs2_64d + currImagePair*9, transVects2_64d + currImagePair*3); /* Create first camera point using R, t */ icvConvertPointSystem( points2[i], points1+i, convRotMatr, convTransVect); CvPoint3D64d tmpPoint2 = { 0, 0, 0 }; icvConvertPointSystem( tmpPoint, &tmpPoint2, rotMatrs1_64d + currImagePair*9, transVects1_64d + currImagePair*3); double err; double dx,dy,dz; dx = tmpPoint2.x - points1[i].x; dy = tmpPoint2.y - points1[i].y; dz = tmpPoint2.z - points1[i].z; err = sqrt(dx*dx + dy*dy + dz*dz); } #if 0 cvProjectPointsSimple( numPoints[currImagePair], objectPoints_64d + begPoint, rotMatrs1_64d + currRt*9, transVects1_64d + currRt*3, cameraMatrix1_64d, distortion1_64d, projImagePoints1); cvProjectPointsSimple( numPoints[currImagePair], objectPoints_64d + begPoint, rotMatrs2_64d + currRt*9, transVects2_64d + currRt*3, cameraMatrix2_64d, distortion2_64d, projImagePoints2); #endif /* Project with no translate and no rotation */ #if 0 { double nodist[4] = {0,0,0,0}; cvProjectPointsSimple( numPoints[currImagePair], points1, convRotMatr2, convTransVect2, cameraMatrix1_64d, nodist, projImagePoints1); cvProjectPointsSimple( numPoints[currImagePair], points2, convRotMatr2, convTransVect2, cameraMatrix2_64d, nodist, projImagePoints2); } #endif cvProjectPointsSimple( numPoints[currImagePair], points1, convRotMatr2, convTransVect2, cameraMatrix1_64d, distortion1_64d, projImagePoints1); cvProjectPointsSimple( numPoints[currImagePair], points2, convRotMatr2, convTransVect2, cameraMatrix2_64d, distortion2_64d, projImagePoints2); /* points are projected. Compute error */ int currPoint; double err1 = 0; double err2 = 0; double err; for( currPoint = 0; currPoint < numberPnt; currPoint++ ) { double len1,len2; double dx1,dy1; dx1 = imagePoints1[begPoint+currPoint].x - projImagePoints1[currPoint].x; dy1 = imagePoints1[begPoint+currPoint].y - projImagePoints1[currPoint].y; len1 = sqrt(dx1*dx1 + dy1*dy1); err1 += len1; double dx2,dy2; dx2 = imagePoints2[begPoint+currPoint].x - projImagePoints2[currPoint].x; dy2 = imagePoints2[begPoint+currPoint].y - projImagePoints2[currPoint].y; len2 = sqrt(dx2*dx2 + dy2*dy2); err2 += len2; } err1 /= (float)(numberPnt); err2 /= (float)(numberPnt); err = (err1+err2) * 0.5; begPoint += numberPnt; /* Set this error to */ errors[numImages*currImagePair+currRt] = (float)err; free(points1); free(points2); free(projImagePoints1); free(projImagePoints2); } } /* Just select R and t with minimal average error */ int bestnumRt = 0; float minError = 0;/* Just for no warnings. Uses 'first' flag. */ int first = 1; for( currRt = 0; currRt < numImages; currRt++ ) { float avErr = 0; for(currImagePair = 0; currImagePair < numImages; currImagePair++ ) { avErr += errors[numImages*currImagePair+currRt]; } avErr /= (float)(numImages); if( first ) { bestnumRt = 0; minError = avErr; first = 0; } else { if( avErr < minError ) { bestnumRt = currRt; minError = avErr; } } } double bestRotMatr_64d[9]; double bestTransVect_64d[3]; icvCreateConvertMatrVect( rotMatrs1_64d + bestnumRt * 9, transVects1_64d + bestnumRt * 3, rotMatrs2_64d + bestnumRt * 9, transVects2_64d + bestnumRt * 3, bestRotMatr_64d, bestTransVect_64d); icvCvt_64d_32f(bestRotMatr_64d,bestRotMatr,9); icvCvt_64d_32f(bestTransVect_64d,bestTransVect,3); free(errors); return CV_OK; } /* ----------------- Stereo calibration functions --------------------- */ float icvDefinePointPosition(CvPoint2D32f point1,CvPoint2D32f point2,CvPoint2D32f point) { float ax = point2.x - point1.x; float ay = point2.y - point1.y; float bx = point.x - point1.x; float by = point.y - point1.y; return (ax*by - ay*bx); } /* Convert function for stereo warping */ int icvConvertWarpCoordinates(double coeffs[3][3], CvPoint2D32f* cameraPoint, CvPoint2D32f* warpPoint, int direction) { double x,y; double det; if( direction == CV_WARP_TO_CAMERA ) {/* convert from camera image to warped image coordinates */ x = warpPoint->x; y = warpPoint->y; det = (coeffs[2][0] * x + coeffs[2][1] * y + coeffs[2][2]); if( fabs(det) > 1e-8 ) { cameraPoint->x = (float)((coeffs[0][0] * x + coeffs[0][1] * y + coeffs[0][2]) / det); cameraPoint->y = (float)((coeffs[1][0] * x + coeffs[1][1] * y + coeffs[1][2]) / det); return CV_OK; } } else if( direction == CV_CAMERA_TO_WARP ) {/* convert from warped image to camera image coordinates */ x = cameraPoint->x; y = cameraPoint->y; 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]); if( fabs(det) > 1e-8 ) { 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); 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); return CV_OK; } } return CV_BADFACTOR_ERR; } /* Compute stereo params using some camera params */ /* by Valery Mosyagin. int ComputeRestStereoParams(StereoParams *stereoparams) */ int icvComputeRestStereoParams(CvStereoCamera *stereoparams) { icvGetQuadsTransformStruct(stereoparams); cvInitPerspectiveTransform( stereoparams->warpSize, stereoparams->quad[0], stereoparams->coeffs[0], 0); cvInitPerspectiveTransform( stereoparams->warpSize, stereoparams->quad[1], stereoparams->coeffs[1], 0); /* Create border for warped images */ CvPoint2D32f corns[4]; corns[0].x = 0; corns[0].y = 0; corns[1].x = (float)(stereoparams->camera[0]->imgSize[0]-1); corns[1].y = 0; corns[2].x = (float)(stereoparams->camera[0]->imgSize[0]-1); corns[2].y = (float)(stereoparams->camera[0]->imgSize[1]-1); corns[3].x = 0; corns[3].y = (float)(stereoparams->camera[0]->imgSize[1]-1); int i; for( i = 0; i < 4; i++ ) { /* For first camera */ icvConvertWarpCoordinates( stereoparams->coeffs[0], corns+i, stereoparams->border[0]+i, CV_CAMERA_TO_WARP); /* For second camera */ icvConvertWarpCoordinates( stereoparams->coeffs[1], corns+i, stereoparams->border[1]+i, CV_CAMERA_TO_WARP); } /* Test compute */ { CvPoint2D32f warpPoints[4]; warpPoints[0] = cvPoint2D32f(0,0); warpPoints[1] = cvPoint2D32f(stereoparams->warpSize.width-1,0); warpPoints[2] = cvPoint2D32f(stereoparams->warpSize.width-1,stereoparams->warpSize.height-1); warpPoints[3] = cvPoint2D32f(0,stereoparams->warpSize.height-1); CvPoint2D32f camPoints1[4]; CvPoint2D32f camPoints2[4]; for( int i = 0; i < 4; i++ ) { icvConvertWarpCoordinates(stereoparams->coeffs[0], camPoints1+i, warpPoints+i, CV_WARP_TO_CAMERA); icvConvertWarpCoordinates(stereoparams->coeffs[1], camPoints2+i, warpPoints+i, CV_WARP_TO_CAMERA); } } /* Allocate memory for scanlines coeffs */ stereoparams->lineCoeffs = (CvStereoLineCoeff*)calloc(stereoparams->warpSize.height,sizeof(CvStereoLineCoeff)); /* Compute coeffs for epilines */ icvComputeCoeffForStereo( stereoparams); /* all coeffs are known */ return CV_OK; } /*-------------------------------------------------------------------------------------------*/ int icvStereoCalibration( int numImages, int* nums, CvSize imageSize, CvPoint2D32f* imagePoints1, CvPoint2D32f* imagePoints2, CvPoint3D32f* objectPoints, CvStereoCamera* stereoparams ) { /* Firstly we must calibrate both cameras */ /* Alocate memory for data */ /* Allocate for translate vectors */ float* transVects1; float* transVects2; float* rotMatrs1; float* rotMatrs2; transVects1 = (float*)calloc(numImages,sizeof(float)*3); transVects2 = (float*)calloc(numImages,sizeof(float)*3); rotMatrs1 = (float*)calloc(numImages,sizeof(float)*9); rotMatrs2 = (float*)calloc(numImages,sizeof(float)*9); /* Calibrate first camera */ cvCalibrateCamera( numImages, nums, imageSize, imagePoints1, objectPoints, stereoparams->camera[0]->distortion, stereoparams->camera[0]->matrix, transVects1, rotMatrs1, 1); /* Calibrate second camera */ cvCalibrateCamera( numImages, nums, imageSize, imagePoints2, objectPoints, stereoparams->camera[1]->distortion, stereoparams->camera[1]->matrix, transVects2, rotMatrs2, 1); /* Cameras are calibrated */ stereoparams->camera[0]->imgSize[0] = (float)imageSize.width; stereoparams->camera[0]->imgSize[1] = (float)imageSize.height; stereoparams->camera[1]->imgSize[0] = (float)imageSize.width; stereoparams->camera[1]->imgSize[1] = (float)imageSize.height; icvSelectBestRt( numImages, nums, imagePoints1, imagePoints2, objectPoints, stereoparams->camera[0]->matrix, stereoparams->camera[0]->distortion, rotMatrs1, transVects1, stereoparams->camera[1]->matrix, stereoparams->camera[1]->distortion, rotMatrs2, transVects2, stereoparams->rotMatrix, stereoparams->transVector ); /* Free memory */ free(transVects1); free(transVects2); free(rotMatrs1); free(rotMatrs2); icvComputeRestStereoParams(stereoparams); return CV_NO_ERR; } /* Find line from epipole */ void FindLine(CvPoint2D32f epipole,CvSize imageSize,CvPoint2D32f point,CvPoint2D32f *start,CvPoint2D32f *end) { CvPoint2D32f frameBeg; CvPoint2D32f frameEnd; CvPoint2D32f cross[4]; int haveCross[4]; float dist; haveCross[0] = 0; haveCross[1] = 0; haveCross[2] = 0; haveCross[3] = 0; frameBeg.x = 0; frameBeg.y = 0; frameEnd.x = (float)(imageSize.width); frameEnd.y = 0; haveCross[0] = icvGetCrossPieceVector(frameBeg,frameEnd,epipole,point,&cross[0]); frameBeg.x = (float)(imageSize.width); frameBeg.y = 0; frameEnd.x = (float)(imageSize.width); frameEnd.y = (float)(imageSize.height); haveCross[1] = icvGetCrossPieceVector(frameBeg,frameEnd,epipole,point,&cross[1]); frameBeg.x = (float)(imageSize.width); frameBeg.y = (float)(imageSize.height); frameEnd.x = 0; frameEnd.y = (float)(imageSize.height); haveCross[2] = icvGetCrossPieceVector(frameBeg,frameEnd,epipole,point,&cross[2]); frameBeg.x = 0; frameBeg.y = (float)(imageSize.height); frameEnd.x = 0; frameEnd.y = 0; haveCross[3] = icvGetCrossPieceVector(frameBeg,frameEnd,epipole,point,&cross[3]); int n; float minDist = (float)(INT_MAX); float maxDist = (float)(INT_MIN); int maxN = -1; int minN = -1; for( n = 0; n < 4; n++ ) { if( haveCross[n] > 0 ) { dist = (epipole.x - cross[n].x)*(epipole.x - cross[n].x) + (epipole.y - cross[n].y)*(epipole.y - cross[n].y); if( dist < minDist ) { minDist = dist; minN = n; } if( dist > maxDist ) { maxDist = dist; maxN = n; } } } if( minN >= 0 && maxN >= 0 && (minN != maxN) ) { *start = cross[minN]; *end = cross[maxN]; } else { start->x = 0; start->y = 0; end->x = 0; end->y = 0; } return; } /* Find line which cross frame by line(a,b,c) */ void FindLineForEpiline(CvSize imageSize,float a,float b,float c,CvPoint2D32f *start,CvPoint2D32f *end) { CvPoint2D32f frameBeg; CvPoint2D32f frameEnd; CvPoint2D32f cross[4]; int haveCross[4]; float dist; haveCross[0] = 0; haveCross[1] = 0; haveCross[2] = 0; haveCross[3] = 0; frameBeg.x = 0; frameBeg.y = 0; frameEnd.x = (float)(imageSize.width); frameEnd.y = 0; haveCross[0] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[0]); frameBeg.x = (float)(imageSize.width); frameBeg.y = 0; frameEnd.x = (float)(imageSize.width); frameEnd.y = (float)(imageSize.height); haveCross[1] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[1]); frameBeg.x = (float)(imageSize.width); frameBeg.y = (float)(imageSize.height); frameEnd.x = 0; frameEnd.y = (float)(imageSize.height); haveCross[2] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[2]); frameBeg.x = 0; frameBeg.y = (float)(imageSize.height); frameEnd.x = 0; frameEnd.y = 0; haveCross[3] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[3]); int n; float minDist = (float)(INT_MAX); float maxDist = (float)(INT_MIN); int maxN = -1; int minN = -1; double midPointX = imageSize.width / 2.0; double midPointY = imageSize.height / 2.0; for( n = 0; n < 4; n++ ) { if( haveCross[n] > 0 ) { dist = (float)((midPointX - cross[n].x)*(midPointX - cross[n].x) + (midPointY - cross[n].y)*(midPointY - cross[n].y)); if( dist < minDist ) { minDist = dist; minN = n; } if( dist > maxDist ) { maxDist = dist; maxN = n; } } } if( minN >= 0 && maxN >= 0 && (minN != maxN) ) { *start = cross[minN]; *end = cross[maxN]; } else { start->x = 0; start->y = 0; end->x = 0; end->y = 0; } return; } /* Cross lines */ int GetCrossLines(CvPoint2D32f p1_start,CvPoint2D32f p1_end,CvPoint2D32f p2_start,CvPoint2D32f p2_end,CvPoint2D32f *cross) { double ex1,ey1,ex2,ey2; double px1,py1,px2,py2; double del; double delA,delB,delX,delY; double alpha,betta; ex1 = p1_start.x; ey1 = p1_start.y; ex2 = p1_end.x; ey2 = p1_end.y; px1 = p2_start.x; py1 = p2_start.y; px2 = p2_end.x; py2 = p2_end.y; del = (ex1-ex2)*(py2-py1)+(ey2-ey1)*(px2-px1); if( del == 0) { return -1; } delA = (px1-ex1)*(py1-py2) + (ey1-py1)*(px1-px2); delB = (ex1-px1)*(ey1-ey2) + (py1-ey1)*(ex1-ex2); alpha = delA / del; betta = -delB / del; if( alpha < 0 || alpha > 1.0 || betta < 0 || betta > 1.0) { return -1; } delX = (ex1-ex2)*(py1*(px1-px2)-px1*(py1-py2))+ (px1-px2)*(ex1*(ey1-ey2)-ey1*(ex1-ex2)); delY = (ey1-ey2)*(px1*(py1-py2)-py1*(px1-px2))+ (py1-py2)*(ey1*(ex1-ex2)-ex1*(ey1-ey2)); cross->x = (float)( delX / del); cross->y = (float)(-delY / del); return 1; } int icvGetCrossPieceVector(CvPoint2D32f p1_start,CvPoint2D32f p1_end,CvPoint2D32f v2_start,CvPoint2D32f v2_end,CvPoint2D32f *cross) { double ex1,ey1,ex2,ey2; double px1,py1,px2,py2; double del; double delA,delB,delX,delY; double alpha,betta; ex1 = p1_start.x; ey1 = p1_start.y; ex2 = p1_end.x; ey2 = p1_end.y; px1 = v2_start.x; py1 = v2_start.y; px2 = v2_end.x; py2 = v2_end.y; del = (ex1-ex2)*(py2-py1)+(ey2-ey1)*(px2-px1); if( del == 0) { return -1; } delA = (px1-ex1)*(py1-py2) + (ey1-py1)*(px1-px2); delB = (ex1-px1)*(ey1-ey2) + (py1-ey1)*(ex1-ex2); alpha = delA / del; betta = -delB / del; if( alpha < 0 || alpha > 1.0 ) { return -1; } delX = (ex1-ex2)*(py1*(px1-px2)-px1*(py1-py2))+ (px1-px2)*(ex1*(ey1-ey2)-ey1*(ex1-ex2)); delY = (ey1-ey2)*(px1*(py1-py2)-py1*(px1-px2))+ (py1-py2)*(ey1*(ex1-ex2)-ex1*(ey1-ey2)); cross->x = (float)( delX / del); cross->y = (float)(-delY / del); return 1; } int icvGetCrossLineDirect(CvPoint2D32f p1,CvPoint2D32f p2,float a,float b,float c,CvPoint2D32f* cross) { double del; double delX,delY,delA; double px1,px2,py1,py2; double X,Y,alpha; px1 = p1.x; py1 = p1.y; px2 = p2.x; py2 = p2.y; del = a * (px2 - px1) + b * (py2-py1); if( del == 0 ) { return -1; } delA = - c - a*px1 - b*py1; alpha = delA / del; if( alpha < 0 || alpha > 1.0 ) { return -1;/* no cross */ } delX = b * (py1*(px1-px2) - px1*(py1-py2)) + c * (px1-px2); delY = a * (px1*(py1-py2) - py1*(px1-px2)) + c * (py1-py2); X = delX / del; Y = delY / del; cross->x = (float)X; cross->y = (float)Y; return 1; } int cvComputeEpipoles( CvMatr32f camMatr1, CvMatr32f camMatr2, CvMatr32f rotMatr1, CvMatr32f rotMatr2, CvVect32f transVect1,CvVect32f transVect2, CvVect32f epipole1, CvVect32f epipole2) { /* Copy matrix */ CvMat ccamMatr1 = cvMat(3,3,CV_MAT32F,camMatr1); CvMat ccamMatr2 = cvMat(3,3,CV_MAT32F,camMatr2); CvMat crotMatr1 = cvMat(3,3,CV_MAT32F,rotMatr1); CvMat crotMatr2 = cvMat(3,3,CV_MAT32F,rotMatr2); CvMat ctransVect1 = cvMat(3,1,CV_MAT32F,transVect1); CvMat ctransVect2 = cvMat(3,1,CV_MAT32F,transVect2); CvMat cepipole1 = cvMat(3,1,CV_MAT32F,epipole1); CvMat cepipole2 = cvMat(3,1,CV_MAT32F,epipole2); CvMat cmatrP1 = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&cmatrP1); CvMat cmatrP2 = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&cmatrP2); CvMat cvectp1 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&cvectp1); CvMat cvectp2 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&cvectp2); CvMat ctmpF1 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&ctmpF1); CvMat ctmpM1 = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&ctmpM1); CvMat ctmpM2 = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&ctmpM2); CvMat cinvP1 = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&cinvP1); CvMat cinvP2 = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&cinvP2); CvMat ctmpMatr = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&ctmpMatr); CvMat ctmpVect1 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&ctmpVect1); CvMat ctmpVect2 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&ctmpVect2); CvMat cmatrF1 = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&cmatrF1); CvMat ctmpF = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&ctmpF); CvMat ctmpE1 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&ctmpE1); CvMat ctmpE2 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&ctmpE2); /* Compute first */ cvmMul( &ccamMatr1, &crotMatr1, &cmatrP1); cvmInvert( &cmatrP1,&cinvP1 ); cvmMul( &ccamMatr1, &ctransVect1, &cvectp1 ); /* Compute second */ cvmMul( &ccamMatr2, &crotMatr2, &cmatrP2 ); cvmInvert( &cmatrP2,&cinvP2 ); cvmMul( &ccamMatr2, &ctransVect2, &cvectp2 ); cvmMul( &cmatrP1, &cinvP2, &ctmpM1); cvmMul( &ctmpM1, &cvectp2, &ctmpVect1); cvmSub( &cvectp1,&ctmpVect1,&ctmpE1); cvmMul( &cmatrP2, &cinvP1, &ctmpM2); cvmMul( &ctmpM2, &cvectp1, &ctmpVect2); cvmSub( &cvectp2, &ctmpVect2, &ctmpE2); /* Need scale */ cvmScale(&ctmpE1,&cepipole1,1.0); cvmScale(&ctmpE2,&cepipole2,1.0); cvmFree(&cmatrP1); cvmFree(&cmatrP1); cvmFree(&cvectp1); cvmFree(&cvectp2); cvmFree(&ctmpF1); cvmFree(&ctmpM1); cvmFree(&ctmpM2); cvmFree(&cinvP1); cvmFree(&cinvP2); cvmFree(&ctmpMatr); cvmFree(&ctmpVect1); cvmFree(&ctmpVect2); cvmFree(&cmatrF1); cvmFree(&ctmpF); cvmFree(&ctmpE1); cvmFree(&ctmpE2); return CV_NO_ERR; }/* cvComputeEpipoles */ /* Compute epipoles for fundamental matrix */ int cvComputeEpipolesFromFundMatrix(CvMatr32f fundMatr, CvPoint3D32f* epipole1, CvPoint3D32f* epipole2) { /* Decompose fundamental matrix using SVD ( A = U W V') */ CvMat fundMatrC = cvMat(3,3,CV_MAT32F,fundMatr); CvMat* matrW = cvCreateMat(3,3,CV_MAT32F); CvMat* matrU = cvCreateMat(3,3,CV_MAT32F); CvMat* matrV = cvCreateMat(3,3,CV_MAT32F); /* From svd we need just last vector of U and V or last row from U' and V' */ /* We get transposed matrixes U and V */ cvSVD(&fundMatrC,matrW,matrU,matrV,CV_SVD_V_T|CV_SVD_U_T); /* Get last row from U' and compute epipole1 */ epipole1->x = matrU->data.fl[6]; epipole1->y = matrU->data.fl[7]; epipole1->z = matrU->data.fl[8]; /* Get last row from V' and compute epipole2 */ epipole2->x = matrV->data.fl[6]; epipole2->y = matrV->data.fl[7]; epipole2->z = matrV->data.fl[8]; cvReleaseMat(&matrW); cvReleaseMat(&matrU); cvReleaseMat(&matrV); return CV_OK; } int cvConvertEssential2Fundamental( CvMatr32f essMatr, CvMatr32f fundMatr, CvMatr32f cameraMatr1, CvMatr32f cameraMatr2) {/* Fund = inv(CM1') * Ess * inv(CM2) */ CvMat essMatrC = cvMat(3,3,CV_MAT32F,essMatr); CvMat fundMatrC = cvMat(3,3,CV_MAT32F,fundMatr); CvMat cameraMatr1C = cvMat(3,3,CV_MAT32F,cameraMatr1); CvMat cameraMatr2C = cvMat(3,3,CV_MAT32F,cameraMatr2); CvMat* invCM2 = cvCreateMat(3,3,CV_MAT32F); CvMat* tmpMatr = cvCreateMat(3,3,CV_MAT32F); CvMat* invCM1T = cvCreateMat(3,3,CV_MAT32F); cvTranspose(&cameraMatr1C,tmpMatr); cvInvert(tmpMatr,invCM1T); cvmMul(invCM1T,&essMatrC,tmpMatr); cvInvert(&cameraMatr2C,invCM2); cvmMul(tmpMatr,invCM2,&fundMatrC); /* Scale fundamental matrix */ double scale; scale = 1.0/fundMatrC.data.fl[8]; cvConvertScale(&fundMatrC,&fundMatrC,scale); cvReleaseMat(&invCM2); cvReleaseMat(&tmpMatr); cvReleaseMat(&invCM1T); return CV_OK; } /* Compute essential matrix */ int cvComputeEssentialMatrix( CvMatr32f rotMatr, CvMatr32f transVect, CvMatr32f essMatr) { float transMatr[9]; /* Make antisymmetric matrix from transpose vector */ transMatr[0] = 0; transMatr[1] = - transVect[2]; transMatr[2] = transVect[1]; transMatr[3] = transVect[2]; transMatr[4] = 0; transMatr[5] = - transVect[0]; transMatr[6] = - transVect[1]; transMatr[7] = transVect[0]; transMatr[8] = 0; icvMulMatrix_32f(transMatr,3,3,rotMatr,3,3,essMatr); return CV_OK; }