| /*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; |
| } |
| |
| |