Update to 2.0.0 tree from current Fremantle build
[opencv] / src / cvaux / cvtrifocal.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 #include "_cvaux.h"
43
44 //#include "cvtypes.h"
45 #include <float.h>
46 #include <limits.h>
47 //#include "cv.h"
48 //#include "windows.h"
49
50 #include <stdio.h>
51
52 /* Valery Mosyagin */
53
54 /* Function defenitions */
55
56 /* ----------------- */
57
58 void cvOptimizeLevenbergMarquardtBundle( CvMat** projMatrs, CvMat** observProjPoints,
59                                        CvMat** pointsPres, int numImages,
60                                        CvMat** resultProjMatrs, CvMat* resultPoints4D,int maxIter,double epsilon );
61
62 int icvComputeProjectMatrices6Points(  CvMat* points1,CvMat* points2,CvMat* points3,
63                                         CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3);
64
65 void icvFindBaseTransform(CvMat* points,CvMat* resultT);
66
67 void GetGeneratorReduceFundSolution(CvMat* points1,CvMat* points2,CvMat* fundReduceCoef1,CvMat* fundReduceCoef2);
68
69 int GetGoodReduceFundamMatrFromTwo(CvMat* fundReduceCoef1,CvMat* fundReduceCoef2,CvMat* resFundReduceCoef);
70
71 void GetProjMatrFromReducedFundamental(CvMat* fundReduceCoefs,CvMat* projMatrCoefs);
72
73 void icvComputeProjectMatrix(CvMat* objPoints,CvMat* projPoints,CvMat* projMatr);
74
75 void icvComputeTransform4D(CvMat* points1,CvMat* points2,CvMat* transMatr);
76
77 int icvComputeProjectMatricesNPoints(  CvMat* points1,CvMat* points2,CvMat* points3,
78                                        CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
79                                        double threshold,/* Threshold for good point */
80                                        double p,/* Probability of good result. */
81                                        CvMat* status,
82                                        CvMat* points4D);
83
84 int icvComputeProjectMatricesNPoints(  CvMat* points1,CvMat* points2,CvMat* points3,
85                                        CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
86                                        double threshold,/* Threshold for good point */
87                                        double p,/* Probability of good result. */
88                                        CvMat* status,
89                                        CvMat* points4D);
90
91 void icvReconstructPointsFor3View( CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
92                                 CvMat* projPoints1,CvMat* projPoints2,CvMat* projPoints3,
93                                 CvMat* points4D);
94
95 void icvReconstructPointsFor3View( CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
96                                 CvMat* projPoints1,CvMat* projPoints2,CvMat* projPoints3,
97                                 CvMat* points4D);
98
99 /*==========================================================================================*/
100 /*                        Functions for calculation the tensor                              */
101 /*==========================================================================================*/
102 #if 1
103 void fprintMatrix(FILE* file,CvMat* matrix)
104 {
105     int i,j;
106     fprintf(file,"\n");
107     for( i=0;i<matrix->rows;i++ )
108     {
109         for(j=0;j<matrix->cols;j++)
110         {
111             fprintf(file,"%10.7lf  ",cvmGet(matrix,i,j));
112         }
113         fprintf(file,"\n");
114     }
115 }
116 #endif
117 /*==========================================================================================*/
118
119 void icvNormalizePoints( CvMat* points, CvMat* normPoints,CvMat* cameraMatr )
120 {
121     /* Normalize image points using camera matrix */
122
123     CV_FUNCNAME( "icvNormalizePoints" );
124     __BEGIN__;
125
126     /* Test for null pointers */
127     if( points == 0 || normPoints == 0 || cameraMatr == 0 )
128     {
129         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
130     }
131
132     if( !CV_IS_MAT(points) || !CV_IS_MAT(normPoints) || !CV_IS_MAT(cameraMatr) )
133     {
134         CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
135     }
136
137     int numPoints;
138     numPoints = points->cols;
139     if( numPoints <= 0 || numPoints != normPoints->cols )
140     {
141         CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be the same and more than 0" );
142     }
143
144     if( normPoints->rows != 2 || normPoints->rows != points->rows )
145     {
146         CV_ERROR( CV_StsUnmatchedSizes, "Points must have 2 coordinates" );
147     }
148
149     if(cameraMatr->rows != 3 || cameraMatr->cols != 3)
150     {
151         CV_ERROR( CV_StsUnmatchedSizes, "Size of camera matrix must be 3x3" );
152     }
153
154     double fx,fy,cx,cy;
155
156     fx = cvmGet(cameraMatr,0,0);
157     fy = cvmGet(cameraMatr,1,1);
158     cx = cvmGet(cameraMatr,0,2);
159     cy = cvmGet(cameraMatr,1,2);
160
161     int i;
162     for( i = 0; i < numPoints; i++ )
163     {
164         cvmSet(normPoints, 0, i, (cvmGet(points,0,i) - cx) / fx );
165         cvmSet(normPoints, 1, i, (cvmGet(points,1,i) - cy) / fy );
166     }
167
168     __END__;
169
170     return;
171 }
172
173
174 /*=====================================================================================*/
175 /*
176 Computes projection matrices for given 6 points on 3 images
177 May returns 3 results. */
178 int icvComputeProjectMatrices6Points( CvMat* points1,CvMat* points2,CvMat* points3,
179                                       CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3/*,
180                                       CvMat* points4D*/)
181 {
182     /* Test input data correctness */
183
184     int numSol = 0;
185
186     CV_FUNCNAME( "icvComputeProjectMatrices6Points" );
187     __BEGIN__;
188
189     /* Test for null pointers */
190     if( points1   == 0 || points2   == 0 || points3   == 0 ||
191         projMatr1 == 0 || projMatr2 == 0 || projMatr3 == 0 )
192     {
193         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
194     }
195
196     if( !CV_IS_MAT(points1)   || !CV_IS_MAT(points2)   || !CV_IS_MAT(points3)   ||
197         !CV_IS_MAT(projMatr1) || !CV_IS_MAT(projMatr2) || !CV_IS_MAT(projMatr3)  )
198     {
199         CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
200     }
201
202     if( (points1->cols != points2->cols) || (points1->cols != points3->cols) || (points1->cols != 6) /* || (points4D->cols !=6) */)
203     {
204         CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be same and == 6" );
205     }
206
207     if( points1->rows != 2 || points2->rows != 2 || points3->rows != 2 )
208     {
209         CV_ERROR( CV_StsUnmatchedSizes, "Number of points coordinates must be 2" );
210     }
211
212     if( projMatr1->cols != 4 || projMatr2->cols != 4 || projMatr3->cols != 4 ||
213         (!(projMatr1->rows == 3 && projMatr2->rows == 3 && projMatr3->rows == 3) &&
214         !(projMatr1->rows == 9 && projMatr2->rows == 9 && projMatr3->rows == 9)) )
215     {
216         CV_ERROR( CV_StsUnmatchedSizes, "Size of project matrix must be 3x4 or 9x4 (for 3 matrices)" );
217     }
218
219 #if 0
220     if( points4D->row != 4 )
221     {
222         CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of points4D  must be 4" );
223     }
224 #endif
225
226     /* Find transform matrix for each camera */
227     int i;
228     CvMat* points[3];
229     points[0] = points1;
230     points[1] = points2;
231     points[2] = points3;
232
233     CvMat* projMatrs[3];
234     projMatrs[0] = projMatr1;
235     projMatrs[1] = projMatr2;
236     projMatrs[2] = projMatr3;
237
238     CvMat transMatr;
239     double transMatr_dat[9];
240     transMatr = cvMat(3,3,CV_64F,transMatr_dat);
241
242     CvMat corrPoints1;
243     CvMat corrPoints2;
244
245     double corrPoints_dat[3*3*2];/* 3-point(images) by 3-coordinates by 2-correspondence*/
246
247     corrPoints1 = cvMat(3,3,CV_64F,corrPoints_dat);  /* 3-coordinates for each of 3-points(3-image) */
248     corrPoints2 = cvMat(3,3,CV_64F,corrPoints_dat+9);/* 3-coordinates for each of 3-points(3-image) */
249
250     for( i = 0; i < 3; i++ )/* for each image */
251     {
252         /* Get last 4 points for computing transformation */
253         CvMat tmpPoints;
254         /* find base points transform for last four points on i-th image */
255         cvGetSubRect(points[i],&tmpPoints,cvRect(2,0,4,2));
256         icvFindBaseTransform(&tmpPoints,&transMatr);
257
258         {/* We have base transform. Compute error scales for three first points */
259             CvMat trPoint;
260             double trPoint_dat[3*3];
261             trPoint = cvMat(3,3,CV_64F,trPoint_dat);
262             /* fill points */
263             for( int kk = 0; kk < 3; kk++ )
264             {
265                 cvmSet(&trPoint,0,kk,cvmGet(points[i],0,kk+2));
266                 cvmSet(&trPoint,1,kk,cvmGet(points[i],1,kk+2));
267                 cvmSet(&trPoint,2,kk,1);
268             }
269
270             /* Transform points */
271             CvMat resPnts;
272             double resPnts_dat[9];
273             resPnts = cvMat(3,3,CV_64F,resPnts_dat);
274             cvmMul(&transMatr,&trPoint,&resPnts);
275         }
276
277         /* Transform two first points */
278         for( int j = 0; j < 2; j++ )
279         {
280             CvMat pnt;
281             double pnt_dat[3];
282             pnt = cvMat(3,1,CV_64F,pnt_dat);
283             pnt_dat[0] = cvmGet(points[i],0,j);
284             pnt_dat[1] = cvmGet(points[i],1,j);
285             pnt_dat[2] = 1.0;
286
287             CvMat trPnt;
288             double trPnt_dat[3];
289             trPnt = cvMat(3,1,CV_64F,trPnt_dat);
290
291             cvmMul(&transMatr,&pnt,&trPnt);
292
293             /* Collect transformed points  */
294             corrPoints_dat[j * 9 + 0 * 3 + i] = trPnt_dat[0];/* x */
295             corrPoints_dat[j * 9 + 1 * 3 + i] = trPnt_dat[1];/* y */
296             corrPoints_dat[j * 9 + 2 * 3 + i] = trPnt_dat[2];/* w */
297         }
298     }
299
300     /* We have computed corr points. Now we can compute generators for reduced fundamental matrix */
301
302     /* Compute generators for reduced fundamental matrix from 3 pair of collect points */
303     CvMat fundReduceCoef1;
304     CvMat fundReduceCoef2;
305     double fundReduceCoef1_dat[5];
306     double fundReduceCoef2_dat[5];
307
308     fundReduceCoef1 = cvMat(1,5,CV_64F,fundReduceCoef1_dat);
309     fundReduceCoef2 = cvMat(1,5,CV_64F,fundReduceCoef2_dat);
310
311     GetGeneratorReduceFundSolution(&corrPoints1, &corrPoints2, &fundReduceCoef1, &fundReduceCoef2);
312
313     /* Choose best solutions for two generators. We can get 3 solutions */
314     CvMat resFundReduceCoef;
315     double resFundReduceCoef_dat[3*5];
316
317     resFundReduceCoef = cvMat(3,5,CV_64F,resFundReduceCoef_dat);
318
319     numSol = GetGoodReduceFundamMatrFromTwo(&fundReduceCoef1, &fundReduceCoef2,&resFundReduceCoef);
320
321     int maxSol;
322     maxSol = projMatrs[0]->rows / 3;
323
324     int currSol;
325     for( currSol = 0; (currSol < numSol && currSol < maxSol); currSol++ )
326     {
327         /* For current solution compute projection matrix */
328         CvMat fundCoefs;
329         cvGetSubRect(&resFundReduceCoef, &fundCoefs, cvRect(0,currSol,5,1));
330
331         CvMat projMatrCoefs;
332         double projMatrCoefs_dat[4];
333         projMatrCoefs = cvMat(1,4,CV_64F,projMatrCoefs_dat);
334
335         GetProjMatrFromReducedFundamental(&fundCoefs,&projMatrCoefs);
336         /* we have computed coeffs for reduced project matrix */
337
338         CvMat objPoints;
339         double objPoints_dat[4*6];
340         objPoints  = cvMat(4,6,CV_64F,objPoints_dat);
341         cvZero(&objPoints);
342
343         /* fill object points */
344         for( i =0; i < 4; i++ )
345         {
346             objPoints_dat[i*6]   = 1;
347             objPoints_dat[i*6+1] = projMatrCoefs_dat[i];
348             objPoints_dat[i*7+2] = 1;
349         }
350
351         int currCamera;
352         for( currCamera = 0; currCamera < 3; currCamera++ )
353         {
354
355             CvMat projPoints;
356             double projPoints_dat[3*6];
357             projPoints = cvMat(3,6,CV_64F,projPoints_dat);
358
359             /* fill projected points for current camera */
360             for( i = 0; i < 6; i++ )/* for each points for current camera */
361             {
362                 projPoints_dat[6*0+i] = cvmGet(points[currCamera],0,i);/* x */
363                 projPoints_dat[6*1+i] = cvmGet(points[currCamera],1,i);/* y */
364                 projPoints_dat[6*2+i] = 1;/* w */
365             }
366
367             /* compute project matrix for current camera */
368             CvMat projMatrix;
369             double projMatrix_dat[3*4];
370             projMatrix = cvMat(3,4,CV_64F,projMatrix_dat);
371
372             icvComputeProjectMatrix(&objPoints,&projPoints,&projMatrix);
373
374             /* Add this matrix to result */
375             CvMat tmpSubRes;
376             cvGetSubRect(projMatrs[currCamera],&tmpSubRes,cvRect(0,currSol*3,4,3));
377             cvConvert(&projMatrix,&tmpSubRes);
378         }
379
380         /* We know project matrices. And we can reconstruct 6 3D-points if need */
381 #if 0
382         if( points4D )
383         {
384             if( currSol < points4D->rows / 4 )
385             {
386                 CvMat tmpPoints4D;
387                 double tmpPoints4D_dat[4*6];
388                 tmpPoints4D = cvMat(4,6,CV_64F,tmpPoints4D_dat);
389
390                 icvReconstructPointsFor3View( &wProjMatr[0], &wProjMatr[1], &wProjMatr[2],
391                                            points1, points2, points3,
392                                            &tmpPoints4D);
393
394                 CvMat tmpSubRes;
395                 cvGetSubRect(points4D,tmpSubRes,cvRect(0,currSol*4,6,4));
396                 cvConvert(tmpPoints4D,points4D);
397             }
398         }
399 #endif
400
401     }/* for all sollutions */
402
403     __END__;
404     return numSol;
405 }
406
407 /*==========================================================================================*/
408 int icvGetRandNumbers(int range,int count,int* arr)
409 {
410     /* Generate random numbers [0,range-1] */
411
412     CV_FUNCNAME( "icvGetRandNumbers" );
413     __BEGIN__;
414
415     /* Test input data */
416     if( arr == 0 )
417     {
418         CV_ERROR( CV_StsNullPtr, "Parameter 'arr' is a NULL pointer" );
419     }
420
421
422     /* Test for errors input data  */
423     if( range < count || range <= 0 )
424     {
425         CV_ERROR( CV_StsOutOfRange, "Can't generate such numbers. Count must be <= range and range must be > 0" );
426     }
427
428     int i,j;
429     int newRand;
430     for( i = 0; i < count; i++ )
431     {
432
433         int haveRep = 0;/* firstly we have not repeats */
434         do
435         {
436             /* generate new number */
437             newRand = rand()%range;
438             haveRep = 0;
439             /* Test for repeats in previous numbers */
440             for( j = 0; j < i; j++ )
441             {
442                 if( arr[j] == newRand )
443                 {
444                     haveRep = 1;
445                     break;
446                 }
447             }
448         } while(haveRep);
449
450         /* We have good random number */
451         arr[i] = newRand;
452     }
453     __END__;
454     return 1;
455 }
456 /*==========================================================================================*/
457 void icvSelectColsByNumbers(CvMat* srcMatr, CvMat* dstMatr, int* indexes,int number)
458 {
459
460     CV_FUNCNAME( "icvSelectColsByNumbers" );
461     __BEGIN__;
462
463     /* Test input data */
464     if( srcMatr == 0 || dstMatr == 0 || indexes == 0)
465     {
466         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
467     }
468
469     if( !CV_IS_MAT(srcMatr) || !CV_IS_MAT(dstMatr) )
470     {
471         CV_ERROR( CV_StsUnsupportedFormat, "srcMatr and dstMatr must be a matrices" );
472     }
473
474     int srcSize;
475     int numRows;
476     numRows = srcMatr->rows;
477     srcSize = srcMatr->cols;
478
479     if( numRows != dstMatr->rows )
480     {
481         CV_ERROR( CV_StsOutOfRange, "Number of rows of matrices must be the same" );
482     }
483
484     int dst;
485     for( dst = 0; dst < number; dst++ )
486     {
487         int src = indexes[dst];
488         if( src >=0 && src < srcSize )
489         {
490             /* Copy each elements in column */
491             int i;
492             for( i = 0; i < numRows; i++ )
493             {
494                 cvmSet(dstMatr,i,dst,cvmGet(srcMatr,i,src));
495             }
496         }
497     }
498
499     __END__;
500     return;
501 }
502
503 /*==========================================================================================*/
504 void icvProject4DPoints(CvMat* points4D,CvMat* projMatr, CvMat* projPoints)
505 {
506
507     CvMat* tmpProjPoints = 0;
508
509     CV_FUNCNAME( "icvProject4DPoints" );
510
511     __BEGIN__;
512
513     if( points4D == 0 || projMatr == 0 || projPoints == 0)
514     {
515         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
516     }
517
518     if( !CV_IS_MAT(points4D) || !CV_IS_MAT(projMatr) || !CV_IS_MAT(projPoints) )
519     {
520         CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
521     }
522
523     int numPoints;
524     numPoints = points4D->cols;
525     if( numPoints < 1 )
526     {
527         CV_ERROR( CV_StsOutOfRange, "Number of points4D must be more than zero" );
528     }
529
530     if( numPoints != projPoints->cols )
531     {
532         CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be the same");
533     }
534
535     if( projPoints->rows != 2 )
536     {
537         CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of projected points must be 2");
538     }
539
540     if( points4D->rows != 4 )
541     {
542         CV_ERROR(CV_StsUnmatchedSizes, "Number of coordinates of 4D points must be 4");
543     }
544
545     if( projMatr->cols != 4 || projMatr->rows != 3 )
546     {
547         CV_ERROR( CV_StsUnmatchedSizes, "Size of projection matrix must be 3x4");
548     }
549
550
551     CV_CALL( tmpProjPoints = cvCreateMat(3,numPoints,CV_64F) );
552
553     cvmMul(projMatr,points4D,tmpProjPoints);
554
555     /* Scale points */
556     int i;
557     for( i = 0; i < numPoints; i++ )
558     {
559         double scale,x,y;
560
561         scale = cvmGet(tmpProjPoints,2,i);
562         x = cvmGet(tmpProjPoints,0,i);
563         y = cvmGet(tmpProjPoints,1,i);
564
565         if( fabs(scale) > 1e-7 )
566         {
567             x /= scale;
568             y /= scale;
569         }
570         else
571         {
572             x = 1e8;
573             y = 1e8;
574         }
575
576         cvmSet(projPoints,0,i,x);
577         cvmSet(projPoints,1,i,y);
578     }
579
580     __END__;
581
582     cvReleaseMat(&tmpProjPoints);
583
584     return;
585 }
586 /*==========================================================================================*/
587 int icvCompute3ProjectMatricesNPointsStatus( CvMat** points,/* 3 arrays of points on image  */
588                                              CvMat** projMatrs,/* array of 3 prejection matrices */
589                                              CvMat** statuses,/* 3 arrays of status of points */
590                                              double threshold,/* Threshold for good point */
591                                              double p,/* Probability of good result. */
592                                              CvMat* resStatus,
593                                              CvMat* points4D)
594 {
595     int numProjMatrs = 0;
596     unsigned char *comStat = 0;
597     CvMat *triPoints[3] = {0,0,0};
598     CvMat *status = 0;
599     CvMat *triPoints4D = 0;
600
601     CV_FUNCNAME( "icvCompute3ProjectMatricesNPointsStatus" );
602     __BEGIN__;
603
604     /* Test for errors */
605     if( points == 0 || projMatrs == 0 || statuses == 0 || resStatus == 0 )
606     {
607         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
608     }
609
610     int currImage;
611     for( currImage = 0; currImage < 3; currImage++ )
612     {
613         /* Test for null pointers */
614         if( points[currImage] == 0 )
615         {
616             CV_ERROR( CV_StsNullPtr, "Some of points arrays is a NULL pointer" );
617         }
618
619         if( projMatrs[currImage] == 0 )
620         {
621             CV_ERROR( CV_StsNullPtr, "Some of projMatr is a NULL pointer" );
622         }
623
624         if( statuses[currImage] == 0 )
625         {
626             CV_ERROR( CV_StsNullPtr, "Some of status arrays is a NULL pointer" );
627         }
628
629         /* Test for matrices */
630         if( !CV_IS_MAT(points[currImage]) )
631         {
632             CV_ERROR( CV_StsNullPtr, "Some of points arrays is not a matrix" );
633         }
634
635         if( !CV_IS_MAT(projMatrs[currImage]) )
636         {
637             CV_ERROR( CV_StsNullPtr, "Some of projMatr is not a matrix" );
638         }
639
640         if( !CV_IS_MASK_ARR(statuses[currImage]) )
641         {
642             CV_ERROR( CV_StsNullPtr, "Some of status arrays is not a mask array" );
643         }
644     }
645
646     int numPoints;
647     numPoints = points[0]->cols;
648     if( numPoints < 6 )
649     {
650         CV_ERROR( CV_StsOutOfRange, "Number points must be more than 6" );
651     }
652
653     for( currImage = 0; currImage < 3; currImage++ )
654     {
655         if( points[currImage]->cols != numPoints || statuses[currImage]->cols != numPoints )
656         {
657             CV_ERROR( CV_StsUnmatchedSizes, "Number of points and statuses must be the same" );
658         }
659
660         if( points[currImage]->rows != 2 )
661         {
662             CV_ERROR( CV_StsOutOfRange, "Number of points coordinates must be == 2" );
663         }
664
665         if( statuses[currImage]->rows != 1 )
666         {
667             CV_ERROR( CV_StsOutOfRange, "Each of status must be matrix 1xN" );
668         }
669
670         if( projMatrs[currImage]->rows != 3 || projMatrs[currImage]->cols != 4 )
671         {
672             CV_ERROR( CV_StsOutOfRange, "Each of projection matrix must be 3x4" );
673         }
674     }
675
676
677     /* Create common status for all points */
678
679     int i;
680
681     CV_CALL( comStat = (unsigned char*)cvAlloc(sizeof(unsigned char)*numPoints) );
682
683     unsigned char *stats[3];
684
685     stats[0] = statuses[0]->data.ptr;
686     stats[1] = statuses[1]->data.ptr;
687     stats[2] = statuses[2]->data.ptr;
688
689     int numTripl;
690     numTripl = 0;
691     for( i = 0; i < numPoints; i++ )
692     {
693         comStat[i] = (unsigned char)(stats[0][i] * stats[1][i] * stats[2][i]);
694         numTripl += comStat[i];
695     }
696
697     if( numTripl > 0 )
698     {
699         /* Create new arrays with points */
700         CV_CALL( triPoints[0] = cvCreateMat(2,numTripl,CV_64F) );
701         CV_CALL( triPoints[1] = cvCreateMat(2,numTripl,CV_64F) );
702         CV_CALL( triPoints[2] = cvCreateMat(2,numTripl,CV_64F) );
703         if( points4D )
704         {
705             CV_CALL( triPoints4D  = cvCreateMat(4,numTripl,CV_64F) );
706         }
707
708         /* Create status array */
709         CV_CALL( status = cvCreateMat(1,numTripl,CV_64F) );
710
711         /* Copy points to new arrays */
712         int currPnt = 0;
713         for( i = 0; i < numPoints; i++ )
714         {
715             if( comStat[i] )
716             {
717                 for( currImage = 0; currImage < 3; currImage++ )
718                 {
719                     cvmSet(triPoints[currImage],0,currPnt,cvmGet(points[currImage],0,i));
720                     cvmSet(triPoints[currImage],1,currPnt,cvmGet(points[currImage],1,i));
721                 }
722                 currPnt++;
723             }
724         }
725
726         /* Call function */
727         numProjMatrs = icvComputeProjectMatricesNPoints( triPoints[0],triPoints[1],triPoints[2],
728                                                          projMatrs[0],projMatrs[1],projMatrs[2],
729                                                          threshold,/* Threshold for good point */
730                                                          p,/* Probability of good result. */
731                                                          status,
732                                                          triPoints4D);
733
734         /* Get computed status and set to result */
735         cvZero(resStatus);
736         currPnt = 0;
737         for( i = 0; i < numPoints; i++ )
738         {
739             if( comStat[i] )
740             {
741                 if( cvmGet(status,0,currPnt) > 0 )
742                 {
743                     resStatus->data.ptr[i] = 1;
744                 }
745                 currPnt++;
746             }
747         }
748
749         if( triPoints4D )
750         {
751             /* Copy copmuted 4D points */
752             cvZero(points4D);
753             currPnt = 0;
754             for( i = 0; i < numPoints; i++ )
755             {
756                 if( comStat[i] )
757                 {
758                     if( cvmGet(status,0,currPnt) > 0 )
759                     {
760                         cvmSet( points4D, 0, i, cvmGet( triPoints4D , 0, currPnt) );
761                         cvmSet( points4D, 1, i, cvmGet( triPoints4D , 1, currPnt) );
762                         cvmSet( points4D, 2, i, cvmGet( triPoints4D , 2, currPnt) );
763                         cvmSet( points4D, 3, i, cvmGet( triPoints4D , 3, currPnt) );
764                     }
765                     currPnt++;
766                 }
767             }
768         }
769     }
770
771     __END__;
772
773     /* Free allocated memory */
774     cvReleaseMat(&status);
775     cvFree( &comStat);
776     cvReleaseMat(&status);
777
778     cvReleaseMat(&triPoints[0]);
779     cvReleaseMat(&triPoints[1]);
780     cvReleaseMat(&triPoints[2]);
781     cvReleaseMat(&triPoints4D);
782
783     return numProjMatrs;
784
785 }
786
787 /*==========================================================================================*/
788 int icvComputeProjectMatricesNPoints(  CvMat* points1,CvMat* points2,CvMat* points3,
789                                        CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
790                                        double threshold,/* Threshold for good point */
791                                        double p,/* Probability of good result. */
792                                        CvMat* status,
793                                        CvMat* points4D)
794 {
795     /* Returns status for each point, Good or bad */
796
797     /* Compute projection matrices using N points */
798
799     char* flags = 0;
800     char* bestFlags = 0;
801
802     int numProjMatrs = 0;
803
804     CvMat* tmpProjPoints[3]={0,0,0};
805     CvMat* recPoints4D = 0;
806     CvMat *reconPoints4D = 0;
807
808
809     CV_FUNCNAME( "icvComputeProjectMatricesNPoints" );
810     __BEGIN__;
811
812     CvMat* points[3];
813     points[0] = points1;
814     points[1] = points2;
815     points[2] = points3;
816
817     /* Test for errors */
818     if( points1   == 0 || points2   == 0 || points3   == 0 ||
819         projMatr1 == 0 || projMatr2 == 0 || projMatr3 == 0 ||
820         status == 0)
821     {
822         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
823     }
824
825     if( !CV_IS_MAT(points1)   || !CV_IS_MAT(points2)   || !CV_IS_MAT(points3)   ||
826         !CV_IS_MAT(projMatr1) || !CV_IS_MAT(projMatr2) || !CV_IS_MAT(projMatr3)  ||
827         !CV_IS_MAT(status) )
828     {
829         CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
830     }
831
832     int numPoints;
833     numPoints = points1->cols;
834
835     if( numPoints < 6 )
836     {
837         CV_ERROR( CV_StsOutOfRange, "Number points must be more than 6" );
838     }
839
840     if( numPoints != points2->cols || numPoints != points3->cols )
841     {
842         CV_ERROR( CV_StsUnmatchedSizes, "number of points must be the same" );
843     }
844
845     if( p < 0 || p > 1.0 )
846     {
847         CV_ERROR( CV_StsOutOfRange, "Probability must be >=0 and <=1" );
848     }
849
850     if( threshold < 0 )
851     {
852         CV_ERROR( CV_StsOutOfRange, "Threshold for good points must be at least >= 0" );
853     }
854
855     CvMat* projMatrs[3];
856
857     projMatrs[0] = projMatr1;
858     projMatrs[1] = projMatr2;
859     projMatrs[2] = projMatr3;
860
861     int i;
862     for( i = 0; i < 3; i++ )
863     {
864         if( projMatrs[i]->cols != 4 || projMatrs[i]->rows != 3 )
865         {
866             CV_ERROR( CV_StsUnmatchedSizes, "Size of projection matrices must be 3x4" );
867         }
868     }
869
870     for( i = 0; i < 3; i++ )
871     {
872         if( points[i]->rows != 2)
873         {
874             CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of points must be 2" );
875         }
876     }
877
878     /* use RANSAC algorithm to compute projection matrices */
879
880     CV_CALL( recPoints4D = cvCreateMat(4,numPoints,CV_64F) );
881     CV_CALL( tmpProjPoints[0] = cvCreateMat(2,numPoints,CV_64F) );
882     CV_CALL( tmpProjPoints[1] = cvCreateMat(2,numPoints,CV_64F) );
883     CV_CALL( tmpProjPoints[2] = cvCreateMat(2,numPoints,CV_64F) );
884
885     CV_CALL( flags = (char*)cvAlloc(sizeof(char)*numPoints) );
886     CV_CALL( bestFlags = (char*)cvAlloc(sizeof(char)*numPoints) );
887
888     {
889         int NumSamples = 500;/* just init number of samples */
890         int wasCount = 0;  /* count of choosing samples */
891         int maxGoodPoints = 0;
892         int numGoodPoints = 0;
893
894         double bestProjMatrs_dat[36];
895         CvMat  bestProjMatrs[3];
896         bestProjMatrs[0] = cvMat(3,4,CV_64F,bestProjMatrs_dat);
897         bestProjMatrs[1] = cvMat(3,4,CV_64F,bestProjMatrs_dat+12);
898         bestProjMatrs[2] = cvMat(3,4,CV_64F,bestProjMatrs_dat+24);
899
900         double tmpProjMatr_dat[36*3];
901         CvMat  tmpProjMatr[3];
902         tmpProjMatr[0] = cvMat(9,4,CV_64F,tmpProjMatr_dat);
903         tmpProjMatr[1] = cvMat(9,4,CV_64F,tmpProjMatr_dat+36);
904         tmpProjMatr[2] = cvMat(9,4,CV_64F,tmpProjMatr_dat+72);
905
906         /* choosen points */
907
908         while( wasCount < NumSamples )
909         {
910             /* select samples */
911             int randNumbs[6];
912             icvGetRandNumbers(numPoints,6,randNumbs);
913
914             /* random numbers of points was generated */
915             /* select points */
916
917             double selPoints_dat[2*6*3];
918             CvMat selPoints[3];
919             selPoints[0] = cvMat(2,6,CV_64F,selPoints_dat);
920             selPoints[1] = cvMat(2,6,CV_64F,selPoints_dat+12);
921             selPoints[2] = cvMat(2,6,CV_64F,selPoints_dat+24);
922
923             /* Copy 6 point for random indexes */
924             icvSelectColsByNumbers( points[0], &selPoints[0], randNumbs,6);
925             icvSelectColsByNumbers( points[1], &selPoints[1], randNumbs,6);
926             icvSelectColsByNumbers( points[2], &selPoints[2], randNumbs,6);
927
928             /* Compute projection matrices for this points */
929             int numProj = icvComputeProjectMatrices6Points( &selPoints[0],&selPoints[1],&selPoints[2],
930                                                             &tmpProjMatr[0],&tmpProjMatr[1],&tmpProjMatr[2]);
931
932             /* Compute number of good points for each matrix */
933             CvMat proj6[3];
934             for( int currProj = 0; currProj < numProj; currProj++ )
935             {
936                 cvGetSubArr(&tmpProjMatr[0],&proj6[0],cvRect(0,currProj*3,4,3));
937                 cvGetSubArr(&tmpProjMatr[1],&proj6[1],cvRect(0,currProj*3,4,3));
938                 cvGetSubArr(&tmpProjMatr[2],&proj6[2],cvRect(0,currProj*3,4,3));
939
940                 /* Reconstruct points for projection matrices */
941                 icvReconstructPointsFor3View( &proj6[0],&proj6[1],&proj6[2],
942                                            points[0], points[1], points[2],
943                                            recPoints4D);
944
945                 /* Project points to images using projection matrices */
946                 icvProject4DPoints(recPoints4D,&proj6[0],tmpProjPoints[0]);
947                 icvProject4DPoints(recPoints4D,&proj6[1],tmpProjPoints[1]);
948                 icvProject4DPoints(recPoints4D,&proj6[2],tmpProjPoints[2]);
949
950                 /* Compute distances and number of good points (inliers) */
951                 int i;
952                 int currImage;
953                 numGoodPoints = 0;
954                 for( i = 0; i < numPoints; i++ )
955                 {
956                     double dist=-1;
957                     dist = 0;
958                     /* Choose max distance for each of three points */
959                     for( currImage = 0; currImage < 3; currImage++ )
960                     {
961                         double x1,y1,x2,y2;
962                         x1 = cvmGet(tmpProjPoints[currImage],0,i);
963                         y1 = cvmGet(tmpProjPoints[currImage],1,i);
964                         x2 = cvmGet(points[currImage],0,i);
965                         y2 = cvmGet(points[currImage],1,i);
966
967                         double dx,dy;
968                         dx = x1-x2;
969                         dy = y1-y2;
970 #if 1
971                         double newDist = dx*dx+dy*dy;
972                         if( newDist > dist )
973                         {
974                             dist = newDist;
975                         }
976 #else
977                         dist += sqrt(dx*dx+dy*dy)/3.0;
978 #endif
979                     }
980                     dist = sqrt(dist);
981                     flags[i] = (char)(dist > threshold ? 0 : 1);
982                     numGoodPoints += flags[i];
983
984                 }
985
986
987                 if( numGoodPoints > maxGoodPoints )
988                 {/* Copy current projection matrices as best */
989
990                     cvCopy(&proj6[0],&bestProjMatrs[0]);
991                     cvCopy(&proj6[1],&bestProjMatrs[1]);
992                     cvCopy(&proj6[2],&bestProjMatrs[2]);
993
994                     maxGoodPoints = numGoodPoints;
995                     /* copy best flags */
996                     memcpy(bestFlags,flags,sizeof(flags[0])*numPoints);
997
998                     /* Adaptive number of samples to count*/
999                                 double ep = 1 - (double)numGoodPoints / (double)numPoints;
1000                     if( ep == 1 )
1001                     {
1002                         ep = 0.5;/* if there is not good points set ration of outliers to 50% */
1003                     }
1004
1005                                 double newNumSamples = (log(1-p) / log(1-pow(1-ep,6)));
1006                     if(  newNumSamples < double(NumSamples) )
1007                     {
1008                         NumSamples = cvRound(newNumSamples);
1009                     }
1010                 }
1011             }
1012
1013             wasCount++;
1014         }
1015 #if 0
1016         char str[300];
1017         sprintf(str,"Initial numPoints = %d\nmaxGoodPoints=%d\nRANSAC made %d steps",
1018                     numPoints,
1019                     maxGoodPoints,
1020                     cvRound(wasCount));
1021         MessageBox(0,str,"Info",MB_OK|MB_TASKMODAL);
1022 #endif
1023
1024         /* we may have best 6-point projection matrices. */
1025         /* and best points */
1026         /* use these points to improve matrices */
1027
1028         if( maxGoodPoints < 6 )
1029         {
1030             /*  matrix not found */
1031             numProjMatrs = 0;
1032         }
1033         else
1034         {
1035             /* We may Improove matrices using ---- method */
1036             /* We may try to use Levenberg-Marquardt optimization */
1037             //int currIter = 0;
1038             int finalGoodPoints = 0;
1039             char *goodFlags = 0;
1040             goodFlags = (char*)cvAlloc(numPoints*sizeof(char));
1041
1042             int needRepeat;
1043             do
1044             {
1045 #if 0
1046 /* Version without using status for Levenberg-Marquardt minimization */
1047
1048                 CvMat *optStatus;
1049                 optStatus = cvCreateMat(1,numPoints,CV_64F);
1050                 int testNumber = 0;
1051                 for( i=0;i<numPoints;i++ )
1052                 {
1053                     cvmSet(optStatus,0,i,(double)bestFlags[i]);
1054                     testNumber += bestFlags[i];
1055                 }
1056
1057                 char str2[200];
1058                 sprintf(str2,"test good num=%d\nmaxGoodPoints=%d",testNumber,maxGoodPoints);
1059                 MessageBox(0,str2,"Info",MB_OK|MB_TASKMODAL);
1060
1061                 CvMat *gPresPoints;
1062                 gPresPoints = cvCreateMat(1,maxGoodPoints,CV_64F);
1063                 for( i = 0; i < maxGoodPoints; i++)
1064                 {
1065                     cvmSet(gPresPoints,0,i,1.0);
1066                 }
1067
1068                 /* Create array of points pres */
1069                 CvMat *pointsPres[3];
1070                 pointsPres[0] = gPresPoints;
1071                 pointsPres[1] = gPresPoints;
1072                 pointsPres[2] = gPresPoints;
1073
1074                 /* Create just good points 2D */
1075                 CvMat *gPoints[3];
1076                 icvCreateGoodPoints(points[0],&gPoints[0],optStatus);
1077                 icvCreateGoodPoints(points[1],&gPoints[1],optStatus);
1078                 icvCreateGoodPoints(points[2],&gPoints[2],optStatus);
1079
1080                 /* Create 4D points array for good points */
1081                 CvMat *resPoints4D;
1082                 resPoints4D = cvCreateMat(4,maxGoodPoints,CV_64F);
1083
1084                 CvMat* projMs[3];
1085
1086                 projMs[0] = &bestProjMatrs[0];
1087                 projMs[1] = &bestProjMatrs[1];
1088                 projMs[2] = &bestProjMatrs[2];
1089
1090
1091                 CvMat resProjMatrs[3];
1092                 double resProjMatrs_dat[36];
1093                 resProjMatrs[0] = cvMat(3,4,CV_64F,resProjMatrs_dat);
1094                 resProjMatrs[1] = cvMat(3,4,CV_64F,resProjMatrs_dat+12);
1095                 resProjMatrs[2] = cvMat(3,4,CV_64F,resProjMatrs_dat+24);
1096
1097                 CvMat* resMatrs[3];
1098                 resMatrs[0] = &resProjMatrs[0];
1099                 resMatrs[1] = &resProjMatrs[1];
1100                 resMatrs[2] = &resProjMatrs[2];
1101
1102                 cvOptimizeLevenbergMarquardtBundle( projMs,//projMs,
1103                                                     gPoints,//points,//points2D,
1104                                                     pointsPres,//pointsPres,
1105                                                     3,
1106                                                     resMatrs,//resProjMatrs,
1107                                                     resPoints4D,//resPoints4D,
1108                                                     100, 1e-9 );
1109
1110                 /* We found optimized projection matrices */
1111
1112                 CvMat *reconPoints4D;
1113                 reconPoints4D = cvCreateMat(4,numPoints,CV_64F);
1114
1115                 /* Reconstruct all points using found projection matrices */
1116                 icvReconstructPointsFor3View( &resProjMatrs[0],&resProjMatrs[1],&resProjMatrs[2],
1117                                               points[0], points[1], points[2],
1118                                               reconPoints4D);
1119
1120                 /* Project points to images using projection matrices */
1121                 icvProject4DPoints(reconPoints4D,&resProjMatrs[0],tmpProjPoints[0]);
1122                 icvProject4DPoints(reconPoints4D,&resProjMatrs[1],tmpProjPoints[1]);
1123                 icvProject4DPoints(reconPoints4D,&resProjMatrs[2],tmpProjPoints[2]);
1124
1125
1126                 /* Compute error for each point and select good */
1127
1128                 int currImage;
1129                 finalGoodPoints = 0;
1130                 for( i = 0; i < numPoints; i++ )
1131                 {
1132                     double dist=-1;
1133                     /* Choose max distance for each of three points */
1134                     for( currImage = 0; currImage < 3; currImage++ )
1135                     {
1136                         double x1,y1,x2,y2;
1137                         x1 = cvmGet(tmpProjPoints[currImage],0,i);
1138                         y1 = cvmGet(tmpProjPoints[currImage],1,i);
1139                         x2 = cvmGet(points[currImage],0,i);
1140                         y2 = cvmGet(points[currImage],1,i);
1141
1142                         double dx,dy;
1143                         dx = x1-x2;
1144                         dy = y1-y2;
1145
1146                         double newDist = dx*dx+dy*dy;
1147                         if( newDist > dist )
1148                         {
1149                             dist = newDist;
1150                         }
1151                     }
1152                     dist = sqrt(dist);
1153                     goodFlags[i] = (char)(dist > threshold ? 0 : 1);
1154                     finalGoodPoints += goodFlags[i];
1155                 }
1156
1157                 char str[200];
1158                 sprintf(str,"Was num = %d\nNew num=%d",maxGoodPoints,finalGoodPoints);
1159                 MessageBox(0,str,"Info",MB_OK|MB_TASKMODAL);
1160                 if( finalGoodPoints > maxGoodPoints )
1161                 {
1162                     /* Copy new version of projection matrices */
1163                     cvCopy(&resProjMatrs[0],&bestProjMatrs[0]);
1164                     cvCopy(&resProjMatrs[1],&bestProjMatrs[1]);
1165                     cvCopy(&resProjMatrs[2],&bestProjMatrs[2]);
1166                     memcpy(bestFlags,goodFlags,numPoints*sizeof(char));
1167                     maxGoodPoints = finalGoodPoints;
1168                 }
1169
1170                 cvReleaseMat(&optStatus);
1171                 cvReleaseMat(&resPoints4D);
1172 #else
1173 /* Version with using status for Levenberd-Marquardt minimization */
1174
1175                 /* Create status */
1176                 CvMat *optStatus;
1177                 optStatus = cvCreateMat(1,numPoints,CV_64F);
1178                 for( i=0;i<numPoints;i++ )
1179                 {
1180                     cvmSet(optStatus,0,i,(double)bestFlags[i]);
1181                 }
1182
1183                 CvMat *pointsPres[3];
1184                 pointsPres[0] = optStatus;
1185                 pointsPres[1] = optStatus;
1186                 pointsPres[2] = optStatus;
1187
1188                 /* Create 4D points array for good points */
1189                 CvMat *resPoints4D;
1190                 resPoints4D = cvCreateMat(4,numPoints,CV_64F);
1191
1192                 CvMat* projMs[3];
1193
1194                 projMs[0] = &bestProjMatrs[0];
1195                 projMs[1] = &bestProjMatrs[1];
1196                 projMs[2] = &bestProjMatrs[2];
1197
1198                 CvMat resProjMatrs[3];
1199                 double resProjMatrs_dat[36];
1200                 resProjMatrs[0] = cvMat(3,4,CV_64F,resProjMatrs_dat);
1201                 resProjMatrs[1] = cvMat(3,4,CV_64F,resProjMatrs_dat+12);
1202                 resProjMatrs[2] = cvMat(3,4,CV_64F,resProjMatrs_dat+24);
1203
1204                 CvMat* resMatrs[3];
1205                 resMatrs[0] = &resProjMatrs[0];
1206                 resMatrs[1] = &resProjMatrs[1];
1207                 resMatrs[2] = &resProjMatrs[2];
1208
1209                 cvOptimizeLevenbergMarquardtBundle( projMs,//projMs,
1210                                                     points,//points2D,
1211                                                     pointsPres,//pointsPres,
1212                                                     3,
1213                                                     resMatrs,//resProjMatrs,
1214                                                     resPoints4D,//resPoints4D,
1215                                                     100, 1e-9 );
1216
1217                 /* We found optimized projection matrices */
1218
1219                 reconPoints4D = cvCreateMat(4,numPoints,CV_64F);
1220
1221                 /* Reconstruct all points using found projection matrices */
1222                 icvReconstructPointsFor3View( &resProjMatrs[0],&resProjMatrs[1],&resProjMatrs[2],
1223                                               points[0], points[1], points[2],
1224                                               reconPoints4D);
1225
1226                 /* Project points to images using projection matrices */
1227                 icvProject4DPoints(reconPoints4D,&resProjMatrs[0],tmpProjPoints[0]);
1228                 icvProject4DPoints(reconPoints4D,&resProjMatrs[1],tmpProjPoints[1]);
1229                 icvProject4DPoints(reconPoints4D,&resProjMatrs[2],tmpProjPoints[2]);
1230
1231
1232                 /* Compute error for each point and select good */
1233
1234                 int currImage;
1235                 finalGoodPoints = 0;
1236                 for( i = 0; i < numPoints; i++ )
1237                 {
1238                     double dist=-1;
1239                     /* Choose max distance for each of three points */
1240                     for( currImage = 0; currImage < 3; currImage++ )
1241                     {
1242                         double x1,y1,x2,y2;
1243                         x1 = cvmGet(tmpProjPoints[currImage],0,i);
1244                         y1 = cvmGet(tmpProjPoints[currImage],1,i);
1245                         x2 = cvmGet(points[currImage],0,i);
1246                         y2 = cvmGet(points[currImage],1,i);
1247
1248                         double dx,dy;
1249                         dx = x1-x2;
1250                         dy = y1-y2;
1251
1252                         double newDist = dx*dx+dy*dy;
1253                         if( newDist > dist )
1254                         {
1255                             dist = newDist;
1256                         }
1257                     }
1258                     dist = sqrt(dist);
1259                     goodFlags[i] = (char)(dist > threshold ? 0 : 1);
1260                     finalGoodPoints += goodFlags[i];
1261                 }
1262
1263                 /*char str[200];
1264                 sprintf(str,"Was num = %d\nNew num=%d",maxGoodPoints,finalGoodPoints);
1265                 MessageBox(0,str,"Info",MB_OK|MB_TASKMODAL);*/
1266
1267                 needRepeat = 0;
1268                 if( finalGoodPoints > maxGoodPoints )
1269                 {
1270                     /* Copy new version of projection matrices */
1271                     cvCopy(&resProjMatrs[0],&bestProjMatrs[0]);
1272                     cvCopy(&resProjMatrs[1],&bestProjMatrs[1]);
1273                     cvCopy(&resProjMatrs[2],&bestProjMatrs[2]);
1274                     memcpy(bestFlags,goodFlags,numPoints*sizeof(char));
1275                     maxGoodPoints = finalGoodPoints;
1276                     needRepeat = 1;
1277                 }
1278
1279                 cvReleaseMat(&optStatus);
1280                 cvReleaseMat(&resPoints4D);
1281
1282
1283 #endif
1284             } while ( needRepeat );
1285
1286             cvFree( &goodFlags);
1287
1288
1289
1290
1291             numProjMatrs = 1;
1292
1293             /* Copy projection matrices */
1294             cvConvert(&bestProjMatrs[0],projMatr1);
1295             cvConvert(&bestProjMatrs[1],projMatr2);
1296             cvConvert(&bestProjMatrs[2],projMatr3);
1297
1298             if( status )
1299             {
1300                 /* copy status for each points if need */
1301                 for( int i = 0; i < numPoints; i++)
1302                 {
1303                     cvmSet(status,0,i,(double)bestFlags[i]);
1304                 }
1305             }
1306         }
1307     }
1308
1309     if( points4D )
1310     {/* Fill reconstructed points */
1311
1312         cvZero(points4D);
1313         icvReconstructPointsFor3View( projMatr1,projMatr2,projMatr3,
1314                                       points[0], points[1], points[2],
1315                                       points4D);
1316     }
1317
1318
1319
1320     __END__;
1321
1322     cvFree( &flags);
1323     cvFree( &bestFlags);
1324
1325     cvReleaseMat(&recPoints4D);
1326     cvReleaseMat(&tmpProjPoints[0]);
1327     cvReleaseMat(&tmpProjPoints[1]);
1328     cvReleaseMat(&tmpProjPoints[2]);
1329
1330     return numProjMatrs;
1331 }
1332
1333 /*==========================================================================================*/
1334
1335 void icvFindBaseTransform(CvMat* points,CvMat* resultT)
1336 {
1337
1338     CV_FUNCNAME( "icvFindBaseTransform" );
1339     __BEGIN__;
1340
1341     if( points == 0 || resultT == 0 )
1342     {
1343         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
1344     }
1345
1346     if( !CV_IS_MAT(points) || !CV_IS_MAT(resultT) )
1347     {
1348         CV_ERROR( CV_StsUnsupportedFormat, "points and resultT must be a matrices" );
1349     }
1350
1351     if( points->rows != 2 || points->cols != 4 )
1352     {
1353         CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be 4. And they must have 2 coordinates" );
1354     }
1355
1356     if( resultT->rows != 3 || resultT->cols != 3 )
1357     {
1358         CV_ERROR( CV_StsUnmatchedSizes, "size of matrix resultT must be 3x3" );
1359     }
1360
1361     /* Function gets four points and compute transformation to e1=(100) e2=(010) e3=(001) e4=(111) */
1362
1363     /* !!! test each three points not collinear. Need to test */
1364
1365     /* Create matrices */
1366     CvMat matrA;
1367     CvMat vectB;
1368     double matrA_dat[3*3];
1369     double vectB_dat[3];
1370     matrA = cvMat(3,3,CV_64F,matrA_dat);
1371     vectB = cvMat(3,1,CV_64F,vectB_dat);
1372
1373     /* fill matrices */
1374     int i;
1375     for( i = 0; i < 3; i++ )
1376     {
1377         cvmSet(&matrA,0,i,cvmGet(points,0,i));
1378         cvmSet(&matrA,1,i,cvmGet(points,1,i));
1379         cvmSet(&matrA,2,i,1);
1380     }
1381
1382     /* Fill vector B */
1383     cvmSet(&vectB,0,0,cvmGet(points,0,3));
1384     cvmSet(&vectB,1,0,cvmGet(points,1,3));
1385     cvmSet(&vectB,2,0,1);
1386
1387     /* result scale */
1388     CvMat scale;
1389     double scale_dat[3];
1390     scale = cvMat(3,1,CV_64F,scale_dat);
1391
1392     cvSolve(&matrA,&vectB,&scale,CV_SVD);
1393
1394     /* multiply by scale */
1395     int j;
1396     for( j = 0; j < 3; j++ )
1397     {
1398         double sc = scale_dat[j];
1399         for( i = 0; i < 3; i++ )
1400         {
1401             matrA_dat[i*3+j] *= sc;
1402         }
1403     }
1404
1405     /* Convert inverse matrix */
1406     CvMat tmpRes;
1407     double tmpRes_dat[9];
1408     tmpRes = cvMat(3,3,CV_64F,tmpRes_dat);
1409     cvInvert(&matrA,&tmpRes);
1410
1411     cvConvert(&tmpRes,resultT);
1412
1413     __END__;
1414
1415     return;
1416 }
1417
1418
1419 /*==========================================================================================*/
1420 void GetGeneratorReduceFundSolution(CvMat* points1,CvMat* points2,CvMat* fundReduceCoef1,CvMat* fundReduceCoef2)
1421 {
1422
1423     CV_FUNCNAME( "GetGeneratorReduceFundSolution" );
1424     __BEGIN__;
1425
1426     /* Test input data for errors */
1427
1428     if( points1 == 0 || points2 == 0 || fundReduceCoef1 == 0 || fundReduceCoef2 == 0)
1429     {
1430         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
1431     }
1432
1433     if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2) || !CV_IS_MAT(fundReduceCoef1) || !CV_IS_MAT(fundReduceCoef2) )
1434     {
1435         CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
1436     }
1437
1438
1439
1440     if( points1->rows != 3 || points1->cols != 3 )
1441     {
1442         CV_ERROR( CV_StsUnmatchedSizes, "Number of points1 must be 3 and and have 3 coordinates" );
1443     }
1444
1445     if( points2->rows != 3 || points2->cols != 3 )
1446     {
1447         CV_ERROR( CV_StsUnmatchedSizes, "Number of points2 must be 3 and and have 3 coordinates" );
1448     }
1449
1450     if( fundReduceCoef1->rows != 1 || fundReduceCoef1->cols != 5 )
1451     {
1452         CV_ERROR( CV_StsUnmatchedSizes, "Size of fundReduceCoef1 must be 1x5" );
1453     }
1454
1455     if( fundReduceCoef2->rows != 1 || fundReduceCoef2->cols != 5 )
1456     {
1457         CV_ERROR( CV_StsUnmatchedSizes, "Size of fundReduceCoef2 must be 1x5" );
1458     }
1459
1460     /* Using 3 corr. points compute reduce */
1461
1462     /* Create matrix */
1463     CvMat matrA;
1464     double matrA_dat[3*5];
1465     matrA = cvMat(3,5,CV_64F,matrA_dat);
1466     int i;
1467     for( i = 0; i < 3; i++ )
1468     {
1469         double x1,y1,w1,x2,y2,w2;
1470         x1 = cvmGet(points1,0,i);
1471         y1 = cvmGet(points1,1,i);
1472         w1 = cvmGet(points1,2,i);
1473
1474         x2 = cvmGet(points2,0,i);
1475         y2 = cvmGet(points2,1,i);
1476         w2 = cvmGet(points2,2,i);
1477
1478         cvmSet(&matrA,i,0,y1*x2-y1*w2);
1479         cvmSet(&matrA,i,1,w1*x2-y1*w2);
1480         cvmSet(&matrA,i,2,x1*y2-y1*w2);
1481         cvmSet(&matrA,i,3,w1*y2-y1*w2);
1482         cvmSet(&matrA,i,4,x1*w2-y1*w2);
1483     }
1484
1485     /* solve system using svd */
1486     CvMat matrU;
1487     CvMat matrW;
1488     CvMat matrV;
1489
1490     double matrU_dat[3*3];
1491     double matrW_dat[3*5];
1492     double matrV_dat[5*5];
1493
1494     matrU = cvMat(3,3,CV_64F,matrU_dat);
1495     matrW = cvMat(3,5,CV_64F,matrW_dat);
1496     matrV = cvMat(5,5,CV_64F,matrV_dat);
1497
1498     /* From svd we need just two last vectors of V or two last row V' */
1499     /* We get transposed matrixes U and V */
1500
1501     cvSVD(&matrA,&matrW,0,&matrV,CV_SVD_V_T);
1502
1503     /* copy results to fundamental matrices */
1504     for(i=0;i<5;i++)
1505     {
1506         cvmSet(fundReduceCoef1,0,i,cvmGet(&matrV,3,i));
1507         cvmSet(fundReduceCoef2,0,i,cvmGet(&matrV,4,i));
1508     }
1509
1510     __END__;
1511     return;
1512
1513 }
1514
1515 /*==========================================================================================*/
1516
1517 int GetGoodReduceFundamMatrFromTwo(CvMat* fundReduceCoef1,CvMat* fundReduceCoef2,CvMat* resFundReduceCoef)
1518 {
1519     int numRoots = 0;
1520
1521     CV_FUNCNAME( "GetGoodReduceFundamMatrFromTwo" );
1522     __BEGIN__;
1523
1524     if( fundReduceCoef1 == 0 || fundReduceCoef2 == 0 || resFundReduceCoef == 0 )
1525     {
1526         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
1527     }
1528
1529     if( !CV_IS_MAT(fundReduceCoef1) || !CV_IS_MAT(fundReduceCoef2) || !CV_IS_MAT(resFundReduceCoef) )
1530     {
1531         CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
1532     }
1533
1534     /* using two fundamental matrix comute matrixes for det(F)=0 */
1535     /* May compute 1 or 3 matrices. Returns number of solutions */
1536     /* Here we will use case F=a*F1+(1-a)*F2  instead of F=m*F1+l*F2 */
1537
1538     /* Test for errors */
1539     if( fundReduceCoef1->rows != 1 || fundReduceCoef1->cols != 5 )
1540     {
1541         CV_ERROR( CV_StsUnmatchedSizes, "Size of fundReduceCoef1 must be 1x5" );
1542     }
1543
1544     if( fundReduceCoef2->rows != 1 || fundReduceCoef2->cols != 5 )
1545     {
1546         CV_ERROR( CV_StsUnmatchedSizes, "Size of fundReduceCoef2 must be 1x5" );
1547     }
1548
1549     if( (resFundReduceCoef->rows != 1 && resFundReduceCoef->rows != 3)  || resFundReduceCoef->cols != 5 )
1550     {
1551         CV_ERROR( CV_StsUnmatchedSizes, "Size of resFundReduceCoef must be 1x5" );
1552     }
1553
1554     double p1,q1,r1,s1,t1;
1555     double p2,q2,r2,s2,t2;
1556     p1 = cvmGet(fundReduceCoef1,0,0);
1557     q1 = cvmGet(fundReduceCoef1,0,1);
1558     r1 = cvmGet(fundReduceCoef1,0,2);
1559     s1 = cvmGet(fundReduceCoef1,0,3);
1560     t1 = cvmGet(fundReduceCoef1,0,4);
1561
1562     p2 = cvmGet(fundReduceCoef2,0,0);
1563     q2 = cvmGet(fundReduceCoef2,0,1);
1564     r2 = cvmGet(fundReduceCoef2,0,2);
1565     s2 = cvmGet(fundReduceCoef2,0,3);
1566     t2 = cvmGet(fundReduceCoef2,0,4);
1567
1568     /* solve equation */
1569     CvMat result;
1570     CvMat coeffs;
1571     double result_dat[2*3];
1572     double coeffs_dat[4];
1573     result = cvMat(2,3,CV_64F,result_dat);
1574     coeffs = cvMat(1,4,CV_64F,coeffs_dat);
1575
1576     coeffs_dat[0] = ((r1-r2)*(-p1-q1-r1-s1-t1+p2+q2+r2+s2+t2)*(q1-q2)+(p1-p2)*(s1-s2)*(t1-t2));/* *a^3 */
1577     coeffs_dat[1] = ((r2*(-p1-q1-r1-s1-t1+p2+q2+r2+s2+t2)+(r1-r2)*(-p2-q2-r2-s2-t2))*(q1-q2)+(r1-r2)*(-p1-q1-r1-s1-t1+p2+q2+r2+s2+t2)*q2+(p2*(s1-s2)+(p1-p2)*s2)*(t1-t2)+(p1-p2)*(s1-s2)*t2);/* *a^2 */
1578     coeffs_dat[2] = (r2*(-p2-q2-r2-s2-t2)*(q1-q2)+(r2*(-p1-q1-r1-s1-t1+p2+q2+r2+s2+t2)+(r1-r2)*(-p2-q2-r2-s2-t2))*q2+p2*s2*(t1-t2)+(p2*(s1-s2)+(p1-p2)*s2)*t2);/* *a */
1579     coeffs_dat[3] = r2*(-p2-q2-r2-s2-t2)*q2+p2*s2*t2;/* 1 */
1580
1581     int num;
1582     num = cvSolveCubic(&coeffs,&result);
1583
1584
1585     /* test number of solutions and test for real solutions */
1586     int i;
1587     for( i = 0; i < num; i++ )
1588     {
1589         if( fabs(cvmGet(&result,1,i)) < 1e-8 )
1590         {
1591             double alpha = cvmGet(&result,0,i);
1592             int j;
1593             for( j = 0; j < 5; j++ )
1594             {
1595                 cvmSet(resFundReduceCoef,numRoots,j,
1596                     alpha * cvmGet(fundReduceCoef1,0,j) + (1-alpha) * cvmGet(fundReduceCoef2,0,j) );
1597             }
1598             numRoots++;
1599         }
1600     }
1601
1602     __END__;
1603     return numRoots;
1604 }
1605
1606 /*==========================================================================================*/
1607
1608 void GetProjMatrFromReducedFundamental(CvMat* fundReduceCoefs,CvMat* projMatrCoefs)
1609 {
1610     CV_FUNCNAME( "GetProjMatrFromReducedFundamental" );
1611     __BEGIN__;
1612
1613     /* Test for errors */
1614     if( fundReduceCoefs == 0 || projMatrCoefs == 0 )
1615     {
1616         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
1617     }
1618
1619     if( !CV_IS_MAT(fundReduceCoefs) || !CV_IS_MAT(projMatrCoefs) )
1620     {
1621         CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
1622     }
1623
1624
1625     if( fundReduceCoefs->rows != 1 || fundReduceCoefs->cols != 5 )
1626     {
1627         CV_ERROR( CV_StsUnmatchedSizes, "Size of fundReduceCoefs must be 1x5" );
1628     }
1629
1630     if( projMatrCoefs->rows != 1 || projMatrCoefs->cols != 4 )
1631     {
1632         CV_ERROR( CV_StsUnmatchedSizes, "Size of projMatrCoefs must be 1x4" );
1633     }
1634
1635     /* Computes project matrix from given reduced matrix */
1636     /* we have p,q,r,s,t and need get a,b,c,d */
1637     /* Fill matrix to compute ratio a:b:c as A:B:C */
1638
1639     CvMat matrA;
1640     double matrA_dat[3*3];
1641     matrA = cvMat(3,3,CV_64F,matrA_dat);
1642
1643     double p,q,r,s,t;
1644     p = cvmGet(fundReduceCoefs,0,0);
1645     q = cvmGet(fundReduceCoefs,0,1);
1646     r = cvmGet(fundReduceCoefs,0,2);
1647     s = cvmGet(fundReduceCoefs,0,3);
1648     t = cvmGet(fundReduceCoefs,0,4);
1649
1650     matrA_dat[0] = p;
1651     matrA_dat[1] = r;
1652     matrA_dat[2] = 0;
1653
1654     matrA_dat[3] = q;
1655     matrA_dat[4] = 0;
1656     matrA_dat[5] = t;
1657
1658     matrA_dat[6] = 0;
1659     matrA_dat[7] = s;
1660     matrA_dat[8] = -(p+q+r+s+t);
1661
1662     CvMat matrU;
1663     CvMat matrW;
1664     CvMat matrV;
1665
1666     double matrU_dat[3*3];
1667     double matrW_dat[3*3];
1668     double matrV_dat[3*3];
1669
1670     matrU = cvMat(3,3,CV_64F,matrU_dat);
1671     matrW = cvMat(3,3,CV_64F,matrW_dat);
1672     matrV = cvMat(3,3,CV_64F,matrV_dat);
1673
1674     /* From svd we need just last vector of V or last row V' */
1675     /* We get transposed matrixes U and V */
1676
1677     cvSVD(&matrA,&matrW,0,&matrV,CV_SVD_V_T);
1678
1679     double A1,B1,C1;
1680     A1 = matrV_dat[6];
1681     B1 = matrV_dat[7];
1682     C1 = matrV_dat[8];
1683
1684     /* Get second coeffs */
1685     matrA_dat[0] = 0;
1686     matrA_dat[1] = r;
1687     matrA_dat[2] = t;
1688
1689     matrA_dat[3] = p;
1690     matrA_dat[4] = 0;
1691     matrA_dat[5] = -(p+q+r+s+t);
1692
1693     matrA_dat[6] = q;
1694     matrA_dat[7] = s;
1695     matrA_dat[8] = 0;
1696
1697     cvSVD(&matrA,&matrW,0,&matrV,CV_SVD_V_T);
1698
1699     double A2,B2,C2;
1700     A2 = matrV_dat[6];
1701     B2 = matrV_dat[7];
1702     C2 = matrV_dat[8];
1703
1704     double a,b,c,d;
1705     {
1706         CvMat matrK;
1707         double matrK_dat[36];
1708         matrK = cvMat(6,6,CV_64F,matrK_dat);
1709         cvZero(&matrK);
1710
1711         matrK_dat[0]  = 1;
1712         matrK_dat[7]  = 1;
1713         matrK_dat[14] = 1;
1714
1715         matrK_dat[18] = -1;
1716         matrK_dat[25] = -1;
1717         matrK_dat[32] = -1;
1718
1719         matrK_dat[21] = 1;
1720         matrK_dat[27] = 1;
1721         matrK_dat[33] = 1;
1722
1723         matrK_dat[0*6+4] = -A1;
1724         matrK_dat[1*6+4] = -B1;
1725         matrK_dat[2*6+4] = -C1;
1726
1727         matrK_dat[3*6+5] = -A2;
1728         matrK_dat[4*6+5] = -B2;
1729         matrK_dat[5*6+5] = -C2;
1730
1731         CvMat matrU;
1732         CvMat matrW;
1733         CvMat matrV;
1734
1735         double matrU_dat[36];
1736         double matrW_dat[36];
1737         double matrV_dat[36];
1738
1739         matrU = cvMat(6,6,CV_64F,matrU_dat);
1740         matrW = cvMat(6,6,CV_64F,matrW_dat);
1741         matrV = cvMat(6,6,CV_64F,matrV_dat);
1742
1743         /* From svd we need just last vector of V or last row V' */
1744         /* We get transposed matrixes U and V */
1745
1746         cvSVD(&matrK,&matrW,0,&matrV,CV_SVD_V_T);
1747
1748         a = matrV_dat[6*5+0];
1749         b = matrV_dat[6*5+1];
1750         c = matrV_dat[6*5+2];
1751         d = matrV_dat[6*5+3];
1752         /* we don't need last two coefficients. Because it just a k1,k2 */
1753
1754         cvmSet(projMatrCoefs,0,0,a);
1755         cvmSet(projMatrCoefs,0,1,b);
1756         cvmSet(projMatrCoefs,0,2,c);
1757         cvmSet(projMatrCoefs,0,3,d);
1758
1759     }
1760
1761     __END__;
1762     return;
1763 }
1764
1765 /*==========================================================================================*/
1766
1767 void icvComputeProjectMatrix(CvMat* objPoints,CvMat* projPoints,CvMat* projMatr)
1768 {/* Using SVD method */
1769
1770     /* Reconstruct points using object points and projected points */
1771     /* Number of points must be >=6 */
1772
1773     CvMat matrV;
1774     CvMat* matrA = 0;
1775     CvMat* matrW = 0;
1776     CvMat* workProjPoints = 0;
1777     CvMat* tmpProjPoints = 0;
1778
1779     CV_FUNCNAME( "icvComputeProjectMatrix" );
1780     __BEGIN__;
1781
1782     /* Test for errors */
1783     if( objPoints == 0 || projPoints == 0 || projMatr == 0)
1784     {
1785         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
1786     }
1787
1788     if( !CV_IS_MAT(objPoints) || !CV_IS_MAT(projPoints) || !CV_IS_MAT(projMatr) )
1789     {
1790         CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
1791     }
1792
1793     if( projMatr->rows != 3 || projMatr->cols != 4 )
1794     {
1795         CV_ERROR( CV_StsUnmatchedSizes, "Size of projMatr must be 3x4" );
1796     }
1797
1798     int numPoints;
1799     numPoints = projPoints->cols;
1800     if( numPoints < 6 )
1801     {
1802         CV_ERROR( CV_StsOutOfRange, "Number of points must be at least 6" );
1803     }
1804
1805     if( numPoints != objPoints->cols )
1806     {
1807         CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be same" );
1808     }
1809
1810     if( objPoints->rows != 4 )
1811     {
1812         CV_ERROR( CV_StsUnmatchedSizes, "Object points must have 4 coordinates" );
1813     }
1814
1815     if( projPoints->rows != 3 &&  projPoints->rows != 2 )
1816     {
1817         CV_ERROR( CV_StsUnmatchedSizes, "Projected points must have 2 or 3 coordinates" );
1818     }
1819
1820     /* Create and fill matrix A */
1821     CV_CALL( matrA = cvCreateMat(numPoints*3, 12, CV_64F) );
1822     CV_CALL( matrW = cvCreateMat(numPoints*3, 12, CV_64F) );
1823
1824     if( projPoints->rows == 2 )
1825     {
1826         CV_CALL( tmpProjPoints = cvCreateMat(3,numPoints,CV_64F) );
1827         cvMake3DPoints(projPoints,tmpProjPoints);
1828         workProjPoints = tmpProjPoints;
1829     }
1830     else
1831     {
1832         workProjPoints = projPoints;
1833     }
1834
1835     double matrV_dat[144];
1836     matrV = cvMat(12,12,CV_64F,matrV_dat);
1837     int i;
1838
1839     char* dat;
1840     dat = (char*)(matrA->data.db);
1841
1842 #if 1
1843     FILE *file;
1844     file = fopen("d:\\test\\recProjMatr.txt","w");
1845
1846 #endif
1847     for( i = 0;i < numPoints; i++ )
1848     {
1849         double x,y,w;
1850         double X,Y,Z,W;
1851         double*  matrDat = (double*)dat;
1852
1853         x = cvmGet(workProjPoints,0,i);
1854         y = cvmGet(workProjPoints,1,i);
1855         w = cvmGet(workProjPoints,2,i);
1856
1857
1858         X = cvmGet(objPoints,0,i);
1859         Y = cvmGet(objPoints,1,i);
1860         Z = cvmGet(objPoints,2,i);
1861         W = cvmGet(objPoints,3,i);
1862
1863 #if 1
1864         fprintf(file,"%d (%lf %lf %lf %lf) - (%lf %lf %lf)\n",i,X,Y,Z,W,x,y,w );
1865 #endif
1866
1867 /*---*/
1868         matrDat[ 0] = 0;
1869         matrDat[ 1] = 0;
1870         matrDat[ 2] = 0;
1871         matrDat[ 3] = 0;
1872
1873         matrDat[ 4] = -w*X;
1874         matrDat[ 5] = -w*Y;
1875         matrDat[ 6] = -w*Z;
1876         matrDat[ 7] = -w*W;
1877
1878         matrDat[ 8] = y*X;
1879         matrDat[ 9] = y*Y;
1880         matrDat[10] = y*Z;
1881         matrDat[11] = y*W;
1882 /*---*/
1883         matrDat[12] = w*X;
1884         matrDat[13] = w*Y;
1885         matrDat[14] = w*Z;
1886         matrDat[15] = w*W;
1887
1888         matrDat[16] = 0;
1889         matrDat[17] = 0;
1890         matrDat[18] = 0;
1891         matrDat[19] = 0;
1892
1893         matrDat[20] = -x*X;
1894         matrDat[21] = -x*Y;
1895         matrDat[22] = -x*Z;
1896         matrDat[23] = -x*W;
1897 /*---*/
1898         matrDat[24] = -y*X;
1899         matrDat[25] = -y*Y;
1900         matrDat[26] = -y*Z;
1901         matrDat[27] = -y*W;
1902
1903         matrDat[28] = x*X;
1904         matrDat[29] = x*Y;
1905         matrDat[30] = x*Z;
1906         matrDat[31] = x*W;
1907
1908         matrDat[32] = 0;
1909         matrDat[33] = 0;
1910         matrDat[34] = 0;
1911         matrDat[35] = 0;
1912 /*---*/
1913         dat += (matrA->step)*3;
1914     }
1915 #if 1
1916     fclose(file);
1917
1918 #endif
1919
1920     /* Solve this system */
1921
1922     /* From svd we need just last vector of V or last row V' */
1923     /* We get transposed matrix V */
1924
1925     cvSVD(matrA,matrW,0,&matrV,CV_SVD_V_T);
1926
1927     /* projected matrix was computed */
1928     for( i = 0; i < 12; i++ )
1929     {
1930         cvmSet(projMatr,i/4,i%4,cvmGet(&matrV,11,i));
1931     }
1932
1933     cvReleaseMat(&matrA);
1934     cvReleaseMat(&matrW);
1935     cvReleaseMat(&tmpProjPoints);
1936     __END__;
1937 }
1938
1939
1940 /*==========================================================================================*/
1941 /*  May be useless function */
1942 void icvComputeTransform4D(CvMat* points1,CvMat* points2,CvMat* transMatr)
1943 {
1944     CvMat* matrA = 0;
1945     CvMat* matrW = 0;
1946
1947     double matrV_dat[256];
1948     CvMat  matrV = cvMat(16,16,CV_64F,matrV_dat);
1949
1950     CV_FUNCNAME( "icvComputeTransform4D" );
1951     __BEGIN__;
1952
1953     if( points1 == 0 || points2 == 0 || transMatr == 0)
1954     {
1955         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
1956     }
1957
1958     if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2) || !CV_IS_MAT(transMatr) )
1959     {
1960         CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
1961     }
1962
1963     /* Computes transformation matrix (4x4) for points1 -> points2 */
1964     /* p2=H*p1 */
1965
1966     /* Test for errors */
1967     int numPoints;
1968     numPoints = points1->cols;
1969
1970     /* we must have at least 5 points */
1971     if( numPoints < 5 )
1972     {
1973         CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be at least 5" );
1974     }
1975
1976     if( numPoints != points2->cols )
1977     {
1978         CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be the same" );
1979     }
1980
1981     if( transMatr->rows != 4 || transMatr->cols != 4 )
1982     {
1983         CV_ERROR( CV_StsUnmatchedSizes, "Size of transMatr must be 4x4" );
1984     }
1985
1986     if( points1->rows != 4 || points2->rows != 4 )
1987     {
1988         CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of points must be 4" );
1989     }
1990
1991     /* Create matrix */
1992     CV_CALL( matrA = cvCreateMat(6*numPoints,16,CV_64F) );
1993     CV_CALL( matrW = cvCreateMat(6*numPoints,16,CV_64F) );
1994
1995     cvZero(matrA);
1996
1997     /* Fill matrices */
1998     int i;
1999     for( i = 0; i < numPoints; i++ )/* For each point */
2000     {
2001         double X1,Y1,Z1,W1;
2002         double P[4];
2003
2004         P[0] = cvmGet(points1,0,i);
2005         P[1] = cvmGet(points1,1,i);
2006         P[2] = cvmGet(points1,2,i);
2007         P[3] = cvmGet(points1,3,i);
2008
2009         X1 = cvmGet(points2,0,i);
2010         Y1 = cvmGet(points2,1,i);
2011         Z1 = cvmGet(points2,2,i);
2012         W1 = cvmGet(points2,3,i);
2013
2014         /* Fill matrA */
2015         for( int j = 0; j < 4; j++ )/* For each coordinate */
2016         {
2017             double x,y,z,w;
2018
2019             x = X1*P[j];
2020             y = Y1*P[j];
2021             z = Z1*P[j];
2022             w = W1*P[j];
2023
2024             cvmSet(matrA,6*i+0,4*0+j,y);
2025             cvmSet(matrA,6*i+0,4*1+j,-x);
2026
2027             cvmSet(matrA,6*i+1,4*0+j,z);
2028             cvmSet(matrA,6*i+1,4*2+j,-x);
2029
2030             cvmSet(matrA,6*i+2,4*0+j,w);
2031             cvmSet(matrA,6*i+2,4*3+j,-x);
2032
2033             cvmSet(matrA,6*i+3,4*1+j,-z);
2034             cvmSet(matrA,6*i+3,4*2+j,y);
2035
2036             cvmSet(matrA,6*i+4,4*1+j,-w);
2037             cvmSet(matrA,6*i+4,4*3+j,y);
2038
2039             cvmSet(matrA,6*i+5,4*2+j,-w);
2040             cvmSet(matrA,6*i+5,4*3+j,z);
2041         }
2042     }
2043
2044     /* From svd we need just two last vectors of V or two last row V' */
2045     /* We get transposed matrixes U and V */
2046
2047     cvSVD(matrA,matrW,0,&matrV,CV_SVD_V_T);
2048
2049     /* Copy result to result matrix */
2050     for( i = 0; i < 16; i++ )
2051     {
2052         cvmSet(transMatr,i/4,i%4,cvmGet(&matrV,15,i));
2053     }
2054
2055     cvReleaseMat(&matrA);
2056     cvReleaseMat(&matrW);
2057
2058     __END__;
2059     return;
2060 }
2061
2062 /*==========================================================================================*/
2063
2064 void icvReconstructPointsFor3View( CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
2065                                 CvMat* projPoints1,CvMat* projPoints2,CvMat* projPoints3,
2066                                 CvMat* points4D)
2067 {
2068     CV_FUNCNAME( "icvReconstructPointsFor3View" );
2069     __BEGIN__;
2070
2071     if( projMatr1 == 0 || projMatr2 == 0 || projMatr3 == 0 ||
2072         projPoints1 == 0 || projPoints2 == 0 || projPoints3 == 0 ||
2073         points4D == 0)
2074     {
2075         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
2076     }
2077
2078     if( !CV_IS_MAT(projMatr1) || !CV_IS_MAT(projMatr2) || !CV_IS_MAT(projMatr3) ||
2079         !CV_IS_MAT(projPoints1) || !CV_IS_MAT(projPoints2) || !CV_IS_MAT(projPoints3)  ||
2080         !CV_IS_MAT(points4D) )
2081     {
2082         CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
2083     }
2084
2085     int numPoints;
2086     numPoints = projPoints1->cols;
2087
2088     if( numPoints < 1 )
2089     {
2090         CV_ERROR( CV_StsOutOfRange, "Number of points must be more than zero" );
2091     }
2092
2093     if( projPoints2->cols != numPoints || projPoints3->cols != numPoints || points4D->cols != numPoints )
2094     {
2095         CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be the same" );
2096     }
2097
2098     if( projPoints1->rows != 2 || projPoints2->rows != 2 || projPoints3->rows != 2)
2099     {
2100         CV_ERROR( CV_StsUnmatchedSizes, "Number of proj points coordinates must be == 2" );
2101     }
2102
2103     if( points4D->rows != 4 )
2104     {
2105         CV_ERROR( CV_StsUnmatchedSizes, "Number of world points coordinates must be == 4" );
2106     }
2107
2108     if( projMatr1->cols != 4 || projMatr1->rows != 3 ||
2109         projMatr2->cols != 4 || projMatr2->rows != 3 ||
2110         projMatr3->cols != 4 || projMatr3->rows != 3)
2111     {
2112         CV_ERROR( CV_StsUnmatchedSizes, "Size of projection matrices must be 3x4" );
2113     }
2114
2115     CvMat matrA;
2116     double matrA_dat[36];
2117     matrA = cvMat(9,4,CV_64F,matrA_dat);
2118
2119     //CvMat matrU;
2120     CvMat matrW;
2121     CvMat matrV;
2122     //double matrU_dat[9*9];
2123     double matrW_dat[9*4];
2124     double matrV_dat[4*4];
2125
2126     //matrU = cvMat(9,9,CV_64F,matrU_dat);
2127     matrW = cvMat(9,4,CV_64F,matrW_dat);
2128     matrV = cvMat(4,4,CV_64F,matrV_dat);
2129
2130     CvMat* projPoints[3];
2131     CvMat* projMatrs[3];
2132
2133     projPoints[0] = projPoints1;
2134     projPoints[1] = projPoints2;
2135     projPoints[2] = projPoints3;
2136
2137     projMatrs[0] = projMatr1;
2138     projMatrs[1] = projMatr2;
2139     projMatrs[2] = projMatr3;
2140
2141     /* Solve system for each point */
2142     int i,j;
2143     for( i = 0; i < numPoints; i++ )/* For each point */
2144     {
2145         /* Fill matrix for current point */
2146         for( j = 0; j < 3; j++ )/* For each view */
2147         {
2148             double x,y;
2149             x = cvmGet(projPoints[j],0,i);
2150             y = cvmGet(projPoints[j],1,i);
2151             for( int k = 0; k < 4; k++ )
2152             {
2153                 cvmSet(&matrA, j*3+0, k, x * cvmGet(projMatrs[j],2,k) -     cvmGet(projMatrs[j],0,k) );
2154                 cvmSet(&matrA, j*3+1, k, y * cvmGet(projMatrs[j],2,k) -     cvmGet(projMatrs[j],1,k) );
2155                 cvmSet(&matrA, j*3+2, k, x * cvmGet(projMatrs[j],1,k) - y * cvmGet(projMatrs[j],0,k) );
2156             }
2157         }
2158         /* Solve system for current point */
2159         {
2160             cvSVD(&matrA,&matrW,0,&matrV,CV_SVD_V_T);
2161
2162             /* Copy computed point */
2163             cvmSet(points4D,0,i,cvmGet(&matrV,3,0));/* X */
2164             cvmSet(points4D,1,i,cvmGet(&matrV,3,1));/* Y */
2165             cvmSet(points4D,2,i,cvmGet(&matrV,3,2));/* Z */
2166             cvmSet(points4D,3,i,cvmGet(&matrV,3,3));/* W */
2167         }
2168     }
2169
2170     /* Points was reconstructed. Try to reproject points */
2171     /* We can compute reprojection error if need */
2172     {
2173         int i;
2174         CvMat point3D;
2175         double point3D_dat[4];
2176         point3D = cvMat(4,1,CV_64F,point3D_dat);
2177
2178         CvMat point2D;
2179         double point2D_dat[3];
2180         point2D = cvMat(3,1,CV_64F,point2D_dat);
2181
2182         for( i = 0; i < numPoints; i++ )
2183         {
2184             double W = cvmGet(points4D,3,i);
2185
2186             point3D_dat[0] = cvmGet(points4D,0,i)/W;
2187             point3D_dat[1] = cvmGet(points4D,1,i)/W;
2188             point3D_dat[2] = cvmGet(points4D,2,i)/W;
2189             point3D_dat[3] = 1;
2190
2191                 /* !!! Project this point for each camera */
2192                 for( int currCamera = 0; currCamera < 3; currCamera++ )
2193                 {
2194                     cvmMul(projMatrs[currCamera], &point3D, &point2D);
2195
2196                     float x,y;
2197                     float xr,yr,wr;
2198                     x = (float)cvmGet(projPoints[currCamera],0,i);
2199                     y = (float)cvmGet(projPoints[currCamera],1,i);
2200
2201                     wr = (float)point2D_dat[2];
2202                     xr = (float)(point2D_dat[0]/wr);
2203                     yr = (float)(point2D_dat[1]/wr);
2204
2205                     float deltaX,deltaY;
2206                     deltaX = (float)fabs(x-xr);
2207                     deltaY = (float)fabs(y-yr);
2208                 }
2209         }
2210     }
2211
2212     __END__;
2213     return;
2214 }
2215
2216
2217
2218
2219 #if 0
2220 void ReconstructPointsFor3View_bySolve( CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
2221                                 CvMat* projPoints1,CvMat* projPoints2,CvMat* projPoints3,
2222                                 CvMat* points3D)
2223 {
2224     CV_FUNCNAME( "ReconstructPointsFor3View" );
2225     __BEGIN__;
2226
2227
2228     int numPoints;
2229     numPoints = projPoints1->cols;
2230     if( projPoints2->cols != numPoints || projPoints3->cols != numPoints || points3D->cols != numPoints )
2231     {
2232         CV_ERROR( CV_StsUnmatchedSizes, "Number of points must be the same" );
2233     }
2234
2235     if( projPoints1->rows != 2 || projPoints2->rows != 2 || projPoints3->rows != 2)
2236     {
2237         CV_ERROR( CV_StsUnmatchedSizes, "Number of proj points coordinates must be == 2" );
2238     }
2239
2240     if( points3D->rows != 4 )
2241     {
2242         CV_ERROR( CV_StsUnmatchedSizes, "Number of world points coordinates must be == 4" );
2243     }
2244
2245     if( projMatr1->cols != 4 || projMatr1->rows != 3 ||
2246         projMatr2->cols != 4 || projMatr2->rows != 3 ||
2247         projMatr3->cols != 4 || projMatr3->rows != 3)
2248     {
2249         CV_ERROR( CV_StsUnmatchedSizes, "Size of proj matrix must be 3x4" );
2250     }
2251
2252     CvMat matrA;
2253     double matrA_dat[3*3*3];
2254     matrA = cvMat(3*3,3,CV_64F,matrA_dat);
2255
2256     CvMat vectB;
2257     double vectB_dat[9];
2258     vectB = cvMat(9,1,CV_64F,vectB_dat);
2259
2260     CvMat result;
2261     double result_dat[3];
2262     result = cvMat(3,1,CV_64F,result_dat);
2263
2264     CvMat* projPoints[3];
2265     CvMat* projMatrs[3];
2266
2267     projPoints[0] = projPoints1;
2268     projPoints[1] = projPoints2;
2269     projPoints[2] = projPoints3;
2270
2271     projMatrs[0] = projMatr1;
2272     projMatrs[1] = projMatr2;
2273     projMatrs[2] = projMatr3;
2274
2275     /* Solve system for each point */
2276     int i,j;
2277     for( i = 0; i < numPoints; i++ )/* For each point */
2278     {
2279         /* Fill matrix for current point */
2280         for( j = 0; j < 3; j++ )/* For each view */
2281         {
2282             double x,y;
2283             x = cvmGet(projPoints[j],0,i);
2284             y = cvmGet(projPoints[j],1,i);
2285
2286             cvmSet(&vectB,j*3+0,0,x-cvmGet(projMatrs[j],0,3));
2287             cvmSet(&vectB,j*3+1,0,y-cvmGet(projMatrs[j],1,3));
2288             cvmSet(&vectB,j*3+2,0,1-cvmGet(projMatrs[j],2,3));
2289
2290             for( int t = 0; t < 3; t++ )
2291             {
2292                 for( int k = 0; k < 3; k++ )
2293                 {
2294                     cvmSet(&matrA, j*3+t, k, cvmGet(projMatrs[j],t,k) );
2295                 }
2296             }
2297         }
2298
2299
2300         /* Solve system for current point */
2301         cvSolve(&matrA,&vectB,&result,CV_SVD);
2302
2303         cvmSet(points3D,0,i,result_dat[0]);/* X */
2304         cvmSet(points3D,1,i,result_dat[1]);/* Y */
2305         cvmSet(points3D,2,i,result_dat[2]);/* Z */
2306         cvmSet(points3D,3,i,1);/* W */
2307
2308     }
2309
2310     /* Points was reconstructed. Try to reproject points */
2311     {
2312         int i;
2313         CvMat point3D;
2314         double point3D_dat[4];
2315         point3D = cvMat(4,1,CV_64F,point3D_dat);
2316
2317         CvMat point2D;
2318         double point2D_dat[3];
2319         point2D = cvMat(3,1,CV_64F,point2D_dat);
2320
2321         for( i = 0; i < numPoints; i++ )
2322         {
2323             double W = cvmGet(points3D,3,i);
2324
2325             point3D_dat[0] = cvmGet(points3D,0,i)/W;
2326             point3D_dat[1] = cvmGet(points3D,1,i)/W;
2327             point3D_dat[2] = cvmGet(points3D,2,i)/W;
2328             point3D_dat[3] = 1;
2329
2330                 /* Project this point for each camera */
2331                 for( int currCamera = 0; currCamera < 3; currCamera++ )
2332                 {
2333                     cvmMul(projMatrs[currCamera], &point3D, &point2D);
2334                     float x,y;
2335                     float xr,yr,wr;
2336                     x = (float)cvmGet(projPoints[currCamera],0,i);
2337                     y = (float)cvmGet(projPoints[currCamera],1,i);
2338
2339                     wr = (float)point2D_dat[2];
2340                     xr = (float)(point2D_dat[0]/wr);
2341                     yr = (float)(point2D_dat[1]/wr);
2342
2343                 }
2344         }
2345     }
2346
2347     __END__;
2348     return;
2349 }
2350 #endif
2351
2352 /*==========================================================================================*/
2353
2354 void icvComputeCameraExrinnsicByPosition(CvMat* camPos, CvMat* rotMatr, CvMat* transVect)
2355 {
2356     /* We know position of camera. we must to compute rotate matrix and translate vector */
2357
2358     CV_FUNCNAME( "icvComputeCameraExrinnsicByPosition" );
2359     __BEGIN__;
2360
2361     /* Test input paramaters */
2362     if( camPos == 0 || rotMatr == 0 || transVect == 0 )
2363     {
2364         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
2365     }
2366
2367     if( !CV_IS_MAT(camPos) || !CV_IS_MAT(rotMatr) || !CV_IS_MAT(transVect) )
2368     {
2369         CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
2370     }
2371
2372     if( camPos->cols != 1 || camPos->rows != 3 )
2373     {
2374         CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of camera position must be 3x1 vector" );
2375     }
2376
2377     if( rotMatr->cols != 3 || rotMatr->rows != 3 )
2378     {
2379         CV_ERROR( CV_StsUnmatchedSizes, "Rotate matrix must be 3x3" );
2380     }
2381
2382     if( transVect->cols != 1 || transVect->rows != 3 )
2383     {
2384         CV_ERROR( CV_StsUnmatchedSizes, "Translate vector must be 3x1" );
2385     }
2386
2387     double x,y,z;
2388     x = cvmGet(camPos,0,0);
2389     y = cvmGet(camPos,1,0);
2390     z = cvmGet(camPos,2,0);
2391
2392     /* Set translate vector. It same as camea position */
2393     cvmSet(transVect,0,0,x);
2394     cvmSet(transVect,1,0,y);
2395     cvmSet(transVect,2,0,z);
2396
2397     /* Compute rotate matrix. Compute each unit transformed vector */
2398
2399     /* normalize flat direction x,y */
2400     double vectorX[3];
2401     double vectorY[3];
2402     double vectorZ[3];
2403
2404     vectorX[0] = -z;
2405     vectorX[1] =  0;
2406     vectorX[2] =  x;
2407
2408     vectorY[0] =  x*y;
2409     vectorY[1] =  x*x+z*z;
2410     vectorY[2] =  z*y;
2411
2412     vectorZ[0] = -x;
2413     vectorZ[1] = -y;
2414     vectorZ[2] = -z;
2415
2416     /* normaize vectors */
2417     double norm;
2418     int i;
2419
2420     /* Norm X */
2421     norm = 0;
2422     for( i = 0; i < 3; i++ )
2423         norm += vectorX[i]*vectorX[i];
2424     norm = sqrt(norm);
2425     for( i = 0; i < 3; i++ )
2426         vectorX[i] /= norm;
2427
2428     /* Norm Y */
2429     norm = 0;
2430     for( i = 0; i < 3; i++ )
2431         norm += vectorY[i]*vectorY[i];
2432     norm = sqrt(norm);
2433     for( i = 0; i < 3; i++ )
2434         vectorY[i] /= norm;
2435
2436     /* Norm Z */
2437     norm = 0;
2438     for( i = 0; i < 3; i++ )
2439         norm += vectorZ[i]*vectorZ[i];
2440     norm = sqrt(norm);
2441     for( i = 0; i < 3; i++ )
2442         vectorZ[i] /= norm;
2443
2444     /* Set output results */
2445
2446     for( i = 0; i < 3; i++ )
2447     {
2448         cvmSet(rotMatr,i,0,vectorX[i]);
2449         cvmSet(rotMatr,i,1,vectorY[i]);
2450         cvmSet(rotMatr,i,2,vectorZ[i]);
2451     }
2452
2453     {/* Try to inverse rotate matrix */
2454         CvMat tmpInvRot;
2455         double tmpInvRot_dat[9];
2456         tmpInvRot = cvMat(3,3,CV_64F,tmpInvRot_dat);
2457         cvInvert(rotMatr,&tmpInvRot,CV_SVD);
2458         cvConvert(&tmpInvRot,rotMatr);
2459
2460
2461
2462     }
2463
2464     __END__;
2465
2466     return;
2467 }
2468
2469 /*==========================================================================================*/
2470
2471 void FindTransformForProjectMatrices(CvMat* projMatr1,CvMat* projMatr2,CvMat* rotMatr,CvMat* transVect)
2472 {
2473     /* Computes homography for project matrix be "canonical" form */
2474     CV_FUNCNAME( "computeProjMatrHomography" );
2475     __BEGIN__;
2476
2477     /* Test input paramaters */
2478     if( projMatr1 == 0 || projMatr2 == 0 || rotMatr == 0 || transVect == 0 )
2479     {
2480         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
2481     }
2482
2483     if( !CV_IS_MAT(projMatr1) || !CV_IS_MAT(projMatr2) || !CV_IS_MAT(rotMatr) || !CV_IS_MAT(transVect) )
2484     {
2485         CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
2486     }
2487
2488     if( projMatr1->cols != 4 || projMatr1->rows != 3 )
2489     {
2490         CV_ERROR( CV_StsUnmatchedSizes, "Size of project matrix 1 must be 3x4" );
2491     }
2492
2493     if( projMatr2->cols != 4 || projMatr2->rows != 3 )
2494     {
2495         CV_ERROR( CV_StsUnmatchedSizes, "Size of project matrix 2 must be 3x4" );
2496     }
2497
2498     if( rotMatr->cols != 3 || rotMatr->rows != 3 )
2499     {
2500         CV_ERROR( CV_StsUnmatchedSizes, "Size of rotation matrix must be 3x3" );
2501     }
2502
2503     if( transVect->cols != 1 || transVect->rows != 3 )
2504     {
2505         CV_ERROR( CV_StsUnmatchedSizes, "Size of translation vector must be 3x1" );
2506     }
2507
2508     CvMat matrA;
2509     double matrA_dat[12*12];
2510     matrA = cvMat(12,12,CV_64F,matrA_dat);
2511     CvMat vectB;
2512     double vectB_dat[12];
2513     vectB = cvMat(12,1,CV_64F,vectB_dat);
2514
2515     cvZero(&matrA);
2516     cvZero(&vectB);
2517     int i,j;
2518     for( i = 0; i < 12; i++ )
2519     {
2520         for( j = 0; j < 12; j++ )
2521         {
2522             cvmSet(&matrA,i,j,cvmGet(projMatr1,i/4,j%4));
2523         }
2524         /* Fill vector B */
2525
2526         double val = cvmGet(projMatr2,i/4,i%4);
2527         if( (i+1)%4 == 0 )
2528         {
2529             val -= cvmGet(projMatr1,i/4,3);
2530
2531         }
2532         cvmSet(&vectB,i,0,val);
2533     }
2534
2535     /* Solve system */
2536     CvMat resVect;
2537     double resVect_dat[12];
2538     resVect = cvMat(12,1,CV_64F,resVect_dat);
2539
2540     int sing;
2541     sing = cvSolve(&matrA,&vectB,&resVect);
2542
2543     /* Fill rotation matrix */
2544     for( i = 0; i < 12; i++ )
2545     {
2546         double val = cvmGet(&resVect,i,0);
2547         if( i < 9 )
2548             cvmSet(rotMatr,i%3,i/3,val);
2549         else
2550             cvmSet(transVect,i-9,0,val);
2551     }
2552
2553     __END__;
2554
2555     return;
2556 }
2557
2558 /*==========================================================================================*/
2559 #if 0
2560 void icvComputeQknowPrincipalPoint(int numImages, CvMat **projMatrs,CvMat *matrQ, double cx,double cy)
2561 {
2562     /* Computes matrix Q */
2563     /* focal x and y eqauls () */
2564     /* we know principal point for camera */
2565     /* focal may differ from image to image */
2566     /* image skew is 0 */
2567
2568     if( numImages < 10 )
2569     {
2570         return;
2571         //Error. Number of images too few
2572     }
2573
2574     /* Create  */
2575
2576
2577     return;
2578 }
2579 #endif
2580
2581 /*==========================================================================================*/
2582
2583 /*==========================================================================================*/
2584 /*==========================================================================================*/
2585 /*==========================================================================================*/
2586 /*==========================================================================================*/
2587 /* Part with metric reconstruction */
2588
2589 #if 1
2590 void icvComputeQ(int numMatr, CvMat** projMatr, CvMat** cameraMatr, CvMat* matrQ)
2591 {
2592     /* K*K' = P*Q*P' */
2593     /* try to solve Q by linear method */
2594
2595     CvMat* matrA = 0;
2596     CvMat* vectB = 0;
2597
2598     CV_FUNCNAME( "ComputeQ" );
2599     __BEGIN__;
2600
2601     /* Define number of projection matrices */
2602     if( numMatr < 2 )
2603     {
2604         CV_ERROR( CV_StsUnmatchedSizes, "Number of projection matrices must be at least 2" );
2605     }
2606
2607
2608     /* test matrices sizes */
2609     if( matrQ->cols != 4 || matrQ->rows != 4 )
2610     {
2611         CV_ERROR( CV_StsUnmatchedSizes, "Size of matrix Q must be 3x3" );
2612     }
2613
2614     int currMatr;
2615     for( currMatr = 0; currMatr < numMatr; currMatr++ )
2616     {
2617
2618         if( cameraMatr[currMatr]->cols != 3 || cameraMatr[currMatr]->rows != 3 )
2619         {
2620             CV_ERROR( CV_StsUnmatchedSizes, "Size of each camera matrix must be 3x3" );
2621         }
2622
2623         if( projMatr[currMatr]->cols != 4 || projMatr[currMatr]->rows != 3 )
2624         {
2625             CV_ERROR( CV_StsUnmatchedSizes, "Size of each camera matrix must be 3x3" );
2626         }
2627     }
2628
2629     CvMat matrw;
2630     double matrw_dat[9];
2631     matrw = cvMat(3,3,CV_64F,matrw_dat);
2632
2633     CvMat matrKt;
2634     double matrKt_dat[9];
2635     matrKt = cvMat(3,3,CV_64F,matrKt_dat);
2636
2637
2638     /* Create matrix A and vector B */
2639     CV_CALL( matrA = cvCreateMat(9*numMatr,10,CV_64F) );
2640     CV_CALL( vectB = cvCreateMat(9*numMatr,1,CV_64F) );
2641
2642     double dataQ[16];
2643
2644     for( currMatr = 0; currMatr < numMatr; currMatr++ )
2645     {
2646         int ord10[10] = {0,1,2,3,5,6,7,10,11,15};
2647         /* Fill atrix A by data from matrices  */
2648
2649         /* Compute matrix w for current camera matrix */
2650         cvTranspose(cameraMatr[currMatr],&matrKt);
2651         cvmMul(cameraMatr[currMatr],&matrKt,&matrw);
2652
2653         /* Fill matrix A and vector B */
2654
2655         int currWi,currWj;
2656         int currMatr;
2657         for( currMatr = 0; currMatr < numMatr; currMatr++ )
2658         {
2659             for( currWi = 0; currWi < 3; currWi++ )
2660             {
2661                 for( currWj = 0; currWj < 3; currWj++ )
2662                 {
2663                     int i,j;
2664                     for( i = 0; i < 4; i++ )
2665                     {
2666                         for( j = 0; j < 4; j++ )
2667                         {
2668                             /* get elements from current projection matrix */
2669                             dataQ[i*4+j] = cvmGet(projMatr[currMatr],currWi,j) *
2670                                            cvmGet(projMatr[currMatr],currWj,i);
2671                         }
2672                     }
2673
2674                     /* we know 16 elements in dataQ move them to matrQ 10 */
2675                     dataQ[1]  += dataQ[4];
2676                     dataQ[2]  += dataQ[8];
2677                     dataQ[3]  += dataQ[12];
2678                     dataQ[6]  += dataQ[9];
2679                     dataQ[7]  += dataQ[13];
2680                     dataQ[11] += dataQ[14];
2681                     /* Now first 10 elements has coeffs */
2682
2683                     /* copy to matrix A */
2684                     for( i = 0; i < 10; i++ )
2685                     {
2686                         cvmSet(matrA,currMatr*9 + currWi*3+currWj,i,dataQ[ord10[i]]);
2687                     }
2688                 }
2689             }
2690
2691             /* Fill vector B */
2692             for( int i = 0; i < 9; i++ )
2693             {
2694                 cvmSet(vectB,currMatr*9+i,0,matrw_dat[i]);
2695             }
2696         }
2697     }
2698
2699     /* Matrix A and vector B filled and we can solve system */
2700
2701     /* Solve system */
2702     CvMat resQ;
2703     double resQ_dat[10];
2704     resQ = cvMat(10,1,CV_64F,resQ_dat);
2705
2706     cvSolve(matrA,vectB,&resQ,CV_SVD);
2707
2708     /* System was solved. We know matrix Q. But we must have condition det Q=0 */
2709     /* Just copy result matrix Q */
2710     {
2711         int curr = 0;
2712         int ord16[16] = {0,1,2,3,1,4,5,6,2,5,7,8,3,6,8,9};
2713
2714         for( int i = 0; i < 4; i++ )
2715         {
2716             for( int j = 0; j < 4; j++ )
2717             {
2718                 cvmSet(matrQ,i,j,resQ_dat[ord16[curr++]]);
2719             }
2720         }
2721     }
2722
2723
2724     __END__;
2725
2726     /* Free allocated memory */
2727     cvReleaseMat(&matrA);
2728     cvReleaseMat(&vectB);
2729
2730     return;
2731 }
2732 #endif
2733 /*-----------------------------------------------------------------------------------------------------*/
2734
2735 void icvDecomposeQ(CvMat* /*matrQ*/,CvMat* /*matrH*/)
2736 {
2737 #if 0
2738     /* Use SVD to decompose matrix Q=H*I*H' */
2739     /* test input data */
2740
2741     CvMat matrW;
2742     CvMat matrU;
2743 //    CvMat matrV;
2744     double matrW_dat[16];
2745     double matrU_dat[16];
2746 //    double matrV_dat[16];
2747
2748     matrW = cvMat(4,4,CV_64F,matrW_dat);
2749     matrU = cvMat(4,4,CV_64F,matrU_dat);
2750 //    matrV = cvMat(4,4,CV_64F,matrV_dat);
2751
2752     cvSVD(matrQ,&matrW,&matrU,0);
2753
2754     double eig[3];
2755     eig[0] = fsqrt(cvmGet(&matrW,0,0));
2756     eig[1] = fsqrt(cvmGet(&matrW,1,1));
2757     eig[2] = fsqrt(cvmGet(&matrW,2,2));
2758
2759     CvMat matrIS;
2760     double matrIS_dat[16];
2761     matrIS =
2762
2763
2764
2765
2766 /* det for matrix Q with q1-q10 */
2767 /*
2768 + q1*q5*q8*q10
2769 - q1*q5*q9*q9
2770 - q1*q6*q6*q10
2771 + 2*q1*q6*q7*q9
2772 - q1*q7*q7*q8
2773 - q2*q2*q8*q10
2774 + q2*q2*q9*q9
2775 + 2*q2*q6*q3*q10
2776 - 2*q2*q6*q4*q9
2777 - 2*q2*q7*q3*q9
2778 + 2*q2*q7*q4*q8
2779 - q5*q3*q3*q10
2780 + 2*q3*q5*q4*q9
2781 + q3*q3*q7*q7
2782 - 2*q3*q7*q4*q6
2783 - q5*q4*q4*q8
2784 + q4*q4*q6*q6
2785 */
2786
2787 //  (1-a)^4 = 1  -  4 * a  +  6 * a * a  -  4 * a * a * a  +  a * a * a * a;
2788
2789
2790 #endif
2791 }
2792