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 static int icvComputeFundamental7Point(CvMat* points1,CvMat* points2,
52 static int icvComputeFundamental8Point(CvMat* points1,CvMat* points2,
56 static 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 static 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 static void icvMakeFundamentalSingular(CvMat* fundMatr);
70 static void icvNormalizeFundPoints( CvMat* points,
73 static void icvMake2DPoints(CvMat* srcPoint,CvMat* dstPoint);
75 static void icvMake3DPoints(const CvMat* srcPoint,CvMat* dstPoint);
77 static int icvCubicV( double a2, double a1, double a0, double *squares );
79 /*=====================================================================================*/
81 /*F///////////////////////////////////////////////////////////////////////////////////////
82 // Name: cvFindFundamentalMat
83 // Purpose: find fundamental matrix for given points using
86 // points1 - points on first image. Size of matrix 2xN or 3xN
87 // points2 - points on second image Size of matrix 2xN or 3xN
88 // fundMatr - found fundamental matrix (or matrixes for 7-point). Size 3x3 or 9x3
89 // method - method for computing fundamental matrix
90 // CV_FM_7POINT - for 7-point algorithm. Number of points == 7
91 // CV_FM_8POINT - for 8-point algorithm. Number of points >= 8
92 // CV_FM_RANSAC - for RANSAC algorithm. Number of points >= 8
93 // CV_FM_LMEDS - for LMedS algorithm. Number of points >= 8
94 // param1 and param2 uses for RANSAC method
95 // param1 - threshold distance from point to epipolar line.
96 // If distance less than threshold point is good.
97 // param2 - probability. Usually = 0.99
98 // status - array, every element of which will be set to 1 if the point was good
99 // and used for computation. 0 else. (for RANSAC and LMedS only)
100 // (it is optional parameter, can be NULL)
103 // number of found matrixes
106 cvFindFundamentalMat( CvMat* points1,
116 CvMat* wpoints[2]={0,0};
117 CvMat* tmpPoints[2]={0,0};
119 CV_FUNCNAME( "icvComputeFundamentalMat" );
122 tmpPoints[0] = points1;
123 tmpPoints[1] = points2;
124 int numRealPoints[2];
127 /* work with points */
130 for( i = 0; i < 2; i++ )
133 realW = tmpPoints[i]->cols;
134 realH = tmpPoints[i]->rows;
137 goodW = realW > realH ? realW : realH;
138 goodH = realW < realH ? realW : realH;
140 if( goodH != 2 && goodH != 3 )
142 CV_ERROR(CV_StsBadPoint,"Number of coordinates of points must be 2 or 3");
145 wpoints[i] = cvCreateMat(2,goodW,CV_64F);
147 numRealPoints[i] = goodW;
149 /* Test for transpose point matrix */
151 {/* need to transpose point matrix */
152 CvMat* tmpPointMatr = 0;
153 tmpPointMatr = cvCreateMat(goodH,goodW,CV_64F);
154 cvTranspose(tmpPoints[i],tmpPointMatr);
155 cvMake2DPoints(tmpPointMatr,wpoints[i]);
156 cvReleaseMat(&tmpPointMatr);
160 cvMake2DPoints(tmpPoints[i],wpoints[i]);
165 if( numRealPoints[0] != numRealPoints[1] )
167 CV_ERROR(CV_StsBadPoint,"Number of points must be the same");
170 numPoints = numRealPoints[0];
173 /* work with status if use functions which don't compute it */
174 if( status && (method == CV_FM_7POINT || method == CV_FM_8POINT ))
177 if( !CV_IS_MAT(status) )
179 CV_ERROR(CV_StsBadPoint,"status is not a matrix");
183 if( !CV_IS_MAT(points1))
185 CV_ERROR(CV_StsBadPoint,"Points1 not a matrix");
188 if( status->cols != numPoints || status->rows != 1 )
190 CV_ERROR(CV_StsBadPoint,"Size of status must be 1xN");
194 for( i = 0; i < status->cols; i++)
196 cvmSet(status,0,i,1.0);
204 case CV_FM_7POINT: result = icvComputeFundamental7Point(wpoints[1], wpoints[0], fundMatr);break;
206 case CV_FM_8POINT: result = icvComputeFundamental8Point(wpoints[1],wpoints[0], fundMatr);break;
208 case CV_FM_LMEDS : result = icvComputeFundamentalLMedS( wpoints[1],wpoints[0], fundMatr,
209 param1,param2,status);break;
211 case CV_FM_RANSAC: result = icvComputeFundamentalRANSAC( wpoints[1],wpoints[0], fundMatr,
212 param1,param2,status);break;
214 //default:return -1/*ERROR*/;
219 cvReleaseMat(&wpoints[0]);
220 cvReleaseMat(&wpoints[1]);
225 /*=====================================================================================*/
227 /* Computes 1 or 3 fundamental matrixes using 7-point algorithm */
228 static int icvComputeFundamental7Point(CvMat* points1, CvMat* points2, CvMat* fundMatr)
234 CV_FUNCNAME( "icvComputeFundamental7Point" );
237 /* Test correct of input data */
239 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2)|| !CV_IS_MAT(fundMatr))
241 CV_ERROR(CV_StsBadPoint,"Not a matrixes");
244 if( !CV_ARE_TYPES_EQ( points1, points2 ))
246 CV_ERROR( CV_StsUnmatchedSizes, "Data types of points unmatched" );
250 numPoint = points1->cols;
253 type = points1->type;*/
255 if( numPoint != points2->cols )
257 CV_ERROR( CV_StsBadSize, "Number of points not equal" );
261 CV_ERROR( CV_StsBadSize, "Number of points must be 7" );
264 if( points1->rows != 2 && points1->rows != 3 )
266 CV_ERROR( CV_StsBadSize, "Number of coordinates of points1 must be 2 or 3" );
269 if( points2->rows != 2 && points2->rows != 3 )
271 CV_ERROR( CV_StsBadSize, "Number of coordinates of points2 must be 2 or 3" );
274 if( ( fundMatr->rows != 3 && fundMatr->rows != 9 )|| fundMatr->cols != 3 )
276 CV_ERROR( CV_StsBadSize, "Size of fundMatr must be 3x3 or 9x3" );
279 squares = cvCreateMat(2,3,CV_64F);
282 /* Make it Normalize points if need */
283 double wPoints1_dat[2*7];
284 double wPoints2_dat[2*7];
287 wPoints1 = cvMat(2,7,CV_64F,wPoints1_dat);
288 wPoints2 = cvMat(2,7,CV_64F,wPoints2_dat);
290 icvMake2DPoints(points1,&wPoints1);
291 icvMake2DPoints(points2,&wPoints2);
297 double matrU_dat[7*9];
298 matrU = cvMat(7,9,CV_64F,matrU_dat);
300 double* currDataLine;
301 currDataLine = matrU_dat;
302 for( currPoint = 0; currPoint < 7; currPoint++ )
305 x1 = cvmGet(&wPoints1,0,currPoint);
306 y1 = cvmGet(&wPoints1,1,currPoint);
307 x2 = cvmGet(&wPoints2,0,currPoint);
308 y2 = cvmGet(&wPoints2,1,currPoint);
310 currDataLine[0] = x1*x2;
311 currDataLine[1] = x1*y2;
312 currDataLine[2] = x1;
313 currDataLine[3] = y1*x2;
314 currDataLine[4] = y1*y2;
315 currDataLine[5] = y1;
316 currDataLine[6] = x2;
317 currDataLine[7] = y2;
326 double matrUU_dat[7*7];
327 double matrSS_dat[7*9];
328 double matrVV_dat[9*9];
329 matrUU = cvMat(7,7,CV_64F,matrUU_dat);
330 matrSS = cvMat(7,9,CV_64F,matrSS_dat);
331 matrVV = cvMat(9,9,CV_64F,matrVV_dat);
333 cvSVD( &matrU, &matrSS, &matrUU, &matrVV, 0/*CV_SVD_V_T*/ );/* get transposed matrix V */
335 double F111,F112,F113;
336 double F121,F122,F123;
337 double F131,F132,F133;
339 double F211,F212,F213;
340 double F221,F222,F223;
341 double F231,F232,F233;
343 F111=cvmGet(&matrVV,0,7);
344 F112=cvmGet(&matrVV,1,7);
345 F113=cvmGet(&matrVV,2,7);
346 F121=cvmGet(&matrVV,3,7);
347 F122=cvmGet(&matrVV,4,7);
348 F123=cvmGet(&matrVV,5,7);
349 F131=cvmGet(&matrVV,6,7);
350 F132=cvmGet(&matrVV,7,7);
351 F133=cvmGet(&matrVV,8,7);
353 F211=cvmGet(&matrVV,0,8);
354 F212=cvmGet(&matrVV,1,8);
355 F213=cvmGet(&matrVV,2,8);
356 F221=cvmGet(&matrVV,3,8);
357 F222=cvmGet(&matrVV,4,8);
358 F223=cvmGet(&matrVV,5,8);
359 F231=cvmGet(&matrVV,6,8);
360 F232=cvmGet(&matrVV,7,8);
361 F233=cvmGet(&matrVV,8,8);
365 a = F231*F112*F223 + F231*F212*F123 - F231*F212*F223 + F231*F113*F122 -
366 F231*F113*F222 - F231*F213*F122 + F231*F213*F222 - F131*F112*F223 -
367 F131*F212*F123 + F131*F212*F223 - F131*F113*F122 + F131*F113*F222 +
368 F131*F213*F122 - F131*F213*F222 + F121*F212*F133 - F121*F212*F233 +
369 F121*F113*F132 - F121*F113*F232 - F121*F213*F132 + F121*F213*F232 +
370 F221*F112*F133 - F221*F112*F233 - F221*F212*F133 + F221*F212*F233 -
371 F221*F113*F132 + F221*F113*F232 + F221*F213*F132 - F221*F213*F232 +
372 F121*F112*F233 - F111*F222*F133 + F111*F222*F233 - F111*F123*F132 +
373 F111*F123*F232 + F111*F223*F132 - F111*F223*F232 - F211*F122*F133 +
374 F211*F122*F233 + F211*F222*F133 - F211*F222*F233 + F211*F123*F132 -
375 F211*F123*F232 - F211*F223*F132 + F211*F223*F232 + F111*F122*F133 -
376 F111*F122*F233 - F121*F112*F133 + F131*F112*F123 - F231*F112*F123;
378 b = 2*F231*F213*F122 - 3*F231*F213*F222 + F231*F112*F123 - 2*F231*F112*F223 -
379 2*F231*F212*F123 + 3*F231*F212*F223 - F231*F113*F122 + 2*F231*F113*F222 +
380 F131*F212*F123 - 2*F131*F212*F223 - F131*F113*F222 - F131*F213*F122 +
381 2*F131*F213*F222 + F121*F113*F232 + F121*F213*F132 - 2*F121*F213*F232 -
382 F221*F112*F133 + 2*F221*F112*F233 + 2*F221*F212*F133 - 3*F221*F212*F233 +
383 F221*F113*F132 - 2*F221*F113*F232 - 2*F221*F213*F132 + 3*F221*F213*F232 +
384 F131*F112*F223 - 2*F211*F122*F233 - 2*F211*F222*F133 + 3*F211*F222*F233 -
385 F211*F123*F132 + 2*F211*F123*F232 + 2*F211*F223*F132 - 3*F211*F223*F232 -
386 F121*F112*F233 - F121*F212*F133 + 2*F121*F212*F233 - 2*F111*F222*F233 -
387 F111*F123*F232 - F111*F223*F132 + 2*F111*F223*F232 + F111*F122*F233 +
388 F111*F222*F133 + F211*F122*F133;
390 c = F231*F112*F223 + F231*F212*F123 - 3*F231*F212*F223 - F231*F113*F222 -
391 F231*F213*F122 + 3*F231*F213*F222 + F131*F212*F223 - F131*F213*F222 +
392 F121*F213*F232 - F221*F112*F233 - F221*F212*F133 + 3*F221*F212*F233 +
393 F221*F113*F232 + F221*F213*F132 - 3*F221*F213*F232 + F211*F122*F233 +
394 F211*F222*F133 - 3*F211*F222*F233 - F211*F123*F232 - F211*F223*F132 +
395 3*F211*F223*F232 - F121*F212*F233 + F111*F222*F233 - F111*F223*F232;
397 d = F221*F213*F232 - F211*F223*F232 + F211*F222*F233 - F221*F212*F233 +
398 F231*F212*F223 - F231*F213*F222;
401 double coeffs_dat[4];
403 coeffs = cvMat(1,4,CV_64F,coeffs_dat);
405 cvmSet(&coeffs,0,0,a);
406 cvmSet(&coeffs,0,1,b);
407 cvmSet(&coeffs,0,2,c);
408 cvmSet(&coeffs,0,3,d);
411 numCubRoots = cvSolveCubic(&coeffs,squares);
413 /* take real solution */
414 /* Need test all roots */
417 for( i = 0; i < numCubRoots; i++ )
419 if( fabs(cvmGet(squares,1,i)) < 1e-8 )
420 {//It is real square. (Im==0)
423 sol = cvmGet(squares,0,i);
424 //F=sol*F1+(1-sol)*F2;
427 for( t = 0; t < 9; t++ )
430 f1 = cvmGet(&matrVV,t,7);
431 f2 = cvmGet(&matrVV,t,8);
433 double s = f1 * sol + (1-sol) * f2;
434 cvmSet(fundMatr,numberRoots*3 + t/3,t%3,s);
438 if( fundMatr->rows == 3 )/* not enough space to store more than one root */
443 /* scale fundamental matrix */
444 for( i = 0; i < numberRoots; i++ )
448 fsc = cvmGet(fundMatr,i*3+2,2);
449 if( fabs(fsc) > 1e-8 )
452 cvGetSubArr( fundMatr, &subFund, cvRect(0,i*3,3,3) );
453 cvScale(&subFund,&subFund,1.0/fsc);
459 cvReleaseMat(&squares);
466 /*=====================================================================================*/
468 static int icvComputeFundamental8Point(CvMat* points1,CvMat* points2, CvMat* fundMatr)
470 CvMat* wpoints[2]={0,0};
471 CvMat* preFundMatr = 0;
478 int numFundMatrs = 0;
480 CV_FUNCNAME( "icvComputeFundamental8Point" );
483 /* Test correct of input data */
485 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2)|| !CV_IS_MAT(fundMatr))
487 CV_ERROR(CV_StsBadPoint,"Not a matrixes");
490 if( !CV_ARE_TYPES_EQ( points1, points2 ))
492 CV_ERROR( CV_StsUnmatchedSizes, "Data types of points unmatched" );
496 numPoint = points1->cols;
499 type = points1->type;*/
501 if( numPoint != points2->cols )
503 CV_ERROR( CV_StsBadSize, "Number of points not equal" );
507 CV_ERROR( CV_StsBadSize, "Number of points must be at least 8" );
510 if( points1->rows > 3 || points1->rows < 2 )
512 CV_ERROR( CV_StsBadSize, "Number of coordinates of points1 must be 2 or 3" );
515 if( points2->rows > 3 || points2->rows < 2 )
517 CV_ERROR( CV_StsBadSize, "Number of coordinates of points2 must be 2 or 3" );
520 if( fundMatr->rows != 3 || fundMatr->cols != 3 )
522 CV_ERROR( CV_StsBadSize, "Size of fundMatr must be 3x3" );
526 CV_CALL( wpoints[0] = cvCreateMat(2,numPoint,CV_64F) );
527 CV_CALL( wpoints[1] = cvCreateMat(2,numPoint,CV_64F) );
528 CV_CALL( matrA = cvCreateMat(numPoint,9,CV_64F) );
529 CV_CALL( preFundMatr = cvCreateMat(3,3,CV_64F) );
530 CV_CALL( matrU = cvCreateMat(numPoint,numPoint,CV_64F) );
531 CV_CALL( matrW = cvCreateMat(numPoint,9,CV_64F) );
532 CV_CALL( matrV = cvCreateMat(9,9,CV_64F) );
533 CV_CALL( sqdists = cvCreateMat(1,numPoint,CV_64F) );
535 /* Create working points with just x,y */
538 double transfMatr1_dat[9];
539 double transfMatr2_dat[9];
540 transfMatr[0] = cvMat(3,3,CV_64F,transfMatr1_dat);
541 transfMatr[1] = cvMat(3,3,CV_64F,transfMatr2_dat);
543 {/* transform to x,y. tranform point and compute transform matrixes */
544 icvMake2DPoints(points1,wpoints[0]);
545 icvMake2DPoints(points2,wpoints[1]);
547 icvNormalizeFundPoints( wpoints[0],&transfMatr[0]);
548 icvNormalizeFundPoints( wpoints[1],&transfMatr[1]);
550 /* we have normalized working points wpoints[0] and wpoints[1] */
551 /* build matrix A from points coordinates */
554 for( currPoint = 0; currPoint < numPoint; currPoint++ )
560 x1 = cvmGet(wpoints[0],0,currPoint);
561 y1 = cvmGet(wpoints[0],1,currPoint);
562 x2 = cvmGet(wpoints[1],0,currPoint);
563 y2 = cvmGet(wpoints[1],1,currPoint);
565 cvGetRow(matrA,&rowA,currPoint);
566 rowA.data.db[0] = x1*x2;
567 rowA.data.db[1] = x1*y2;
568 rowA.data.db[2] = x1;
570 rowA.data.db[3] = y1*x2;
571 rowA.data.db[4] = y1*y2;
572 rowA.data.db[5] = y1;
574 rowA.data.db[6] = x2;
575 rowA.data.db[7] = y2;
580 /* We have matrix A. Compute svd(A). We need last column of V */
583 cvSVD( matrA, matrW, matrU, matrV, CV_SVD_V_T );/* get transposed matrix V */
585 /* Compute number of non zero eigen values */
590 for( i = 0; i < 8; i++ )
592 if( cvmGet(matrW,i,i) < 1e-8 )
610 /* copy last row of matrix V to precomputed fundamental matrix */
613 cvGetRow(matrV,&preF,8);
614 cvReshape(&preF,preFundMatr,1,3);
616 /* Apply singularity condition */
617 icvMakeFundamentalSingular(preFundMatr);
619 /* Denormalize fundamental matrix */
620 /* Compute transformation for normalization */
623 double wfundMatr_dat[9];
624 wfundMatr = cvMat(3,3,CV_64F,wfundMatr_dat);
626 {/* Freal = T1'*Fpre*T2 */
627 double tmpMatr_dat[9];
628 double tmptransfMatr_dat[9];
630 CvMat tmpMatr = cvMat(3,3,CV_64F,tmpMatr_dat);
631 CvMat tmptransfMatr = cvMat(3,3,CV_64F,tmptransfMatr_dat);
633 cvTranspose(&transfMatr[0],&tmptransfMatr);
635 cvMatMul(&tmptransfMatr,preFundMatr,&tmpMatr);
636 cvMatMul(&tmpMatr,&transfMatr[1],&wfundMatr);
639 /* scale fundamental matrix */
641 fsc = cvmGet(&wfundMatr,2,2);
642 if( fabs(fsc) > 1.0e-8 )
644 cvScale(&wfundMatr,&wfundMatr,1.0/fsc);
647 /* copy result fundamental matrix */
648 cvConvert( &wfundMatr, fundMatr );
655 cvReleaseMat(&matrU);
656 cvReleaseMat(&matrW);
657 cvReleaseMat(&matrV);
658 cvReleaseMat(&preFundMatr);
659 cvReleaseMat(&matrA);
660 cvReleaseMat(&wpoints[0]);
661 cvReleaseMat(&wpoints[1]);
662 cvReleaseMat(&sqdists);
667 /*=====================================================================================*/
669 /* Computes fundamental matrix using RANSAC method */
671 static int icvComputeFundamentalRANSAC( CvMat* points1,CvMat* points2,
673 double threshold,/* Threshold for good points */
674 double p,/* Probability of good result. */
679 CvMat* corrLines1 = 0;
680 CvMat* corrLines2 = 0;
681 CvMat* bestPoints1 = 0;
682 CvMat* bestPoints2 = 0;
688 CV_FUNCNAME( "icvComputeFundamentalRANSAC" );
691 /* Test correct of input data */
693 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2)|| !CV_IS_MAT(fundMatr))
695 CV_ERROR(CV_StsBadPoint,"points1 or points2 or funMatr are not a matrixes");
699 numPoint = points1->cols;
702 type = points1->type;*/
704 if( numPoint != points2->cols )
706 CV_ERROR( CV_StsBadSize, "Number of points not equals" );
710 CV_ERROR( CV_StsBadSize, "Number of points must be >= 8" );
713 if( points1->rows != 2 && points1->rows != 3 )
715 CV_ERROR( CV_StsBadSize, "Number of coordinates of points1 must be 2 or 3" );
718 if( points2->rows != 2 && points2->rows != 3 )
720 CV_ERROR( CV_StsBadSize, "Number of coordinates of points2 must be 2 or 3" );
723 if( fundMatr->rows != 3 || fundMatr->cols != 3 )
725 CV_ERROR( CV_StsBadSize, "Size of fundMatr must be 3x3" );
729 {/* status is present test it */
730 if( !CV_IS_MAT(status) )
732 CV_ERROR(CV_StsBadPoint,"status is not a matrix");
735 if( status->cols != numPoint || status->rows != 1 )
737 CV_ERROR(CV_StsBadPoint,"Size of status must be 1xN");
741 /* We will choose adaptive number of N (samples) */
743 /* Convert points to 64F working points */
745 CV_CALL( flags = (int*)cvAlloc(numPoint * sizeof(int)) );
746 CV_CALL( bestFlags = (int*)cvAlloc(numPoint * sizeof(int)) );
747 CV_CALL( wpoints1 = cvCreateMat(3,numPoint,CV_64F) );
748 CV_CALL( wpoints2 = cvCreateMat(3,numPoint,CV_64F) );
749 CV_CALL( corrLines1 = cvCreateMat(3,numPoint,CV_64F));
750 CV_CALL( corrLines2 = cvCreateMat(3,numPoint,CV_64F));
751 CV_CALL( bestPoints1 = cvCreateMat(3,numPoint,CV_64F));
752 CV_CALL( bestPoints2 = cvCreateMat(3,numPoint,CV_64F));
754 icvMake3DPoints(points1,wpoints1);
755 icvMake3DPoints(points2,wpoints2);
758 int wasCount = 0; //count of choosing samples
759 int maxGoodPoints = 0;
760 int numGoodPoints = 0;
762 double bestFund_dat[9];
764 bestFund = cvMat(3,3,CV_64F,bestFund_dat);
767 int NumSamples = 500;/* Initial need number of samples */
768 while( wasCount < NumSamples )
775 for( i = 0; i < 7; i++ )
779 newnum = rand()%numPoint;
781 /* test this number */
784 for( test = 0; test < i; test++ )
786 if( randNumbs[test] == newnum )
794 randNumbs[i] = newnum;
796 /* random numbers of points was generated */
799 double selPoints1_dat[2*7];
800 double selPoints2_dat[2*7];
803 selPoints1 = cvMat(2,7,CV_64F,selPoints1_dat);
804 selPoints2 = cvMat(2,7,CV_64F,selPoints2_dat);
807 for( t = 0; t < 7; t++ )
810 x = cvmGet(wpoints1,0,randNumbs[t]);
811 y = cvmGet(wpoints1,1,randNumbs[t]);
812 cvmSet(&selPoints1,0,t,x);
813 cvmSet(&selPoints1,1,t,y);
815 x = cvmGet(wpoints2,0,randNumbs[t]);
816 y = cvmGet(wpoints2,1,randNumbs[t]);
817 cvmSet(&selPoints2,0,t,x);
818 cvmSet(&selPoints2,1,t,y);
821 /* Compute fundamental matrix using 7-points algorithm */
823 double fundTriple_dat[27];
825 fundTriple = cvMat(9,3,CV_64F,fundTriple_dat);
827 int numFund = icvComputeFundamental7Point(&selPoints1,&selPoints2,&fundTriple);
829 //double fund7_dat[9];
831 //fund7 = cvMat(3,3,CV_64F,fund7_dat);
834 for( int currFund = 0; currFund < numFund; currFund++ )
836 cvGetSubArr(&fundTriple,&fund7,cvRect(0,currFund*3,3,3));
838 /* Compute inliers for this fundamental matrix */
839 /* Compute distances for points and correspond lines */
841 /* Create corresponde lines */
843 cvComputeCorrespondEpilines(wpoints1,2,&fund7,corrLines2);
844 cvComputeCorrespondEpilines(wpoints2,1,&fund7,corrLines1);
845 /* compute distances for points and number of good points */
848 for( i = 0; i < numPoint; i++ )
852 cvGetCol(wpoints1,&pnt1,i);
853 cvGetCol(corrLines1,&lin1,i);
854 cvGetCol(wpoints2,&pnt2,i);
855 cvGetCol(corrLines2,&lin2,i);
857 dist1 = fabs(cvDotProduct(&pnt1,&lin1));
858 dist2 = fabs(cvDotProduct(&pnt2,&lin2));
859 flags[i] = ( dist1 < threshold && dist2 < threshold )?1:0;
860 numGoodPoints += flags[i];
865 if( numGoodPoints > maxGoodPoints )
867 cvCopy(&fund7,&bestFund);
868 maxGoodPoints = numGoodPoints;
869 /* copy best flags */
871 for(i=0;i<numPoint;i++)
873 bestFlags[i] = flags[i];
876 /* Recompute new number of need steps */
878 /* Adaptive number of samples to count*/
879 double ep = 1 - (double)numGoodPoints / (double)numPoint;
882 ep = 0.5;//if there is not good points set ration of outliers to 50%
885 double newNumSamples = log(1-p);
886 newNumSamples /= log(1-pow(1-ep,7));
888 if( newNumSamples < (double)NumSamples )
890 NumSamples = cvRound(newNumSamples);
899 /* we have best 7-point fundamental matrix. */
900 /* and best points */
901 /* use these points to improve matrix */
903 /* collect best points */
906 /* Test number of points. And if number >=8 improove found fundamental matrix */
908 if( maxGoodPoints < 7 )
910 /* Fundamental matrix not found */
915 if( maxGoodPoints > 7 )
917 /* Found >= 8 point. Improove matrix */
922 for( i = 0; i < numPoint; i++ )
928 cvGetCol( wpoints1,&wPnt, i );
929 cvGetCol( bestPoints1,&bestPnt, currPnt );
930 cvCopy(&wPnt,&bestPnt);
931 cvGetCol( wpoints2,&wPnt, i );
932 cvGetCol( bestPoints2,&bestPnt, currPnt );
933 cvCopy(&wPnt,&bestPnt);
941 cvGetSubArr( bestPoints1, &wbestPnts1, cvRect(0,0,maxGoodPoints,3) );
942 cvGetSubArr( bestPoints2, &wbestPnts2, cvRect(0,0,maxGoodPoints,3) );
944 /* best points was collectet. Improve fundamental matrix */
945 /* Just use 8-point algorithm */
946 double impFundMatr_dat[9];
948 impFundMatr = cvMat(3,3,CV_64F,impFundMatr_dat);
949 numFundMatr = icvComputeFundamental8Point(&wbestPnts1,&wbestPnts2,&impFundMatr);
951 cvConvert(&impFundMatr,fundMatr);
952 //cvConvert(&bestFund,fundMatr); // This line must be deleted
956 /* 7 point. Just copy to result */
957 cvConvert(&bestFund,fundMatr);
961 /* copy flag to status if need */
964 for( int i = 0; i < numPoint; i++)
966 cvmSet(status,0,i,(double)bestFlags[i]);
976 /* free allocated memory */
978 cvReleaseMat(&corrLines1);
979 cvReleaseMat(&corrLines2);
980 cvReleaseMat(&wpoints1);
981 cvReleaseMat(&wpoints2);
982 cvReleaseMat(&bestPoints1);
983 cvReleaseMat(&bestPoints2);
984 cvFree((void**)&flags);
985 cvFree((void**)&bestFlags);
988 }//icvComputeFundamentalRANSAC
990 /*=====================================================================================*/
992 static void icvCompPointLineDists(CvMat* points,CvMat* lines,CvMat* distances)
993 {/* Line must be normalized */
996 numPoints = points->cols;
997 if( numPoints != lines->cols && numPoints != distances->cols )
999 //printf("Size if arrays not equals\n");
1004 for( i = 0; i < numPoints; i++ )
1008 cvGetCol(points,&pnt,i);
1009 cvGetCol(lines,&lin,i);
1011 dist = fabs(cvDotProduct(&pnt,&lin));
1012 cvmSet(distances,0,i,dist);
1018 /*=====================================================================================*/
1022 #define _compVals( v1, v2 ) ((v1) < (v2))
1024 /* Create function to sort vector */
1025 static CV_IMPLEMENT_QSORT( _SortCvMatVect, double, _compVals )
1027 /*=====================================================================================*/
1028 static int icvComputeFundamentalLMedS( CvMat* points1,CvMat* points2,
1030 double threshold,/* Threshold for good points */
1031 double p,/* Probability of good result. */
1034 CvMat* wpoints1 = 0;
1035 CvMat* wpoints2 = 0;
1036 CvMat* corrLines1 = 0;
1037 CvMat* corrLines2 = 0;
1038 CvMat* bestPoints1 = 0;
1039 CvMat* bestPoints2 = 0;
1042 CvMat* distsSq1 = 0;
1043 CvMat* distsSq2 = 0;
1044 CvMat* allDists = 0;
1048 int numFundMatr = 0;
1050 CV_FUNCNAME( "icvComputeFundamentalLMedS" );
1053 /* Test correct of input data */
1055 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2)|| !CV_IS_MAT(fundMatr))
1057 CV_ERROR(CV_StsBadPoint,"Not a matrixes");
1061 numPoint = points1->cols;
1064 type = points1->type;*/
1066 if( numPoint != points2->cols )
1068 CV_ERROR( CV_StsBadSize, "Number of points not equal" );
1072 CV_ERROR( CV_StsBadSize, "Number of points must be >= 8" );
1075 if( points1->rows != 2 && points1->rows != 3 )
1077 CV_ERROR( CV_StsBadSize, "Number of coordinates of points1 must be 2 or 3" );
1080 if( points2->rows != 2 && points2->rows != 3 )
1082 CV_ERROR( CV_StsBadSize, "Number of coordinates of points2 must be 2 or 3" );
1085 if( fundMatr->rows != 3 || fundMatr->cols != 3 )
1087 CV_ERROR( CV_StsBadSize, "Size of fundMatr must be 3x3" );
1091 {/* status is present test it */
1092 if( !CV_IS_MAT(status) )
1094 CV_ERROR(CV_StsBadPoint,"status is not a matrix");
1097 if( status->cols != numPoint || status->rows != 1 )
1099 CV_ERROR(CV_StsBadPoint,"Size of status must be 1xN");
1103 /* We will choose adaptive number of N (samples) */
1105 /* Convert points to 64F working points */
1107 CV_CALL( flags = (int*)cvAlloc(numPoint * sizeof(int)) );
1108 CV_CALL( bestFlags = (int*)cvAlloc(numPoint * sizeof(int)) );
1109 CV_CALL( wpoints1 = cvCreateMat(3,numPoint,CV_64F) );
1110 CV_CALL( wpoints2 = cvCreateMat(3,numPoint,CV_64F) );
1111 CV_CALL( corrLines1 = cvCreateMat(3,numPoint,CV_64F));
1112 CV_CALL( corrLines2 = cvCreateMat(3,numPoint,CV_64F));
1113 CV_CALL( bestPoints1 = cvCreateMat(3,numPoint,CV_64F));
1114 CV_CALL( bestPoints2 = cvCreateMat(3,numPoint,CV_64F));
1115 CV_CALL( dists1 = cvCreateMat(1,numPoint,CV_64F));
1116 CV_CALL( dists2 = cvCreateMat(1,numPoint,CV_64F));
1117 CV_CALL( distsSq1 = cvCreateMat(1,numPoint,CV_64F));
1118 CV_CALL( distsSq2 = cvCreateMat(1,numPoint,CV_64F));
1119 CV_CALL( allDists = cvCreateMat(1,numPoint,CV_64F));
1121 icvMake3DPoints(points1,wpoints1);
1122 icvMake3DPoints(points2,wpoints2);
1125 int NumSamples = 500;//Maximux number of steps
1126 int wasCount = 0; //count of choosing samples
1128 double goodMean = FLT_MAX;
1131 int numGoodPoints = 0;
1133 double bestFund_dat[9];
1135 bestFund = cvMat(3,3,CV_64F,bestFund_dat);
1137 /* choosen points */
1138 while( wasCount < NumSamples )
1140 /* select samples */
1145 for( i = 0; i < 7; i++ )
1149 newnum = rand()%numPoint;
1151 /* test this number */
1154 for( test = 0; test < i; test++ )
1156 if( randNumbs[test] == newnum )
1164 randNumbs[i] = newnum;
1166 /* random numbers of points was generated */
1169 double selPoints1_dat[2*7];
1170 double selPoints2_dat[2*7];
1173 selPoints1 = cvMat(2,7,CV_64F,selPoints1_dat);
1174 selPoints2 = cvMat(2,7,CV_64F,selPoints2_dat);
1177 for( t = 0; t < 7; t++ )
1180 x = cvmGet(wpoints1,0,randNumbs[t]);
1181 y = cvmGet(wpoints1,1,randNumbs[t]);
1182 cvmSet(&selPoints1,0,t,x);
1183 cvmSet(&selPoints1,1,t,y);
1185 x = cvmGet(wpoints2,0,randNumbs[t]);
1186 y = cvmGet(wpoints2,1,randNumbs[t]);
1187 cvmSet(&selPoints2,0,t,x);
1188 cvmSet(&selPoints2,1,t,y);
1190 /* Compute fundamental matrix using 7-points algorithm */
1192 double fundTriple_dat[27];
1194 fundTriple = cvMat(9,3,CV_64F,fundTriple_dat);
1196 int numFund = icvComputeFundamental7Point(&selPoints1,&selPoints2,&fundTriple);
1198 //double fund7_dat[9];
1200 //fund7 = cvMat(3,3,CV_64F,fund7_dat);
1202 /* get sub matrix */
1203 for( int currFund = 0; currFund < numFund; currFund++ )
1206 cvGetSubArr(&fundTriple,&fund7,cvRect(0,currFund*3,3,3));
1208 /* Compute median error for this matrix */
1210 cvComputeCorrespondEpilines(wpoints1,2,&fund7,corrLines2);
1211 cvComputeCorrespondEpilines(wpoints2,1,&fund7,corrLines1);
1213 icvCompPointLineDists(wpoints1,corrLines1,dists1);
1214 icvCompPointLineDists(wpoints2,corrLines2,dists2);
1216 /* add distances for points (d1*d1+d2*d2) */
1217 cvMul(dists1,dists1,distsSq1);
1218 cvMul(dists2,dists2,distsSq2);
1220 cvAdd(distsSq1,distsSq2,allDists);
1222 /* sort distances */
1223 _SortCvMatVect(allDists->data.db,numPoint,0);
1225 /* get median error */
1226 currMean = allDists->data.db[numPoint/2];
1230 if( currMean < goodMean )
1232 cvCopy(&fund7,&bestFund);
1233 goodMean = currMean;
1235 /* Compute number of good points using threshold */
1238 for( i = 0 ; i < numPoint; i++ )
1240 if( dists1->data.db[i] < threshold && dists2->data.db[i] < threshold )
1247 /* Compute adaptive number of steps */
1248 double ep = 1 - (double)numGoodPoints / (double)numPoint;
1251 ep = 0.5;//if there is not good points set ration of outliers to 50%
1254 double newNumSamples = log(1-p);
1255 newNumSamples /= log(1-pow(1-ep,7));
1256 if( newNumSamples < (double)NumSamples )
1258 NumSamples = cvRound(newNumSamples);
1266 /* Select just good points using threshold */
1267 /* Compute distances for all points for best fundamental matrix */
1269 /* Test if we have computed fundamental matrix*/
1270 if( goodMean == FLT_MAX )
1276 {/* we have computed fundamental matrix */
1278 cvComputeCorrespondEpilines(wpoints1,2,&bestFund,corrLines2);
1279 cvComputeCorrespondEpilines(wpoints2,1,&bestFund,corrLines1);
1281 icvCompPointLineDists(wpoints1,corrLines1,dists1);
1282 icvCompPointLineDists(wpoints2,corrLines2,dists2);
1284 /* test dist for each point and set status for each point if need */
1287 for( i = 0; i < numPoint; i++ )
1289 if( dists1->data.db[i] < threshold && dists2->data.db[i] < threshold )
1293 cvGetCol( wpoints1,&wPnt, i );
1294 cvGetCol( bestPoints1,&bestPnt, currPnt );
1295 cvCopy(&wPnt,&bestPnt);
1296 cvGetCol( wpoints2,&wPnt, i );
1297 cvGetCol( bestPoints2,&bestPnt, currPnt );
1298 cvCopy(&wPnt,&bestPnt);
1302 cvmSet(status,0,i,1.0);
1307 cvmSet(status,0,i,0.0);
1311 numGoodPoints = currPnt;
1314 /* we have best 7-point fundamental matrix. */
1315 /* and best points */
1316 /* use these points to improove matrix */
1318 /* Test number of points. And if number >=8 improove found fundamental matrix */
1320 if( numGoodPoints < 7 )
1322 /* Fundamental matrix not found */
1327 if( numGoodPoints > 7 )
1329 /* Found >= 8 point. Improove matrix */
1334 cvGetSubArr( bestPoints1, &wbestPnts1, cvRect(0,0,numGoodPoints,3) );
1335 cvGetSubArr( bestPoints2, &wbestPnts2, cvRect(0,0,numGoodPoints,3) );
1337 /* best points was collectet. Improve fundamental matrix */
1338 /* Just use 8-point algorithm */
1339 double impFundMatr_dat[9];
1341 impFundMatr = cvMat(3,3,CV_64F,impFundMatr_dat);
1342 numFundMatr = icvComputeFundamental8Point(&wbestPnts1,&wbestPnts2,&impFundMatr);
1344 cvConvert(&impFundMatr,fundMatr);
1348 /* 7 point. Just copy to result */
1349 cvConvert(&bestFund,fundMatr);
1359 /* free allocated memory */
1361 cvReleaseMat(&corrLines1);
1362 cvReleaseMat(&corrLines2);
1363 cvReleaseMat(&wpoints1);
1364 cvReleaseMat(&wpoints2);
1365 cvReleaseMat(&bestPoints1);
1366 cvReleaseMat(&bestPoints2);
1367 cvReleaseMat(&dists1);
1368 cvReleaseMat(&dists2);
1369 cvReleaseMat(&distsSq1);
1370 cvReleaseMat(&distsSq2);
1371 cvReleaseMat(&allDists);
1372 cvFree((void**)&flags);
1373 cvFree((void**)&bestFlags);
1376 }//icvComputeFundamentalLMedS
1378 /*=====================================================================================*/
1382 static void icvMakeFundamentalSingular(CvMat* fundMatr)
1384 CV_FUNCNAME( "icvFundSingular" );
1387 if( !CV_IS_MAT(fundMatr) )
1389 CV_ERROR(CV_StsBadPoint,"Input data is not matrix");
1392 if( fundMatr->rows != 3 || fundMatr->cols != 3 )
1394 CV_ERROR( CV_StsBadSize, "Size of fundametal matrix must be 3x3" );
1398 {/* Apply singularity condition */
1404 double matrFU_dat[9];
1405 double matrFW_dat[9];
1406 double matrFVt_dat[9];
1407 double tmpMatr_dat[9];
1408 double preFundMatr_dat[9];
1411 matrFU = cvMat(3,3,CV_64F,matrFU_dat);
1412 matrFW = cvMat(3,3,CV_64F,matrFW_dat);
1413 matrFVt = cvMat(3,3,CV_64F,matrFVt_dat);
1414 tmpMatr = cvMat(3,3,CV_64F,tmpMatr_dat);
1415 preFundMatr = cvMat(3,3,CV_64F,preFundMatr_dat);
1417 cvConvert(fundMatr,&preFundMatr);
1418 cvSVD( &preFundMatr, &matrFW, &matrFU, &matrFVt, CV_SVD_V_T );
1419 cvmSet(&matrFW,2,2,0);
1420 /* multiply U*W*V' */
1422 cvMatMul(&matrFU,&matrFW,&tmpMatr);
1423 cvMatMul(&tmpMatr,&matrFVt,&preFundMatr);
1424 cvConvert(&preFundMatr,fundMatr);
1432 /*=====================================================================================*/
1433 /* Normalize points for computing fundamental matrix */
1434 /* and compute transform matrix */
1437 /* place centroid of points to (0,0) */
1438 /* set mean distance from (0,0) by sqrt(2) */
1440 static void icvNormalizeFundPoints( CvMat* points, CvMat* transfMatr )
1442 CvMat* subwpointsx = 0;
1443 CvMat* subwpointsy = 0;
1445 CvMat* pointsxx = 0;
1446 CvMat* pointsyy = 0;
1449 double shiftx,shifty;
1459 CV_FUNCNAME( "icvNormalizeFundPoints" );
1462 /* Test for correct input data */
1464 if( !CV_IS_MAT(points) || !CV_IS_MAT(transfMatr) )
1466 CV_ERROR(CV_StsBadPoint,"Input data is not matrixes");
1469 numPoint = points->cols;
1473 CV_ERROR( CV_StsBadSize, "Number of points must be at least 1" );
1476 if( points->rows != 2 )
1478 CV_ERROR( CV_StsBadSize, "Number of coordinates of points1 must be 2" );
1481 if( transfMatr->rows != 3 || transfMatr->cols != 3 )
1483 CV_ERROR( CV_StsBadSize, "Size of transform matrix must be 3x3" );
1486 CV_CALL( subwpointsx = cvCreateMat(1,numPoint,CV_64F) );
1487 CV_CALL( subwpointsy = cvCreateMat(1,numPoint,CV_64F) );
1488 CV_CALL( sqdists = cvCreateMat(1,numPoint,CV_64F) );
1489 CV_CALL( pointsxx = cvCreateMat(1,numPoint,CV_64F) );
1490 CV_CALL( pointsyy = cvCreateMat(1,numPoint,CV_64F) );
1492 /* get x,y coordinates of points */
1495 cvGetRow( points, &tmpwpointsx, 0 );
1496 cvGetRow( points, &tmpwpointsy, 1 );
1498 /* Copy to working data 64F */
1499 cvConvert(&tmpwpointsx,subwpointsx);
1500 cvConvert(&tmpwpointsy,subwpointsy);
1503 /* Compute center of points */
1505 sumx = cvSum(subwpointsx);
1506 sumy = cvSum(subwpointsy);
1508 sumx.val[0] /= (double)numPoint;
1509 sumy.val[0] /= (double)numPoint;
1511 shiftx = sumx.val[0];
1512 shifty = sumy.val[0];
1514 /* Shift points center to 0 */
1516 cvSubS( subwpointsx, sumx, subwpointsx);
1517 cvSubS( subwpointsy, sumy, subwpointsy);
1519 /* Compute x*x and y*y */
1521 cvMul(subwpointsx,subwpointsx,pointsxx);
1522 cvMul(subwpointsy,subwpointsy,pointsyy);
1525 cvAdd( pointsxx, pointsyy, sqdists);
1527 /* compute sqrt of each component*/
1529 cvPow(sqdists,sqdists,0.5);
1531 /* in vector sqdists we have distances */
1532 /* compute mean value and scale */
1534 meand = cvAvg(sqdists).val[0];
1536 if( fabs(meand) > 1e-8 )
1538 scale = 0.70710678118654752440084436210485/meand;
1545 /* scale working points */
1546 cvScale(subwpointsx,subwpointsx,scale);
1547 cvScale(subwpointsy,subwpointsy,scale);
1549 /* copy output data */
1551 cvGetRow( points, &tmpwpointsx, 0 );
1552 cvGetRow( points, &tmpwpointsy, 1 );
1554 /* Copy to output data 64F */
1555 cvConvert(subwpointsx,&tmpwpointsx);
1556 cvConvert(subwpointsy,&tmpwpointsy);
1559 /* Set transform matrix */
1561 cvmSet(transfMatr,0,0, scale);
1562 cvmSet(transfMatr,0,1, 0);
1563 cvmSet(transfMatr,0,2, -scale*shiftx);
1565 cvmSet(transfMatr,1,0, 0);
1566 cvmSet(transfMatr,1,1, scale);
1567 cvmSet(transfMatr,1,2, -scale*shifty);
1569 cvmSet(transfMatr,2,0, 0);
1570 cvmSet(transfMatr,2,1, 0);
1571 cvmSet(transfMatr,2,2, 1);
1576 cvReleaseMat(&subwpointsx);
1577 cvReleaseMat(&subwpointsy);
1578 cvReleaseMat(&sqdists);
1579 cvReleaseMat(&pointsxx);
1580 cvReleaseMat(&pointsyy);
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 CV_IMPL int cvSolveCubic(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 static 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((const CvMat*)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 static void icvMake3DPoints(const 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 /*=====================================================================================*/
1919 cvComputeCorrespondEpilines(const CvMat* points,int pointImageID,const CvMat* fundMatr,CvMat* corrLines)
1923 CvMat* wcorrLines = 0;
1925 pointImageID = 3-pointImageID;
1927 CV_FUNCNAME( "icvComputeCorrespondEpilines" );
1930 /* Test correct of input data */
1932 if( !CV_IS_MAT(points) || !CV_IS_MAT(fundMatr)|| !CV_IS_MAT(corrLines))
1934 CV_ERROR(CV_StsBadPoint,"Not a matrixes");
1940 numPoint = points->cols;
1942 if( numPoint != corrLines->cols )
1944 CV_ERROR( CV_StsBadSize, "Number of points and lines are not equal" );
1949 CV_ERROR( CV_StsBadSize, "Number of points must > 0" );
1952 if( points->rows != 2 && points->rows != 3 )
1954 CV_ERROR( CV_StsBadSize, "Number of coordinates of points1 must be 2 or 3" );
1957 if( corrLines->rows != 3 )
1959 CV_ERROR( CV_StsBadSize, "Number of coordinates of corrLines must be 3" );
1962 if( fundMatr->rows != 3 || fundMatr->cols != 3 )
1964 CV_ERROR( CV_StsBadSize, "Size of fundMatr must be 3x3" );
1967 double wfundMatr_dat[9];
1969 wfundMatr = cvMat(3,3,CV_64F,wfundMatr_dat);
1970 cvConvert(fundMatr,&wfundMatr);
1972 if( pointImageID == 1 )
1973 {// get transformed fundamental matrix
1974 double tmpMatr_dat[9];
1976 tmpMatr = cvMat(3,3,CV_64F,tmpMatr_dat);
1977 cvConvert(fundMatr,&tmpMatr);
1978 cvTranspose(&tmpMatr,&wfundMatr);
1980 else if( pointImageID != 2 )
1982 CV_ERROR( CV_StsBadArg, "Image ID must be 1 or 2" );
1984 /* if wfundMatr we have good fundamental matrix */
1985 /* compute corr epi line for given points */
1987 CV_CALL( wpoints = cvCreateMat(3,numPoint,CV_64F) );
1988 CV_CALL( wcorrLines = cvCreateMat(3,numPoint,CV_64F) );
1991 /* if points has 2 coordinates trandform them to 3D */
1992 icvMake3DPoints(points,wpoints);
1994 cvMatMul(&wfundMatr,wpoints,wcorrLines);
1996 /* normalise line coordinates */
1998 for( i = 0; i < numPoint; i++ )
2001 cvGetCol(wcorrLines,&line,i);
2003 a = cvmGet(&line,0,0);
2004 b = cvmGet(&line,1,0);
2007 cvConvertScale(&line,&line,1.0 / nv);
2009 cvConvert(wcorrLines,corrLines);
2014 cvReleaseMat(&wpoints);
2015 cvReleaseMat(&wcorrLines);
2019 /*=====================================================================================*/
2021 #define SIGN(x) ( (x)<0 ? -1:((x)>0?1:0 ) )
2022 //#define REAL_ZERO(x) ( (x) < EPSILON && (x) > -EPSILON)
2023 #define REAL_ZERO(x) ( (x) < 1e-8 && (x) > -1e-8)
2025 /* function return squares for cubic equation. 6 params - two for each square (Re,Im) */
2027 icvCubicV( double a2, double a1, double a0, double *squares )
2029 double p, q, D, c1, c2, b1, b2, ro1, ro2, fi1, fi2;
2034 return CV_BADFACTOR_ERR;
2036 if( fabs(a0) > FLT_MAX || fabs(a1) > FLT_MAX || fabs(a2) > FLT_MAX )
2038 return 0;//Coeffs too big
2042 p = a1 - a2 * a2 / 3;
2043 q = (9 * a1 * a2 - 27 * a0 - 2 * a2 * a2 * a2) / 27;
2044 D = q * q / 4 + p * p * p / 27;
2046 if( fabs(p) > FLT_MAX || fabs(q) > FLT_MAX || fabs(D) > FLT_MAX )
2048 return 0;//Coeffs too big
2059 ro1 = sqrt( c1 * c1 - D );
2062 fi1 = atan2( b1, c1 );
2068 c1 = q / 2 + sqrt( D );
2069 c2 = q / 2 - sqrt( D );
2075 fi1 = CV_PI * (1 - SIGN( c1 )) / 2;
2076 fi2 = CV_PI * (1 - SIGN( c2 )) / 2;
2079 for( i = 0; i < 6; i++ )
2086 squares[i] = x[i][i % 2];
2089 if( !REAL_ZERO( ro1 ))
2091 c1 = SIGN( ro1 ) * pow( fabs( ro1 ), 1. / 3 );
2092 c1 -= SIGN( ro1 ) * p / 3. * pow( fabs( ro1 ), -1. / 3 );
2094 c2 = SIGN( ro1 ) * pow( fabs( ro1 ), 1. / 3 );
2095 c2 += SIGN( ro1 ) * p / 3. * pow( fabs( ro1 ), -1. / 3 );
2098 if( !REAL_ZERO( ro2 ))
2100 b1 = SIGN( ro2 ) * pow( fabs( ro2 ), 1. / 3 );
2101 b1 -= SIGN( ro2 ) * p / 3. * pow( fabs( ro2 ), -1. / 3 );
2103 b2 = SIGN( ro2 ) * pow( fabs( ro2 ), 1. / 3 );
2104 b2 += SIGN( ro2 ) * p / 3. * pow( fabs( ro2 ), -1. / 3 );
2107 for( i = 0; i < 6; i++ )
2113 if( !REAL_ZERO( ro1 ))
2116 x[i][0] = cos( fi1 / 3. + 2 * CV_PI * (i % 3) / 3. ) * c1 - a2 / 3;
2117 x[i][1] = sin( fi1 / 3. + 2 * CV_PI * (i % 3) / 3. ) * c2;
2128 if( !REAL_ZERO( ro2 ))
2131 x[i][0] = cos( fi2 / 3. + 2 * CV_PI * (i % 3) / 3. ) * b1 - a2 / 3;
2132 x[i][1] = sin( fi2 / 3. + 2 * CV_PI * (i % 3) / 3. ) * b2;
2145 for( i = 0; i < 6 && t < 6; i++ )
2151 squares[t++] = x[i][0];
2152 squares[t++] = x[i][1];
2155 for( j = i + 1; j < 6; j++ )
2156 {/* delete equal root from rest */
2158 if( !x[j][2] && REAL_ZERO( x[i][0] - x[j][0] )
2159 && REAL_ZERO( x[i][1] - x[j][1] ))
2171 /*=====================================================================================*/