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
58void cvOptimizeLevenbergMarquardtBundle( CvMat** projMatrs, CvMat** observProjPoints,
59                                       CvMat** pointsPres, int numImages,
60                                       CvMat** resultProjMatrs, CvMat* resultPoints4D,int maxIter,double epsilon );
61
62int icvComputeProjectMatrices6Points(  CvMat* points1,CvMat* points2,CvMat* points3,
63                                        CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3);
64
65void icvFindBaseTransform(CvMat* points,CvMat* resultT);
66
67void GetGeneratorReduceFundSolution(CvMat* points1,CvMat* points2,CvMat* fundReduceCoef1,CvMat* fundReduceCoef2);
68
69int GetGoodReduceFundamMatrFromTwo(CvMat* fundReduceCoef1,CvMat* fundReduceCoef2,CvMat* resFundReduceCoef);
70
71void GetProjMatrFromReducedFundamental(CvMat* fundReduceCoefs,CvMat* projMatrCoefs);
72
73void icvComputeProjectMatrix(CvMat* objPoints,CvMat* projPoints,CvMat* projMatr);
74
75void icvComputeTransform4D(CvMat* points1,CvMat* points2,CvMat* transMatr);
76
77int 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
84int 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
91void icvReconstructPointsFor3View( CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
92                                CvMat* projPoints1,CvMat* projPoints2,CvMat* projPoints3,
93                                CvMat* points4D);
94
95void 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
103void 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
119void 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/*
176Computes projection matrices for given 6 points on 3 images
177May returns 3 results. */
178int 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/*==========================================================================================*/
408int 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/*==========================================================================================*/
457void 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/*==========================================================================================*/
504void 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/*==========================================================================================*/
587int 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/*==========================================================================================*/
788int 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
1335void 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/*==========================================================================================*/
1420void 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
1517int 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
1608void 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
1767void 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 */
1942void 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
2064void 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
2220void 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
2354void 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
2471void 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
2560void 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
2590void 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
2735void 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
2793