1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
45 /*=====================================================================================*/
46 /* new version of fundamental matrix functions */
47 /*=====================================================================================*/
49 int icvComputeFundamental7Point(CvMat* points1,CvMat* points2,
52 int icvComputeFundamental8Point(CvMat* points1,CvMat* points2,
56 int icvComputeFundamentalRANSAC( CvMat* points1,CvMat* points2,
58 double threshold,/* threshold for good point. Distance from epipolar line */
59 double p,/* probability of good result. Usually = 0.99 */
62 int icvComputeFundamentalLMedS( CvMat* points1,CvMat* points2,
64 double threshold,/* threshold for good point. Distance from epipolar line */
65 double p,/* probability of good result. Usually = 0.99 */
68 void icvMakeFundamentalSingular(CvMat* fundMatr);
70 void icvNormalizeFundPoints( CvMat* points,
73 int icvSolveCubic(CvMat* coeffs,CvMat* result);
75 void icvMake2DPoints(CvMat* srcPoint,CvMat* dstPoint);
77 void icvMake3DPoints(CvMat* srcPoint,CvMat* dstPoint);
79 void icvComputeCorrespondEpilines(CvMat* points,int pointImageID,CvMat* fundMatr,CvMat* corrLines);
81 int icvCubicV( double a2, double a1, double a0, double *squares );
83 /*=====================================================================================*/
85 /*F///////////////////////////////////////////////////////////////////////////////////////
86 // Name: cvFindFundamentalMat
87 // Purpose: find fundamental matrix for given points using
90 // points1 - points on first image. Size of matrix 2xN or 3xN
91 // points2 - points on second image Size of matrix 2xN or 3xN
92 // fundMatr - found fundamental matrix (or matrixes for 7-point). Size 3x3 or 9x3
93 // method - method for computing fundamental matrix
94 // CV_FM_7POINT - for 7-point algorithm. Number of points == 7
95 // CV_FM_8POINT - for 8-point algorithm. Number of points >= 8
96 // CV_FM_RANSAC - for RANSAC algorithm. Number of points >= 8
97 // CV_FM_LMEDS - for LMedS algorithm. Number of points >= 8
98 // param1 and param2 uses for RANSAC method
99 // param1 - threshold distance from point to epipolar line.
100 // If distance less than threshold point is good.
101 // param2 - probability. Usually = 0.99
102 // status - array, every element of which will be set to 1 if the point was good
103 // and used for computation. 0 else. (for RANSAC and LMedS only)
104 // (it is optional parameter, can be NULL)
107 // number of found matrixes
109 int cvFindFundamentalMat( CvMat* points1,
119 CvMat* wpoints[2]={0,0};
120 CvMat* tmpPoints[2]={0,0};
122 CV_FUNCNAME( "icvComputeFundamentalMat" );
125 tmpPoints[0] = points1;
126 tmpPoints[1] = points2;
127 int numRealPoints[2];
130 /* work with points */
133 for( i = 0; i < 2; i++ )
136 realW = tmpPoints[i]->cols;
137 realH = tmpPoints[i]->rows;
140 goodW = realW > realH ? realW : realH;
141 goodH = realW < realH ? realW : realH;
143 if( goodH != 2 && goodH != 3 )
145 CV_ERROR(CV_StsBadPoint,"Number of coordinates of points must be 2 or 3");
148 wpoints[i] = cvCreateMat(2,goodW,CV_64F);
150 numRealPoints[i] = goodW;
152 /* Test for transpose point matrix */
154 {/* need to transpose point matrix */
155 CvMat* tmpPointMatr = 0;
156 tmpPointMatr = cvCreateMat(goodH,goodW,CV_64F);
157 cvTranspose(tmpPoints[i],tmpPointMatr);
158 cvMake2DPoints(tmpPointMatr,wpoints[i]);
159 cvReleaseMat(&tmpPointMatr);
163 cvMake2DPoints(tmpPoints[i],wpoints[i]);
168 if( numRealPoints[0] != numRealPoints[1] )
170 CV_ERROR(CV_StsBadPoint,"Number of points must be the same");
173 numPoints = numRealPoints[0];
176 /* work with status if use functions which don't compute it */
177 if( status && (method == CV_FM_7POINT || method == CV_FM_8POINT ))
180 if( !CV_IS_MAT(status) )
182 CV_ERROR(CV_StsBadPoint,"status is not a matrix");
186 if( !CV_IS_MAT(points1))
188 CV_ERROR(CV_StsBadPoint,"Points1 not a matrix");
191 if( status->cols != numPoints || status->rows != 1 )
193 CV_ERROR(CV_StsBadPoint,"Size of status must be 1xN");
197 for( i = 0; i < status->cols; i++)
199 cvmSet(status,0,i,1.0);
207 case CV_FM_7POINT: result = icvComputeFundamental7Point(wpoints[1], wpoints[0], fundMatr);break;
209 case CV_FM_8POINT: result = icvComputeFundamental8Point(wpoints[1],wpoints[0], fundMatr);break;
211 case CV_FM_LMEDS : result = icvComputeFundamentalLMedS( wpoints[1],wpoints[0], fundMatr,
212 param1,param2,status);break;
214 case CV_FM_RANSAC: result = icvComputeFundamentalRANSAC( wpoints[1],wpoints[0], fundMatr,
215 param1,param2,status);break;
217 //default:return -1/*ERROR*/;
222 cvReleaseMat(&wpoints[0]);
223 cvReleaseMat(&wpoints[1]);
228 /*=====================================================================================*/
230 /* Computes 1 or 3 fundamental matrixes using 7-point algorithm */
231 int icvComputeFundamental7Point(CvMat* points1, CvMat* points2, CvMat* fundMatr)
232 {/* !!! Use just first real square of cubic equation */
237 CV_FUNCNAME( "icvComputeFundamental7Point" );
240 /* Test correct of input data */
242 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2)|| !CV_IS_MAT(fundMatr))
244 CV_ERROR(CV_StsBadPoint,"Not a matrixes");
247 if( !CV_ARE_TYPES_EQ( points1, points2 ))
249 CV_ERROR( CV_StsUnmatchedSizes, "Data types of points unmatched" );
253 numPoint = points1->cols;
256 type = points1->type;
258 if( numPoint != points2->cols )
260 CV_ERROR( CV_StsBadSize, "Number of points not equal" );
264 CV_ERROR( CV_StsBadSize, "Number of points must be 7" );
267 if( points1->rows != 2 && points1->rows != 3 )
269 CV_ERROR( CV_StsBadSize, "Number of coordinates of points1 must be 2 or 3" );
272 if( points2->rows != 2 && points2->rows != 3 )
274 CV_ERROR( CV_StsBadSize, "Number of coordinates of points2 must be 2 or 3" );
277 if( ( fundMatr->rows != 3 && fundMatr->rows != 9 )|| fundMatr->cols != 3 )
279 CV_ERROR( CV_StsBadSize, "Size of fundMatr must be 3x3 or 9x3" );
282 squares = cvCreateMat(2,3,CV_64F);
285 /* Make it Normalize points if need */
286 double wPoints1_dat[2*7];
287 double wPoints2_dat[2*7];
290 wPoints1 = cvMat(2,7,CV_64F,wPoints1_dat);
291 wPoints2 = cvMat(2,7,CV_64F,wPoints2_dat);
293 icvMake2DPoints(points1,&wPoints1);
294 icvMake2DPoints(points2,&wPoints2);
300 double matrU_dat[7*9];
301 matrU = cvMat(7,9,CV_64F,matrU_dat);
303 double* currDataLine;
304 currDataLine = matrU_dat;
305 for( currPoint = 0; currPoint < 7; currPoint++ )
308 x1 = cvmGet(&wPoints1,0,currPoint);
309 y1 = cvmGet(&wPoints1,1,currPoint);
310 x2 = cvmGet(&wPoints2,0,currPoint);
311 y2 = cvmGet(&wPoints2,1,currPoint);
313 currDataLine[0] = x1*x2;
314 currDataLine[1] = x1*y2;
315 currDataLine[2] = x1;
316 currDataLine[3] = y1*x2;
317 currDataLine[4] = y1*y2;
318 currDataLine[5] = y1;
319 currDataLine[6] = x2;
320 currDataLine[7] = y2;
329 double matrUU_dat[7*7];
330 double matrSS_dat[7*9];
331 double matrVV_dat[9*9];
332 matrUU = cvMat(7,7,CV_64F,matrUU_dat);
333 matrSS = cvMat(7,9,CV_64F,matrSS_dat);
334 matrVV = cvMat(9,9,CV_64F,matrVV_dat);
336 cvSVD( &matrU, &matrSS, &matrUU, &matrVV, 0/*CV_SVD_V_T*/ );/* get transposed matrix V */
338 double F111,F112,F113;
339 double F121,F122,F123;
340 double F131,F132,F133;
342 double F211,F212,F213;
343 double F221,F222,F223;
344 double F231,F232,F233;
346 F111=cvmGet(&matrVV,0,7);
347 F112=cvmGet(&matrVV,1,7);
348 F113=cvmGet(&matrVV,2,7);
349 F121=cvmGet(&matrVV,3,7);
350 F122=cvmGet(&matrVV,4,7);
351 F123=cvmGet(&matrVV,5,7);
352 F131=cvmGet(&matrVV,6,7);
353 F132=cvmGet(&matrVV,7,7);
354 F133=cvmGet(&matrVV,8,7);
356 F211=cvmGet(&matrVV,0,8);
357 F212=cvmGet(&matrVV,1,8);
358 F213=cvmGet(&matrVV,2,8);
359 F221=cvmGet(&matrVV,3,8);
360 F222=cvmGet(&matrVV,4,8);
361 F223=cvmGet(&matrVV,5,8);
362 F231=cvmGet(&matrVV,6,8);
363 F232=cvmGet(&matrVV,7,8);
364 F233=cvmGet(&matrVV,8,8);
368 a = F231*F112*F223 + F231*F212*F123 - F231*F212*F223 + F231*F113*F122 -
369 F231*F113*F222 - F231*F213*F122 + F231*F213*F222 - F131*F112*F223 -
370 F131*F212*F123 + F131*F212*F223 - F131*F113*F122 + F131*F113*F222 +
371 F131*F213*F122 - F131*F213*F222 + F121*F212*F133 - F121*F212*F233 +
372 F121*F113*F132 - F121*F113*F232 - F121*F213*F132 + F121*F213*F232 +
373 F221*F112*F133 - F221*F112*F233 - F221*F212*F133 + F221*F212*F233 -
374 F221*F113*F132 + F221*F113*F232 + F221*F213*F132 - F221*F213*F232 +
375 F121*F112*F233 - F111*F222*F133 + F111*F222*F233 - F111*F123*F132 +
376 F111*F123*F232 + F111*F223*F132 - F111*F223*F232 - F211*F122*F133 +
377 F211*F122*F233 + F211*F222*F133 - F211*F222*F233 + F211*F123*F132 -
378 F211*F123*F232 - F211*F223*F132 + F211*F223*F232 + F111*F122*F133 -
379 F111*F122*F233 - F121*F112*F133 + F131*F112*F123 - F231*F112*F123;
381 b = 2*F231*F213*F122 - 3*F231*F213*F222 + F231*F112*F123 - 2*F231*F112*F223 -
382 2*F231*F212*F123 + 3*F231*F212*F223 - F231*F113*F122 + 2*F231*F113*F222 +
383 F131*F212*F123 - 2*F131*F212*F223 - F131*F113*F222 - F131*F213*F122 +
384 2*F131*F213*F222 + F121*F113*F232 + F121*F213*F132 - 2*F121*F213*F232 -
385 F221*F112*F133 + 2*F221*F112*F233 + 2*F221*F212*F133 - 3*F221*F212*F233 +
386 F221*F113*F132 - 2*F221*F113*F232 - 2*F221*F213*F132 + 3*F221*F213*F232 +
387 F131*F112*F223 - 2*F211*F122*F233 - 2*F211*F222*F133 + 3*F211*F222*F233 -
388 F211*F123*F132 + 2*F211*F123*F232 + 2*F211*F223*F132 - 3*F211*F223*F232 -
389 F121*F112*F233 - F121*F212*F133 + 2*F121*F212*F233 - 2*F111*F222*F233 -
390 F111*F123*F232 - F111*F223*F132 + 2*F111*F223*F232 + F111*F122*F233 +
391 F111*F222*F133 + F211*F122*F133;
393 c = F231*F112*F223 + F231*F212*F123 - 3*F231*F212*F223 - F231*F113*F222 -
394 F231*F213*F122 + 3*F231*F213*F222 + F131*F212*F223 - F131*F213*F222 +
395 F121*F213*F232 - F221*F112*F233 - F221*F212*F133 + 3*F221*F212*F233 +
396 F221*F113*F232 + F221*F213*F132 - 3*F221*F213*F232 + F211*F122*F233 +
397 F211*F222*F133 - 3*F211*F222*F233 - F211*F123*F232 - F211*F223*F132 +
398 3*F211*F223*F232 - F121*F212*F233 + F111*F222*F233 - F111*F223*F232;
400 d = F221*F213*F232 - F211*F223*F232 + F211*F222*F233 - F221*F212*F233 +
401 F231*F212*F223 - F231*F213*F222;
404 double coeffs_dat[4];
406 coeffs = cvMat(1,4,CV_64F,coeffs_dat);
408 cvmSet(&coeffs,0,0,a);
409 cvmSet(&coeffs,0,1,b);
410 cvmSet(&coeffs,0,2,c);
411 cvmSet(&coeffs,0,3,d);
414 numCubRoots = icvSolveCubic(&coeffs,squares);
416 /* take real solution */
417 /* !!! Need test whole 3 roots */
420 for( i = 0; i < numCubRoots; i++ )
422 if( fabs(cvmGet(squares,1,i)) < 1e-8 )
423 {//It is real square. (Im==0)
426 sol = cvmGet(squares,0,i);
427 //F=sol*F1+(1-sol)*F2;
430 for( t = 0; t < 9; t++ )
433 f1 = cvmGet(&matrVV,t,7);
434 f2 = cvmGet(&matrVV,t,8);
436 double s = f1 * sol + (1-sol) * f2;
437 cvmSet(fundMatr,numberRoots*3 + t/3,t%3,s);
441 if( fundMatr->rows == 3 )/* not enough space to store more than one root */
446 /* scale fundamental matrix */
447 for( i = 0; i < numberRoots; i++ )
451 fsc = cvmGet(fundMatr,i*3+2,2);
452 if( fabs(fsc) > 1e-8 )
455 cvGetSubArr( fundMatr, &subFund, cvRect(0,i*3,3,3) );
456 cvmScale(&subFund,&subFund,1.0/fsc);
462 cvReleaseMat(&squares);
469 /*=====================================================================================*/
471 int icvComputeFundamental8Point(CvMat* points1,CvMat* points2, CvMat* fundMatr)
473 CvMat* wpoints[2]={0,0};
474 CvMat* preFundMatr = 0;
481 int numFundMatrs = 0;
483 CV_FUNCNAME( "icvComputeFundamental8Point" );
486 /* Test correct of input data */
488 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2)|| !CV_IS_MAT(fundMatr))
490 CV_ERROR(CV_StsBadPoint,"Not a matrixes");
493 if( !CV_ARE_TYPES_EQ( points1, points2 ))
495 CV_ERROR( CV_StsUnmatchedSizes, "Data types of points unmatched" );
499 numPoint = points1->cols;
502 type = points1->type;
504 if( numPoint != points2->cols )
506 CV_ERROR( CV_StsBadSize, "Number of points not equal" );
510 CV_ERROR( CV_StsBadSize, "Number of points must be at least 8" );
513 if( points1->rows > 3 || points1->rows < 2 )
515 CV_ERROR( CV_StsBadSize, "Number of coordinates of points1 must be 2 or 3" );
518 if( points2->rows > 3 || points2->rows < 2 )
520 CV_ERROR( CV_StsBadSize, "Number of coordinates of points2 must be 2 or 3" );
523 if( fundMatr->rows != 3 || fundMatr->cols != 3 )
525 CV_ERROR( CV_StsBadSize, "Size of fundMatr must be 3x3" );
529 CV_CALL( wpoints[0] = cvCreateMat(2,numPoint,CV_64F) );
530 CV_CALL( wpoints[1] = cvCreateMat(2,numPoint,CV_64F) );
531 CV_CALL( matrA = cvCreateMat(numPoint,9,CV_64F) );
532 CV_CALL( preFundMatr = cvCreateMat(3,3,CV_64F) );
533 CV_CALL( matrU = cvCreateMat(numPoint,numPoint,CV_64F) );
534 CV_CALL( matrW = cvCreateMat(numPoint,9,CV_64F) );
535 CV_CALL( matrV = cvCreateMat(9,9,CV_64F) );
536 CV_CALL( sqdists = cvCreateMat(1,numPoint,CV_64F) );
538 /* Create working points with just x,y */
541 double transfMatr1_dat[9];
542 double transfMatr2_dat[9];
543 transfMatr[0] = cvMat(3,3,CV_64F,transfMatr1_dat);
544 transfMatr[1] = cvMat(3,3,CV_64F,transfMatr2_dat);
546 {/* transform to x,y. tranform point and compute transform matrixes */
547 icvMake2DPoints(points1,wpoints[0]);
548 icvMake2DPoints(points2,wpoints[1]);
550 icvNormalizeFundPoints( wpoints[0],&transfMatr[0]);
551 icvNormalizeFundPoints( wpoints[1],&transfMatr[1]);
553 /* we have normalized working points wpoints[0] and wpoints[1] */
554 /* build matrix A from points coordinates */
557 for( currPoint = 0; currPoint < numPoint; currPoint++ )
563 x1 = cvmGet(wpoints[0],0,currPoint);
564 y1 = cvmGet(wpoints[0],1,currPoint);
565 x2 = cvmGet(wpoints[1],0,currPoint);
566 y2 = cvmGet(wpoints[1],1,currPoint);
568 cvGetRow(matrA,&rowA,currPoint);
569 rowA.data.db[0] = x1*x2;
570 rowA.data.db[1] = x1*y2;
571 rowA.data.db[2] = x1;
573 rowA.data.db[3] = y1*x2;
574 rowA.data.db[4] = y1*y2;
575 rowA.data.db[5] = y1;
577 rowA.data.db[6] = x2;
578 rowA.data.db[7] = y2;
583 /* We have matrix A. Compute svd(A). We need last column of V */
586 cvSVD( matrA, matrW, matrU, matrV, CV_SVD_V_T );/* get transposed matrix V */
588 /* Compute number of non zero eigen values */
593 for( i = 0; i < 9; i++ )
595 if( cvmGet(matrW,i,i) < 1e-8 )
613 /* copy last row of matrix V to precomputed fundamental matrix */
616 cvGetRow(matrV,&preF,8);
617 cvReshape(&preF,preFundMatr,1,3);
619 /* Apply singularity condition */
620 icvMakeFundamentalSingular(preFundMatr);
622 /* Denormalize fundamental matrix */
623 /* Copmute transformation for normalization */
626 double wfundMatr_dat[9];
627 wfundMatr = cvMat(3,3,CV_64F,wfundMatr_dat);
629 {/* Freal = T1'*Fpre*T2 */
630 double tmpMatr_dat[9];
631 double tmptransfMatr_dat[9];
633 CvMat tmpMatr = cvMat(3,3,CV_64F,tmpMatr_dat);
634 CvMat tmptransfMatr = cvMat(3,3,CV_64F,tmptransfMatr_dat);
636 cvTranspose(&transfMatr[0],&tmptransfMatr);
638 cvmMul(&tmptransfMatr,preFundMatr,&tmpMatr);
639 cvmMul(&tmpMatr,&transfMatr[1],&wfundMatr);
642 /* scale fundamental matrix */
644 fsc = cvmGet(&wfundMatr,2,2);
645 if( fabs(fsc) > 1.0e-8 )
647 cvmScale(&wfundMatr,&wfundMatr,1.0/fsc);
650 /* copy result fundamental matrix */
651 cvConvert( &wfundMatr, fundMatr );
658 cvReleaseMat(&matrU);
659 cvReleaseMat(&matrW);
660 cvReleaseMat(&matrV);
661 cvReleaseMat(&preFundMatr);
662 cvReleaseMat(&matrA);
663 cvReleaseMat(&wpoints[0]);
664 cvReleaseMat(&wpoints[1]);
665 cvReleaseMat(&sqdists);
670 /*=====================================================================================*/
672 /* Computes fundamental matrix using RANSAC method */
674 int icvComputeFundamentalRANSAC( CvMat* points1,CvMat* points2,
676 double threshold,/* Threshold for good points */
677 double p,/* Probability of good result. */
682 CvMat* corrLines1 = 0;
683 CvMat* corrLines2 = 0;
684 CvMat* bestPoints1 = 0;
685 CvMat* bestPoints2 = 0;
691 CV_FUNCNAME( "icvComputeFundamentalRANSAC" );
694 /* Test correct of input data */
696 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2)|| !CV_IS_MAT(fundMatr))
698 CV_ERROR(CV_StsBadPoint,"points1 or points2 or funMatr are not a matrixes");
702 numPoint = points1->cols;
705 type = points1->type;
707 if( numPoint != points2->cols )
709 CV_ERROR( CV_StsBadSize, "Number of points not equals" );
713 CV_ERROR( CV_StsBadSize, "Number of points must be >= 8" );
716 if( points1->rows != 2 && points1->rows != 3 )
718 CV_ERROR( CV_StsBadSize, "Number of coordinates of points1 must be 2 or 3" );
721 if( points2->rows != 2 && points2->rows != 3 )
723 CV_ERROR( CV_StsBadSize, "Number of coordinates of points2 must be 2 or 3" );
726 if( fundMatr->rows != 3 || fundMatr->cols != 3 )
728 CV_ERROR( CV_StsBadSize, "Size of fundMatr must be 3x3" );
732 {/* status is present test it */
733 if( !CV_IS_MAT(status) )
735 CV_ERROR(CV_StsBadPoint,"status is not a matrix");
738 if( status->cols != numPoint || status->rows != 1 )
740 CV_ERROR(CV_StsBadPoint,"Size of status must be 1xN");
744 /* We will choose adaptive number of N (samples) */
746 /* Convert points to 64F working points */
748 CV_CALL( flags = (int*)cvAlloc(numPoint * sizeof(int)) );
749 CV_CALL( bestFlags = (int*)cvAlloc(numPoint * sizeof(int)) );
750 CV_CALL( wpoints1 = cvCreateMat(3,numPoint,CV_64F) );
751 CV_CALL( wpoints2 = cvCreateMat(3,numPoint,CV_64F) );
752 CV_CALL( corrLines1 = cvCreateMat(3,numPoint,CV_64F));
753 CV_CALL( corrLines2 = cvCreateMat(3,numPoint,CV_64F));
754 CV_CALL( bestPoints1 = cvCreateMat(3,numPoint,CV_64F));
755 CV_CALL( bestPoints2 = cvCreateMat(3,numPoint,CV_64F));
757 icvMake3DPoints(points1,wpoints1);
758 icvMake3DPoints(points2,wpoints2);
763 int NumSamples = 1;//just init number of samples
764 int wasCount = 0; //count of choosing samples
765 int maxGoodPoints = 0;
766 int numGoodPoints = 0;
768 double bestFund_dat[9];
770 bestFund = cvMat(3,3,CV_64F,bestFund_dat);
773 while( NumSamples > wasCount )
780 for( i = 0; i < 7; i++ )
784 newnum = rand()%numPoint;
786 /* test this number */
789 for( test = 0; test < i; test++ )
791 if( randNumbs[test] == newnum )
799 randNumbs[i] = newnum;
801 /* random numbers of points was generated */
804 double selPoints1_dat[2*7];
805 double selPoints2_dat[2*7];
808 selPoints1 = cvMat(2,7,CV_64F,selPoints1_dat);
809 selPoints2 = cvMat(2,7,CV_64F,selPoints2_dat);
812 for( t = 0; t < 7; t++ )
815 x = cvmGet(wpoints1,0,randNumbs[t]);
816 y = cvmGet(wpoints1,1,randNumbs[t]);
817 cvmSet(&selPoints1,0,t,x);
818 cvmSet(&selPoints1,1,t,y);
820 x = cvmGet(wpoints2,0,randNumbs[t]);
821 y = cvmGet(wpoints2,1,randNumbs[t]);
822 cvmSet(&selPoints2,0,t,x);
823 cvmSet(&selPoints2,1,t,y);
826 /* Copmute fundamental matrix using 7-points algorithm */
828 double fundTriple_dat[27];
830 fundTriple = cvMat(9,3,CV_64F,fundTriple_dat);
832 int numFund = icvComputeFundamental7Point(&selPoints1,&selPoints2,&fundTriple);
834 //double fund7_dat[9];
836 //fund7 = cvMat(3,3,CV_64F,fund7_dat);
839 for( int currFund = 0; currFund < numFund; currFund++ )
841 cvGetSubArr(&fundTriple,&fund7,cvRect(0,currFund*3,3,3));
843 /* Compute inliers for this fundamental matrix */
844 /* Compute distances for points and correspond lines */
846 /* Create corresponde lines */
848 icvComputeCorrespondEpilines(wpoints1,2,&fund7,corrLines2);
849 icvComputeCorrespondEpilines(wpoints2,1,&fund7,corrLines1);
850 /* compute distances for points and number of good points */
853 for( i = 0; i < numPoint; i++ )
857 cvGetCol(wpoints1,&pnt1,i);
858 cvGetCol(corrLines1,&lin1,i);
859 cvGetCol(wpoints2,&pnt2,i);
860 cvGetCol(corrLines2,&lin2,i);
862 dist1 = fabs(cvDotProduct(&pnt1,&lin1));
863 dist2 = fabs(cvDotProduct(&pnt2,&lin2));
864 flags[i] = ( dist1 < threshold && dist2 < threshold )?1:0;
865 numGoodPoints += flags[i];
870 if( numGoodPoints > maxGoodPoints )
872 cvCopy(&fund7,&bestFund);
873 maxGoodPoints = numGoodPoints;
874 /* copy best flags */
876 for(i=0;i<numPoint;i++)
878 bestFlags[i] = flags[i];
883 /* Adaptive number of samples to count*/
884 double ep = 1 - (double)numGoodPoints / (double)numPoint;
887 ep = 0.5;//if there is not good points set ration of outliers to 50%
890 NumSamples = cvRound(log(1-p) / log(1-pow(1-ep,7)));
894 /* we have best 7-point fundamental matrix. */
895 /* and best points */
896 /* use these points to improve matrix */
898 /* collect best points */
901 /* Test number of points. And if number >=8 improove found fundamental matrix */
903 if( maxGoodPoints < 7 )
905 /* Fundamental matrix not found */
910 if( maxGoodPoints > 7 )
912 /* Found >= 8 point. Improove matrix */
917 for( i = 0; i < numPoint; i++ )
923 cvGetCol( wpoints1,&wPnt, i );
924 cvGetCol( bestPoints1,&bestPnt, currPnt );
925 cvCopy(&wPnt,&bestPnt);
926 cvGetCol( wpoints2,&wPnt, i );
927 cvGetCol( bestPoints2,&bestPnt, currPnt );
928 cvCopy(&wPnt,&bestPnt);
936 cvGetSubArr( bestPoints1, &wbestPnts1, cvRect(0,0,maxGoodPoints,3) );
937 cvGetSubArr( bestPoints2, &wbestPnts2, cvRect(0,0,maxGoodPoints,3) );
939 /* best points was collectet. Improve fundamental matrix */
940 /* !!! Just use 8-point algorithm */
941 double impFundMatr_dat[9];
943 impFundMatr = cvMat(3,3,CV_64F,impFundMatr_dat);
944 numFundMatr = icvComputeFundamental8Point(&wbestPnts1,&wbestPnts2,&impFundMatr);
946 cvConvert(&impFundMatr,fundMatr);
947 //cvConvert(&bestFund,fundMatr); // This line must be deleted
951 /* 7 point. Just copy to result */
952 cvConvert(&bestFund,fundMatr);
956 /* copy flag to status if need */
959 for( int i = 0; i < numPoint; i++)
961 cvmSet(status,0,i,(double)bestFlags[i]);
971 /* free allocated memory */
973 cvReleaseMat(&corrLines1);
974 cvReleaseMat(&corrLines2);
975 cvReleaseMat(&wpoints1);
976 cvReleaseMat(&wpoints2);
977 cvReleaseMat(&bestPoints1);
978 cvReleaseMat(&bestPoints2);
979 cvFree((void**)&flags);
980 cvFree((void**)&bestFlags);
983 }//icvComputeFundamentalRANSAC
985 /*=====================================================================================*/
987 void icvCompPointLineDists(CvMat* points,CvMat* lines,CvMat* distances)
988 {/* Line must be normalized */
991 numPoints = points->cols;
992 if( numPoints != lines->cols && numPoints != distances->cols )
994 //printf("Size if arrays not equals\n");
999 for( i = 0; i < numPoints; i++ )
1003 cvGetCol(points,&pnt,i);
1004 cvGetCol(lines,&lin,i);
1006 dist = fabs(cvDotProduct(&pnt,&lin));
1007 cvmSet(distances,0,i,dist);
1013 /*=====================================================================================*/
1017 #define _compVals( v1, v2 ) ((v1) < (v2))
1019 /* Create function to sort vector */
1020 CV_IMPLEMENT_QSORT( _SortCvMatVect, double, _compVals )
1022 /*=====================================================================================*/
1023 int icvComputeFundamentalLMedS( CvMat* points1,CvMat* points2,
1025 double threshold,/* Threshold for good points */
1026 double p,/* Probability of good result. */
1029 CvMat* wpoints1 = 0;
1030 CvMat* wpoints2 = 0;
1031 CvMat* corrLines1 = 0;
1032 CvMat* corrLines2 = 0;
1033 CvMat* bestPoints1 = 0;
1034 CvMat* bestPoints2 = 0;
1037 CvMat* distsSq1 = 0;
1038 CvMat* distsSq2 = 0;
1039 CvMat* allDists = 0;
1043 int numFundMatr = 0;
1045 CV_FUNCNAME( "icvComputeFundamentalLMedS" );
1048 /* Test correct of input data */
1050 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2)|| !CV_IS_MAT(fundMatr))
1052 CV_ERROR(CV_StsBadPoint,"Not a matrixes");
1056 numPoint = points1->cols;
1059 type = points1->type;
1061 if( numPoint != points2->cols )
1063 CV_ERROR( CV_StsBadSize, "Number of points not equal" );
1067 CV_ERROR( CV_StsBadSize, "Number of points must be >= 8" );
1070 if( points1->rows != 2 && points1->rows != 3 )
1072 CV_ERROR( CV_StsBadSize, "Number of coordinates of points1 must be 2 or 3" );
1075 if( points2->rows != 2 && points2->rows != 3 )
1077 CV_ERROR( CV_StsBadSize, "Number of coordinates of points2 must be 2 or 3" );
1080 if( fundMatr->rows != 3 || fundMatr->cols != 3 )
1082 CV_ERROR( CV_StsBadSize, "Size of fundMatr must be 3x3" );
1086 {/* status is present test it */
1087 if( !CV_IS_MAT(status) )
1089 CV_ERROR(CV_StsBadPoint,"status is not a matrix");
1092 if( status->cols != numPoint || status->rows != 1 )
1094 CV_ERROR(CV_StsBadPoint,"Size of status must be 1xN");
1098 /* We will choose adaptive number of N (samples) */
1100 /* Convert points to 64F working points */
1102 CV_CALL( flags = (int*)cvAlloc(numPoint * sizeof(int)) );
1103 CV_CALL( bestFlags = (int*)cvAlloc(numPoint * sizeof(int)) );
1104 CV_CALL( wpoints1 = cvCreateMat(3,numPoint,CV_64F) );
1105 CV_CALL( wpoints2 = cvCreateMat(3,numPoint,CV_64F) );
1106 CV_CALL( corrLines1 = cvCreateMat(3,numPoint,CV_64F));
1107 CV_CALL( corrLines2 = cvCreateMat(3,numPoint,CV_64F));
1108 CV_CALL( bestPoints1 = cvCreateMat(3,numPoint,CV_64F));
1109 CV_CALL( bestPoints2 = cvCreateMat(3,numPoint,CV_64F));
1110 CV_CALL( dists1 = cvCreateMat(1,numPoint,CV_64F));
1111 CV_CALL( dists2 = cvCreateMat(1,numPoint,CV_64F));
1112 CV_CALL( distsSq1 = cvCreateMat(1,numPoint,CV_64F));
1113 CV_CALL( distsSq2 = cvCreateMat(1,numPoint,CV_64F));
1114 CV_CALL( allDists = cvCreateMat(1,numPoint,CV_64F));
1116 icvMake3DPoints(points1,wpoints1);
1117 icvMake3DPoints(points2,wpoints2);
1122 int NumSamples = 1;//just init number of samples
1123 int wasCount = 0; //count of choosing samples
1125 double goodMean = FLT_MAX;
1128 int numGoodPoints = 0;
1130 double bestFund_dat[9];
1132 bestFund = cvMat(3,3,CV_64F,bestFund_dat);
1134 /* choosen points */
1135 while( NumSamples > wasCount )
1137 /* select samples */
1142 for( i = 0; i < 7; i++ )
1146 newnum = rand()%numPoint;
1148 /* test this number */
1151 for( test = 0; test < i; test++ )
1153 if( randNumbs[test] == newnum )
1161 randNumbs[i] = newnum;
1163 /* random numbers of points was generated */
1166 double selPoints1_dat[2*7];
1167 double selPoints2_dat[2*7];
1170 selPoints1 = cvMat(2,7,CV_64F,selPoints1_dat);
1171 selPoints2 = cvMat(2,7,CV_64F,selPoints2_dat);
1174 for( t = 0; t < 7; t++ )
1177 x = cvmGet(wpoints1,0,randNumbs[t]);
1178 y = cvmGet(wpoints1,1,randNumbs[t]);
1179 cvmSet(&selPoints1,0,t,x);
1180 cvmSet(&selPoints1,1,t,y);
1182 x = cvmGet(wpoints2,0,randNumbs[t]);
1183 y = cvmGet(wpoints2,1,randNumbs[t]);
1184 cvmSet(&selPoints2,0,t,x);
1185 cvmSet(&selPoints2,1,t,y);
1187 /* Compute fundamental matrix using 7-points algorithm */
1189 double fundTriple_dat[27];
1191 fundTriple = cvMat(9,3,CV_64F,fundTriple_dat);
1193 int numFund = icvComputeFundamental7Point(&selPoints1,&selPoints2,&fundTriple);
1195 //double fund7_dat[9];
1197 //fund7 = cvMat(3,3,CV_64F,fund7_dat);
1199 /* get sub matrix */
1200 for( int currFund = 0; currFund < numFund; currFund++ )
1203 cvGetSubArr(&fundTriple,&fund7,cvRect(0,currFund*3,3,3));
1205 /* Compute median error for this matrix */
1207 icvComputeCorrespondEpilines(wpoints1,2,&fund7,corrLines2);
1208 icvComputeCorrespondEpilines(wpoints2,1,&fund7,corrLines1);
1210 icvCompPointLineDists(wpoints1,corrLines1,dists1);
1211 icvCompPointLineDists(wpoints2,corrLines2,dists2);
1213 /* add distances for points (d1*d1+d2*d2) */
1214 cvMul(dists1,dists1,distsSq1);
1215 cvMul(dists2,dists2,distsSq2);
1217 cvAdd(distsSq1,distsSq2,allDists);
1219 /* sort distances */
1220 _SortCvMatVect(allDists->data.db,numPoint,0);
1222 /* get median error */
1223 currMean = allDists->data.db[numPoint/2];
1227 if( currMean < goodMean )
1229 cvCopy(&fund7,&bestFund);
1230 goodMean = currMean;
1232 /* Compute number of good points using threshold */
1235 for( i = 0 ; i < numPoint; i++ )
1237 if( dists1->data.db[i] < threshold && dists2->data.db[i] < threshold )
1246 /* Compute adaptive number of steps */
1247 double ep = 1 - (double)numGoodPoints / (double)numPoint;
1250 ep = 0.5;//if there is not good points set ration of outliers to 50%
1253 NumSamples = cvRound(log(1-p) / log(1-pow(1-ep,7)));
1258 /* Select just good points using threshold */
1259 /* Compute distances for all points for best fundamental matrix */
1261 /* Test if we have computed fundamental matrix*/
1262 if( goodMean == FLT_MAX )
1268 {/* we have computed fundamental matrix */
1270 icvComputeCorrespondEpilines(wpoints1,2,&bestFund,corrLines2);
1271 icvComputeCorrespondEpilines(wpoints2,1,&bestFund,corrLines1);
1273 icvCompPointLineDists(wpoints1,corrLines1,dists1);
1274 icvCompPointLineDists(wpoints2,corrLines2,dists2);
1276 /* test dist for each point and set status for each point if need */
1279 for( i = 0; i < numPoint; i++ )
1281 if( dists1->data.db[i] < threshold && dists2->data.db[i] < threshold )
1285 cvGetCol( wpoints1,&wPnt, i );
1286 cvGetCol( bestPoints1,&bestPnt, currPnt );
1287 cvCopy(&wPnt,&bestPnt);
1288 cvGetCol( wpoints2,&wPnt, i );
1289 cvGetCol( bestPoints2,&bestPnt, currPnt );
1290 cvCopy(&wPnt,&bestPnt);
1294 cvmSet(status,0,i,1.0);
1299 cvmSet(status,0,i,0.0);
1303 numGoodPoints = currPnt;
1306 /* we have best 7-point fundamental matrix. */
1307 /* and best points */
1308 /* use these points to improove matrix */
1310 /* Test number of points. And if number >=8 improove found fundamental matrix */
1312 if( numGoodPoints < 7 )
1314 /* Fundamental matrix not found */
1319 if( numGoodPoints > 7 )
1321 /* Found >= 8 point. Improove matrix */
1326 cvGetSubArr( bestPoints1, &wbestPnts1, cvRect(0,0,numGoodPoints,3) );
1327 cvGetSubArr( bestPoints2, &wbestPnts2, cvRect(0,0,numGoodPoints,3) );
1329 /* best points was collectet. Improve fundamental matrix */
1330 /* !!! Just use 8-point algorithm */
1331 double impFundMatr_dat[9];
1333 impFundMatr = cvMat(3,3,CV_64F,impFundMatr_dat);
1334 numFundMatr = icvComputeFundamental8Point(&wbestPnts1,&wbestPnts2,&impFundMatr);
1336 cvConvert(&impFundMatr,fundMatr);
1340 /* 7 point. Just copy to result */
1341 cvConvert(&bestFund,fundMatr);
1351 /* free allocated memory */
1353 cvReleaseMat(&corrLines1);
1354 cvReleaseMat(&corrLines2);
1355 cvReleaseMat(&wpoints1);
1356 cvReleaseMat(&wpoints2);
1357 cvReleaseMat(&bestPoints1);
1358 cvReleaseMat(&bestPoints2);
1359 cvReleaseMat(&dists1);
1360 cvReleaseMat(&dists2);
1361 cvReleaseMat(&distsSq1);
1362 cvReleaseMat(&distsSq2);
1363 cvReleaseMat(&allDists);
1364 cvFree((void**)&flags);
1365 cvFree((void**)&bestFlags);
1368 }//icvComputeFundamentalLMedS
1370 /*=====================================================================================*/
1374 void icvMakeFundamentalSingular(CvMat* fundMatr)
1376 CV_FUNCNAME( "icvFundSingular" );
1379 if( !CV_IS_MAT(fundMatr) )
1381 CV_ERROR(CV_StsBadPoint,"Input data is not matrix");
1384 if( fundMatr->rows != 3 || fundMatr->cols != 3 )
1386 CV_ERROR( CV_StsBadSize, "Size of fundametal matrix must be 3x3" );
1390 {/* Apply singularity condition */
1396 double matrFU_dat[9];
1397 double matrFW_dat[9];
1398 double matrFVt_dat[9];
1399 double tmpMatr_dat[9];
1400 double preFundMatr_dat[9];
1403 matrFU = cvMat(3,3,CV_64F,matrFU_dat);
1404 matrFW = cvMat(3,3,CV_64F,matrFW_dat);
1405 matrFVt = cvMat(3,3,CV_64F,matrFVt_dat);
1406 tmpMatr = cvMat(3,3,CV_64F,tmpMatr_dat);
1407 preFundMatr = cvMat(3,3,CV_64F,preFundMatr_dat);
1409 cvConvert(fundMatr,&preFundMatr);
1410 cvSVD( &preFundMatr, &matrFW, &matrFU, &matrFVt, CV_SVD_V_T );
1411 cvmSet(&matrFW,2,2,0);
1412 /* multiply U*W*V' */
1414 cvmMul(&matrFU,&matrFW,&tmpMatr);
1415 cvmMul(&tmpMatr,&matrFVt,&preFundMatr);
1416 cvConvert(&preFundMatr,fundMatr);
1423 /*=====================================================================================*/
1424 /* Normalize points for computing fundamental matrix */
1425 /* and compute transform matrix */
1428 /* place centroid of points to (0,0) */
1429 /* set mean distance from (0,0) by sqrt(2) */
1431 void icvNormalizeFundPoints( CvMat* points,
1434 CvMat* subwpointsx = 0;
1435 CvMat* subwpointsy = 0;
1437 CvMat* pointsxx = 0;
1438 CvMat* pointsyy = 0;
1440 CV_FUNCNAME( "icvNormalizeFundPoints" );
1443 /* Test for correct input data */
1445 if( !CV_IS_MAT(points) || !CV_IS_MAT(transfMatr) )
1447 CV_ERROR(CV_StsBadPoint,"Input data is not matrixes");
1451 numPoint = points->cols;
1454 type = points->type;
1458 CV_ERROR( CV_StsBadSize, "Number of points must be at least 1" );
1461 if( points->rows != 2 )
1463 CV_ERROR( CV_StsBadSize, "Number of coordinates of points1 must be 2" );
1466 if( transfMatr->rows != 3 || transfMatr->cols != 3 )
1468 CV_ERROR( CV_StsBadSize, "Size of transform matrix must be 3x3" );
1471 CV_CALL( subwpointsx = cvCreateMat(1,numPoint,CV_64F));
1472 CV_CALL( subwpointsy = cvCreateMat(1,numPoint,CV_64F));
1473 CV_CALL( sqdists = cvCreateMat(1,numPoint,CV_64F));
1474 CV_CALL( pointsxx = cvCreateMat(1,numPoint,CV_64F));
1475 CV_CALL( pointsyy = cvCreateMat(1,numPoint,CV_64F));
1477 /* get x,y coordinates of points */
1482 cvGetRow( points, &tmpwpointsx, 0 );
1483 cvGetRow( points, &tmpwpointsy, 1 );
1485 /* Copy to working data 64F */
1486 cvConvert(&tmpwpointsx,subwpointsx);
1487 cvConvert(&tmpwpointsy,subwpointsy);
1490 double shiftx,shifty;
1492 /* Compute center of points */
1494 CvScalar sumx = cvSum(subwpointsx);
1495 CvScalar sumy = cvSum(subwpointsy);
1497 sumx.val[0] /= (double)numPoint;
1498 sumy.val[0] /= (double)numPoint;
1500 shiftx = sumx.val[0];
1501 shifty = sumy.val[0];
1503 /* Shift points center to 0 */
1505 cvSubS( subwpointsx, sumx, subwpointsx);
1506 cvSubS( subwpointsy, sumy, subwpointsy);
1508 /* Compute x*x and y*y */
1510 cvMul(subwpointsx,subwpointsx,pointsxx);
1511 cvMul(subwpointsy,subwpointsy,pointsyy);
1514 cvAdd( pointsxx, pointsyy, sqdists);
1516 /* compute sqrt of each component*/
1518 cvPow(sqdists,sqdists,0.5);
1520 /* in vector sqdists we have distances */
1521 /* compute mean value and scale */
1524 meand = cvMean(sqdists);
1527 if( fabs(meand) > 1e-8 )
1529 scale = sqrt(2)/meand;
1537 /* scale working points */
1538 cvScale(subwpointsx,subwpointsx,scale);
1539 cvScale(subwpointsy,subwpointsy,scale);
1541 /* copy output data */
1545 cvGetRow( points, &tmpwpointsx, 0 );
1546 cvGetRow( points, &tmpwpointsy, 1 );
1548 /* Copy to output data 64F */
1549 cvConvert(subwpointsx,&tmpwpointsx);
1550 cvConvert(subwpointsy,&tmpwpointsy);
1553 /* Set transform matrix */
1555 cvmSet(transfMatr,0,0, scale);
1556 cvmSet(transfMatr,0,1, 0);
1557 cvmSet(transfMatr,0,2, -scale*shiftx);
1559 cvmSet(transfMatr,1,0, 0);
1560 cvmSet(transfMatr,1,1, scale);
1561 cvmSet(transfMatr,1,2, -scale*shifty);
1563 cvmSet(transfMatr,2,0, 0);
1564 cvmSet(transfMatr,2,1, 0);
1565 cvmSet(transfMatr,2,2, 1);
1570 cvReleaseMat(&subwpointsx);
1571 cvReleaseMat(&subwpointsy);
1572 cvReleaseMat(&sqdists);
1573 cvReleaseMat(&pointsxx);
1574 cvReleaseMat(&pointsyy);
1577 /*=====================================================================================*/
1578 // Solve cubic equation and returns number of roots
1579 int cvSolveCubic(CvMat* coeffs,CvMat* result)
1581 return icvSolveCubic(coeffs, result);
1584 /*=====================================================================================*/
1585 // Solve cubic equation and returns number of roots
1586 // Also returns 0 if all values are possible
1587 // Test for very big coefficients
1588 // Input params 1x3 or 1x4
1589 int icvSolveCubic(CvMat* coeffs,CvMat* result)
1590 {/* solve a*x^3 + b+x^2 + c*x + d = 0 */
1591 /* coeffs a,b,c,d or b,c,d if a== 1*/
1592 /* test input params */
1597 CV_FUNCNAME( "icvSolveCubic" );
1600 /* Test correct of input data */
1602 if( !CV_IS_MAT(coeffs) || !CV_IS_MAT(result) )
1604 CV_ERROR(CV_StsBadPoint,"Not a matrixes");
1607 if( !(coeffs->rows == 1 && (coeffs->cols == 3 || coeffs->cols == 4) ))
1609 CV_ERROR( CV_StsBadSize, "Number of coeffs must be 3 or 4" );
1615 cc[0] = cvmGet(coeffs,0,0);
1616 cc[1] = cvmGet(coeffs,0,1);
1617 cc[2] = cvmGet(coeffs,0,2);
1619 if( fabs(cc[0]) > FLT_MAX || fabs(cc[1]) > FLT_MAX || fabs(cc[2]) > FLT_MAX )
1621 return 0;//Coeffs too big
1625 if( coeffs->cols == 3 )
1630 numRoots = icvCubicV(a0,a1,a2,squares);
1633 {// We have for coeffs
1634 /* Test for very big coeffs */
1635 cc[3] = cvmGet(coeffs,0,3);
1637 if( fabs(cc[3]) > FLT_MAX )
1639 return 0;//Coeffs too big
1643 if( fabs(a) > FLT_MIN)
1649 numRoots = icvCubicV(a0,a1,a2,squares);
1652 {// !!! It's a square eqaution.
1657 if( fabs(a) > 1e-8 )
1664 squares[0] = (-b + sqrt(D))/(2*a);
1666 squares[2] = (-b - sqrt(D))/(2*a);
1672 {/* Two Im values */
1674 squares[0] = (-b)/(2*a);
1675 squares[1] = ( sqrt(-D))/(2*a);
1677 squares[2] = (-b)/(2*a);
1678 squares[3] = ( -sqrt(-D))/(2*a);
1683 squares[0] = (-b)/(2*a);
1685 squares[2] = (-b)/(2*a);
1692 if( fabs(b) > FLT_MIN )
1700 if( fabs(c) > FLT_MIN)
1706 /* All values are posible */
1708 //cvmSet(result,0,0,0);
1709 //cvmSet(result,1,0,0);
1719 for( i=0;i<numRoots;i++ )
1721 cvmSet(result,0,i,squares[i*2]);
1722 cvmSet(result,1,i,squares[i*2+1]);
1729 /*=====================================================================================*/
1730 void cvMake2DPoints(CvMat* srcPoint,CvMat* dstPoint)
1732 icvMake2DPoints(srcPoint,dstPoint);
1737 Convert 2D or 3D points to 2D points
1741 for 2D just copy and maybe convert type
1743 Source and destiantion may be the same and in this case src must be 2D
1745 void icvMake2DPoints(CvMat* srcPoint,CvMat* dstPoint)
1751 CV_FUNCNAME( "icvMake2DPoints" );
1754 if( !CV_IS_MAT(srcPoint) || !CV_IS_MAT(dstPoint) )
1756 CV_ERROR(CV_StsBadPoint,"Not a matrixes");
1760 numPoint = srcPoint->cols;
1762 if( numPoint != dstPoint->cols )
1764 CV_ERROR( CV_StsBadSize, "Number of points not equal" );
1768 CV_ERROR( CV_StsBadSize, "Number of points must > 0" );
1771 if( srcPoint->rows > 3 || srcPoint->rows < 2 )
1773 CV_ERROR( CV_StsBadSize, "Number of coordinates of srcPoint must be 2 or 3" );
1776 if( dstPoint->rows != 2 )
1778 CV_ERROR( CV_StsBadSize, "Number of coordinates of dstPoint must be 2" );
1781 CV_CALL( submatx = cvCreateMat(1,numPoint,CV_64F) );
1782 CV_CALL( submaty = cvCreateMat(1,numPoint,CV_64F) );
1783 CV_CALL( submatz = cvCreateMat(1,numPoint,CV_64F) );
1792 cvGetRow( dstPoint, &subwpointsx, 0 );
1793 cvGetRow( dstPoint, &subwpointsy, 1 );
1795 cvGetRow( srcPoint, &tmpSubmatx, 0 );
1796 cvGetRow( srcPoint, &tmpSubmaty, 1 );
1798 cvConvert(&tmpSubmatx,submatx);
1799 cvConvert(&tmpSubmaty,submaty);
1801 if( srcPoint->rows == 3 )
1803 cvGetRow( srcPoint, &tmpSubmatz, 2 );
1804 cvConvert(&tmpSubmatz,submatz);
1806 cvDiv( submatx, submatz, &subwpointsx);
1807 cvDiv( submaty, submatz, &subwpointsy);
1811 cvConvert(submatx,&subwpointsx);
1812 cvConvert(submaty,&subwpointsy);
1817 cvReleaseMat(&submatx);
1818 cvReleaseMat(&submaty);
1819 cvReleaseMat(&submatz);
1822 /*=====================================================================================*/
1824 void cvMake3DPoints(CvMat* srcPoint,CvMat* dstPoint)
1826 icvMake3DPoints(srcPoint,dstPoint);
1832 Convert 2D or 3D points to 3D points
1842 Source and destiantion may be the same and in this case src must be 2D
1844 void icvMake3DPoints(CvMat* srcPoint,CvMat* dstPoint)
1846 CvMat* tmpSubmatz = 0;
1848 CV_FUNCNAME( "icvMake3DPoints" );
1851 if( !CV_IS_MAT(srcPoint) || !CV_IS_MAT(dstPoint) )
1853 CV_ERROR(CV_StsBadPoint,"Not a matrixes");
1857 numPoint = srcPoint->cols;
1859 if( numPoint != dstPoint->cols )
1861 CV_ERROR( CV_StsBadSize, "Number of points not equal" );
1865 CV_ERROR( CV_StsBadSize, "Number of points must > 0" );
1868 if( srcPoint->rows > 3 || srcPoint->rows < 2 )
1870 CV_ERROR( CV_StsBadSize, "Number of coordinates of srcPoint must be 2 or 3" );
1873 if( dstPoint->rows != 3 )
1875 CV_ERROR( CV_StsBadSize, "Number of coordinates of dstPoint must be 3" );
1878 CV_CALL( tmpSubmatz = cvCreateMat(1,numPoint,CV_64F) );
1880 if( srcPoint->rows == 3 )
1882 /* Just copy all points */
1883 cvConvert(srcPoint,dstPoint);
1891 cvGetRow( dstPoint, &subwpointsx, 0 );
1892 cvGetRow( dstPoint, &subwpointsy, 1 );
1893 cvGetRow( dstPoint, &subwpointsz, 2 );
1898 cvGetRow( srcPoint, &tmpSubmatx, 0 );
1899 cvGetRow( srcPoint, &tmpSubmaty, 1 );
1901 cvConvert( &tmpSubmatx, &subwpointsx );
1902 cvConvert( &tmpSubmaty, &subwpointsy );
1906 for( i = 0; i < numPoint; i++ )
1908 cvmSet(&subwpointsz,0,i,1.0);
1914 cvReleaseMat(&tmpSubmatz);
1917 /*=====================================================================================*/
1918 void cvComputeCorrespondEpilines(CvMat* points,int pointImageID,CvMat* fundMatr,CvMat* corrLines)
1920 icvComputeCorrespondEpilines(points, pointImageID, fundMatr, corrLines);
1923 /*=====================================================================================*/
1924 void icvComputeCorrespondEpilines(CvMat* points,int pointImageID,CvMat* fundMatr,CvMat* corrLines)
1928 CvMat* wcorrLines = 0;
1930 pointImageID = 3-pointImageID;
1932 CV_FUNCNAME( "icvComputeCorrespondEpilines" );
1935 /* Test correct of input data */
1937 if( !CV_IS_MAT(points) || !CV_IS_MAT(fundMatr)|| !CV_IS_MAT(corrLines))
1939 CV_ERROR(CV_StsBadPoint,"Not a matrixes");
1945 numPoint = points->cols;
1947 if( numPoint != corrLines->cols )
1949 CV_ERROR( CV_StsBadSize, "Number of points and lines are not equal" );
1954 CV_ERROR( CV_StsBadSize, "Number of points must > 0" );
1957 if( points->rows != 2 && points->rows != 3 )
1959 CV_ERROR( CV_StsBadSize, "Number of coordinates of points1 must be 2 or 3" );
1962 if( corrLines->rows != 3 )
1964 CV_ERROR( CV_StsBadSize, "Number of coordinates of corrLines must be 3" );
1967 if( fundMatr->rows != 3 || fundMatr->cols != 3 )
1969 CV_ERROR( CV_StsBadSize, "Size of fundMatr must be 3x3" );
1972 double wfundMatr_dat[9];
1974 wfundMatr = cvMat(3,3,CV_64F,wfundMatr_dat);
1975 cvConvert(fundMatr,&wfundMatr);
1977 if( pointImageID == 1 )
1978 {// get transformed fundamental matrix
1979 double tmpMatr_dat[9];
1981 tmpMatr = cvMat(3,3,CV_64F,tmpMatr_dat);
1982 cvConvert(fundMatr,&tmpMatr);
1983 cvTranspose(&tmpMatr,&wfundMatr);
1985 else if( pointImageID != 2 )
1987 CV_ERROR( CV_StsBadArg, "Image ID must be 1 or 2" );
1989 /* if wfundMatr we have good fundamental matrix */
1990 /* compute corr epi line for given points */
1992 CV_CALL( wpoints = cvCreateMat(3,numPoint,CV_64F) );
1993 CV_CALL( wcorrLines = cvCreateMat(3,numPoint,CV_64F) );
1996 /* if points has 2 coordinates trandform them to 3D */
1997 icvMake3DPoints(points,wpoints);
1999 cvmMul(&wfundMatr,wpoints,wcorrLines);
2001 /* normalise line coordinates */
2003 for( i = 0; i < numPoint; i++ )
2006 cvGetCol(wcorrLines,&line,i);
2008 a = cvmGet(&line,0,0);
2009 b = cvmGet(&line,1,0);
2012 cvConvertScale(&line,&line,1.0 / nv);
2014 cvConvert(wcorrLines,corrLines);
2019 cvReleaseMat(&wpoints);
2020 cvReleaseMat(&wcorrLines);
2024 /*=====================================================================================*/
2026 #define SIGN(x) ( (x)<0 ? -1:((x)>0?1:0 ) )
2027 //#define REAL_ZERO(x) ( (x) < EPSILON && (x) > -EPSILON)
2028 #define REAL_ZERO(x) ( (x) < 1e-8 && (x) > -1e-8)
2030 /* function return squares for cubic equation. 6 params - two for each square (Re,Im) */
2032 icvCubicV( double a2, double a1, double a0, double *squares )
2034 double p, q, D, c1, c2, b1, b2, ro1, ro2, fi1, fi2;
2039 return CV_BADFACTOR_ERR;
2041 if( fabs(a0) > FLT_MAX || fabs(a1) > FLT_MAX || fabs(a2) > FLT_MAX )
2043 return 0;//Coeffs too big
2047 p = a1 - a2 * a2 / 3;
2048 q = (9 * a1 * a2 - 27 * a0 - 2 * a2 * a2 * a2) / 27;
2049 D = q * q / 4 + p * p * p / 27;
2051 if( fabs(p) > FLT_MAX || fabs(q) > FLT_MAX || fabs(D) > FLT_MAX )
2053 return 0;//Coeffs too big
2064 ro1 = sqrt( c1 * c1 - D );
2067 fi1 = atan2( b1, c1 );
2073 c1 = q / 2 + sqrt( D );
2074 c2 = q / 2 - sqrt( D );
2080 fi1 = CV_PI * (1 - SIGN( c1 )) / 2;
2081 fi2 = CV_PI * (1 - SIGN( c2 )) / 2;
2084 for( i = 0; i < 6; i++ )
2091 squares[i] = x[i][i % 2];
2094 if( !REAL_ZERO( ro1 ))
2097 c1 = SIGN( ro1 ) * pow( fabs( ro1 ), 1. / 3 ) -
2098 SIGN( ro1 ) * p / 3. * pow( fabs( ro1 ), -1. / 3 );
2100 c2 = SIGN( ro1 ) * pow( fabs( ro1 ), 1. / 3 ) +
2101 SIGN( ro1 ) * p / 3. * pow( fabs( ro1 ), -1. / 3 );
2104 if( !REAL_ZERO( ro2 ))
2107 b1 = SIGN( ro2 ) * pow( fabs( ro2 ), 1. / 3 ) -
2108 SIGN( ro2 ) * p / 3. * pow( fabs( ro2 ), -1. / 3 );
2110 b2 = SIGN( ro2 ) * pow( fabs( ro2 ), 1. / 3 ) +
2111 SIGN( ro2 ) * p / 3. * pow( fabs( ro2 ), -1. / 3 );
2114 for( i = 0; i < 6; i++ )
2120 if( !REAL_ZERO( ro1 ))
2123 x[i][0] = cos( fi1 / 3. + 2 * CV_PI * (i % 3) / 3. ) * c1 - a2 / 3;
2124 x[i][1] = sin( fi1 / 3. + 2 * CV_PI * (i % 3) / 3. ) * c2;
2135 if( !REAL_ZERO( ro2 ))
2138 x[i][0] = cos( fi2 / 3. + 2 * CV_PI * (i % 3) / 3. ) * b1 - a2 / 3;
2139 x[i][1] = sin( fi2 / 3. + 2 * CV_PI * (i % 3) / 3. ) * b2;
2152 for( i = 0; i < 6 && t < 6; i++ )
2158 squares[t++] = x[i][0];
2159 squares[t++] = x[i][1];
2162 for( j = i + 1; j < 6; j++ )
2163 {/* delete equal root from rest */
2165 if( !x[j][2] && REAL_ZERO( x[i][0] - x[j][0] )
2166 && REAL_ZERO( x[i][1] - x[j][1] ))
2178 /*=====================================================================================*/
2188 /* Obsolete functions. Just for ViewMorping */
2189 /*=====================================================================================*/
2192 icvGaussMxN( double *A, double *B, int M, int N, double **solutions )
2195 int row, swapi, i, i_best = 0, j, j_best = 0, t;
2196 double swapd, ratio, bigest;
2198 if( !A || !B || !M || !N )
2201 variables = (int *) icvAlloc( (long) N * sizeof( int ));
2203 if( variables == 0 )
2206 for( i = 0; i < N; i++ )
2211 /* ----- Direct way ----- */
2213 for( row = 0; row < M; row++ )
2218 for( j = row; j < M; j++ )
2219 { /* search non null element */
2220 for( i = row; i < N; i++ )
2223 if( fabs( A[j * N + i] ) > fabs( bigest ))
2225 bigest = A[j * N + i];
2232 if( REAL_ZERO( bigest ))
2233 break; /* if all shank elements are null */
2238 for( t = 0; t < N; t++ )
2241 swapd = A[row * N + t];
2242 A[row * N + t] = A[j_best * N + t];
2243 A[j_best * N + t] = swapd;
2254 for( t = 0; t < M; t++ )
2255 { /* swap a columns */
2257 swapd = A[t * N + i_best];
2258 A[t * N + i_best] = A[t * N + row];
2259 A[t * N + row] = swapd;
2262 swapi = variables[row];
2263 variables[row] = variables[i_best];
2264 variables[i_best] = swapi;
2267 for( i = row + 1; i < M; i++ )
2268 { /* recounting A and B */
2270 ratio = -A[i * N + row] / A[row * N + row];
2271 B[i] += B[row] * ratio;
2273 for( j = N - 1; j >= row; j-- )
2276 A[i * N + j] += A[row * N + j] * ratio;
2282 { /* if rank(A)<M */
2284 for( j = row; j < M; j++ )
2286 if( !REAL_ZERO( B[j] ))
2289 icvFree( &variables );
2290 return -1; /* if system is antithetic */
2294 M = row; /* decreasing size of the task */
2297 /* ----- Reverse way ----- */
2300 { /* if solution are not exclusive */
2302 *solutions = (double *) icvAlloc( ((N - M + 1) * N) * sizeof( double ));
2304 if( *solutions == 0 )
2306 icvFree( &variables );
2311 for( t = M; t <= N; t++ )
2313 for( j = M; j < N; j++ )
2316 (*solutions)[(t - M) * N + variables[j]] = (double) (t == j);
2319 for( i = M - 1; i >= 0; i-- )
2320 { /* finding component of solution */
2324 (*solutions)[(t - M) * N + variables[i]] = 0;
2328 (*solutions)[(t - M) * N + variables[i]] = B[i] / A[i * N + i];
2331 for( j = i + 1; j < N; j++ )
2334 (*solutions)[(t - M) * N + variables[i]] -=
2335 (*solutions)[(t - M) * N + variables[j]] * A[i * N + j] / A[i * N + i];
2340 icvFree( &variables );
2344 *solutions = (double *) icvAlloc( (N) * sizeof( double ));
2346 if( solutions == 0 )
2349 for( i = N - 1; i >= 0; i-- )
2350 { /* finding exclusive solution */
2352 (*solutions)[variables[i]] = B[i] / A[i * N + i];
2354 for( j = i + 1; j < N; j++ )
2357 (*solutions)[variables[i]] -=
2358 (*solutions)[variables[j]] * A[i * N + j] / A[i * N + i];
2362 icvFree( &variables );
2367 /*=====================================================================================*/
2370 icvGetCoof( double *f1, double *f2, double *a2, double *a1, double *a0 )
2375 if( !f1 || !f2 || !a0 || !a1 || !a2 )
2376 return CV_BADFACTOR_ERR;
2378 for( i = 0; i < 9; i++ )
2381 G[i] = f1[i] - f2[i];
2386 if( REAL_ZERO( a3 ))
2387 return CV_BADFACTOR_ERR;
2393 for( i = 0; i < 9; i++ )
2396 *a2 += f2[i] * icvMinor( G, (int) (i % 3), (int) (i / 3) );
2397 *a1 += G[i] * icvMinor( f2, (int) (i % 3), (int) (i / 3) );
2410 /*======================================================================================*/
2412 /*F///////////////////////////////////////////////////////////////////////////////////////
2427 // CV_NO_ERR if all Ok or error code
2432 icvLMedS7( int *points1, int *points2, CvMatrix3 * matrix )
2433 { /* Incorrect realization */
2434 CvStatus error = CV_NO_ERR;
2441 /* error = cs_Point7( points1, points2, matrix ); */
2442 /* error = icvPoint7 ( points1, points2, matrix,&amount ); */
2448 /*======================================================================================*/
2450 /*F///////////////////////////////////////////////////////////////////////////////////////
2465 // CV_NO_ERR if all Ok or error code
2470 icvPoint7( int *ml, int *mr, double *F, int *amount )
2481 CvStatus error = CV_BADFACTOR_ERR;
2483 /* F = (float*)matrix->m; */
2485 if( !ml || !mr || !F )
2486 return CV_BADFACTOR_ERR;
2488 for( i = 0; i < 7; i++ )
2490 for( j = 0; j < 9; j++ )
2493 A[i * 9 + j] = (double) ml[i * 3 + j / 3] * (double) mr[i * 3 + j % 3];
2500 if( icvGaussMxN( A, B, 7, 9, &solutions ) == 2 )
2502 if( icvGetCoef( solutions, solutions + 9, &a2, &a1, &a0 ) == CV_NO_ERR )
2504 icvCubic( a2, a1, a0, squares );
2506 for( i = 0; i < 1; i++ )
2509 if( REAL_ZERO( squares[i * 2 + 1] ))
2512 for( j = 0; j < 9; j++ )
2515 F[*amount + j] = (float) (squares[i] * solutions[j] +
2516 (1 - squares[i]) * solutions[j + 9]);
2525 icvFree( &solutions );
2530 icvFree( &solutions );
2536 icvFree( &solutions );