Update the changelog
[opencv] / cvaux / src / cvepilines.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42
43 #include "_cvaux.h"
44 #include "cvtypes.h"
45 #include <float.h>
46 #include <limits.h>
47 #include "cv.h"
48
49 /* Valery Mosyagin */
50
51 #undef quad
52
53 #define EPS64D 1e-9
54
55 int cvComputeEssentialMatrix(  CvMatr32f rotMatr,
56                                     CvMatr32f transVect,
57                                     CvMatr32f essMatr);
58
59 int cvConvertEssential2Fundamental( CvMatr32f essMatr,
60                                          CvMatr32f fundMatr,
61                                          CvMatr32f cameraMatr1,
62                                          CvMatr32f cameraMatr2);
63
64 int cvComputeEpipolesFromFundMatrix(CvMatr32f fundMatr,
65                                          CvPoint3D32f* epipole1,
66                                          CvPoint3D32f* epipole2);
67
68 void icvTestPoint( CvPoint2D64d testPoint,
69                 CvVect64d line1,CvVect64d line2,
70                 CvPoint2D64d basePoint,
71                 int* result);
72
73
74
75 int icvGetSymPoint3D(  CvPoint3D64d pointCorner,
76                             CvPoint3D64d point1,
77                             CvPoint3D64d point2,
78                             CvPoint3D64d *pointSym2)
79 {
80     double len1,len2;
81     double alpha;
82     icvGetPieceLength3D(pointCorner,point1,&len1);
83     if( len1 < EPS64D )
84     {
85         return CV_BADARG_ERR;
86     }
87     icvGetPieceLength3D(pointCorner,point2,&len2);
88     alpha = len2 / len1;
89
90     pointSym2->x = pointCorner.x + alpha*(point1.x - pointCorner.x);
91     pointSym2->y = pointCorner.y + alpha*(point1.y - pointCorner.y);
92     pointSym2->z = pointCorner.z + alpha*(point1.z - pointCorner.z);
93     return CV_NO_ERR;
94 }
95
96 /*  author Valery Mosyagin */
97
98 /* Compute 3D point for scanline and alpha betta */
99 int icvCompute3DPoint( double alpha,double betta,
100                             CvStereoLineCoeff* coeffs,
101                             CvPoint3D64d* point)
102 {
103
104     double partX;
105     double partY;
106     double partZ;
107     double partAll;
108     double invPartAll;
109
110     double alphabetta = alpha*betta;
111     
112     partAll = alpha - betta;
113     if( fabs(partAll) > 0.00001  ) /* alpha must be > betta */
114     {
115
116         partX   = coeffs->Xcoef        + coeffs->XcoefA *alpha +
117                   coeffs->XcoefB*betta + coeffs->XcoefAB*alphabetta;
118
119         partY   = coeffs->Ycoef        + coeffs->YcoefA *alpha +
120                   coeffs->YcoefB*betta + coeffs->YcoefAB*alphabetta;
121         
122         partZ   = coeffs->Zcoef        + coeffs->ZcoefA *alpha +
123                   coeffs->ZcoefB*betta + coeffs->ZcoefAB*alphabetta;
124
125         invPartAll = 1.0 / partAll;
126
127         point->x = partX * invPartAll;
128         point->y = partY * invPartAll;
129         point->z = partZ * invPartAll;
130         return CV_NO_ERR;
131     }
132     else
133     {
134         return CV_BADFACTOR_ERR;
135     }
136 }
137
138 /*--------------------------------------------------------------------------------------*/
139
140 /* Compute rotate matrix and trans vector for change system */
141 int icvCreateConvertMatrVect( CvMatr64d     rotMatr1,
142                                 CvMatr64d     transVect1,
143                                 CvMatr64d     rotMatr2,
144                                 CvMatr64d     transVect2,
145                                 CvMatr64d     convRotMatr,
146                                 CvMatr64d     convTransVect)
147 {
148     double invRotMatr2[9];
149     double tmpVect[3];
150
151
152     icvInvertMatrix_64d(rotMatr2,3,invRotMatr2);
153     /* Test for error */
154
155     icvMulMatrix_64d(   rotMatr1,
156                         3,3,
157                         invRotMatr2,
158                         3,3,
159                         convRotMatr);
160
161     icvMulMatrix_64d(   convRotMatr,
162                         3,3,
163                         transVect2,
164                         1,3, 
165                         tmpVect);
166     
167     icvSubVector_64d(transVect1,tmpVect,convTransVect,3);
168
169     
170     return CV_NO_ERR;
171 }
172
173 /*--------------------------------------------------------------------------------------*/
174
175 /* Compute point coordinates in other system */
176 int icvConvertPointSystem(CvPoint3D64d  M2,
177                             CvPoint3D64d* M1,
178                             CvMatr64d     rotMatr,
179                             CvMatr64d     transVect
180                             )
181 {
182     double tmpVect[3];
183
184     icvMulMatrix_64d(   rotMatr,
185                         3,3,
186                         (double*)&M2,
187                         1,3, 
188                         tmpVect);
189
190     icvAddVector_64d(tmpVect,transVect,(double*)M1,3);
191     
192     return CV_NO_ERR;
193 }
194 /*--------------------------------------------------------------------------------------*/
195 int icvComputeCoeffForStereoV3( double quad1[4][2],
196                                 double quad2[4][2],
197                                 int    numScanlines,
198                                 CvMatr64d    camMatr1,
199                                 CvMatr64d    rotMatr1,
200                                 CvMatr64d    transVect1,
201                                 CvMatr64d    camMatr2,
202                                 CvMatr64d    rotMatr2,
203                                 CvMatr64d    transVect2,
204                                 CvStereoLineCoeff*    startCoeffs,
205                                 int* needSwapCamera)
206 {
207     /* For each pair */
208     /* In this function we must define position of cameras */
209
210     CvPoint2D64d point1;
211     CvPoint2D64d point2;
212     CvPoint2D64d point3;
213     CvPoint2D64d point4;
214
215     int currLine;
216     *needSwapCamera = 0;
217     for( currLine = 0; currLine < numScanlines; currLine++ )
218     {
219         /* Compute points */
220         double alpha = ((double)currLine)/((double)(numScanlines)); /* maybe - 1 */
221
222         point1.x = (1.0 - alpha) * quad1[0][0] + alpha * quad1[3][0];
223         point1.y = (1.0 - alpha) * quad1[0][1] + alpha * quad1[3][1];
224
225         point2.x = (1.0 - alpha) * quad1[1][0] + alpha * quad1[2][0];
226         point2.y = (1.0 - alpha) * quad1[1][1] + alpha * quad1[2][1];
227         
228         point3.x = (1.0 - alpha) * quad2[0][0] + alpha * quad2[3][0];
229         point3.y = (1.0 - alpha) * quad2[0][1] + alpha * quad2[3][1];
230
231         point4.x = (1.0 - alpha) * quad2[1][0] + alpha * quad2[2][0];
232         point4.y = (1.0 - alpha) * quad2[1][1] + alpha * quad2[2][1];
233
234         /* We can compute coeffs for this line */
235         icvComCoeffForLine(    point1,
236                             point2,
237                             point3,
238                             point4,
239                             camMatr1,
240                             rotMatr1,
241                             transVect1,
242                             camMatr2,
243                             rotMatr2,
244                             transVect2,
245                             &startCoeffs[currLine],
246                             needSwapCamera);
247     }
248     return CV_NO_ERR;    
249 }
250 /*--------------------------------------------------------------------------------------*/
251 int icvComputeCoeffForStereoNew(   double quad1[4][2],
252                                         double quad2[4][2],
253                                         int    numScanlines,
254                                         CvMatr32f    camMatr1,
255                                         CvMatr32f    rotMatr1,
256                                         CvMatr32f    transVect1,
257                                         CvMatr32f    camMatr2,
258                                         CvStereoLineCoeff*    startCoeffs,
259                                         int* needSwapCamera)
260 {
261     /* Convert data */
262
263     double camMatr1_64d[9];
264     double camMatr2_64d[9];
265     
266     double rotMatr1_64d[9];
267     double transVect1_64d[3];
268     
269     double rotMatr2_64d[9];
270     double transVect2_64d[3];
271
272     icvCvt_32f_64d(camMatr1,camMatr1_64d,9);
273     icvCvt_32f_64d(camMatr2,camMatr2_64d,9);
274
275     icvCvt_32f_64d(rotMatr1,rotMatr1_64d,9);
276     icvCvt_32f_64d(transVect1,transVect1_64d,3);
277
278     rotMatr2_64d[0] = 1;
279     rotMatr2_64d[1] = 0;
280     rotMatr2_64d[2] = 0;
281     rotMatr2_64d[3] = 0;
282     rotMatr2_64d[4] = 1;
283     rotMatr2_64d[5] = 0;
284     rotMatr2_64d[6] = 0;
285     rotMatr2_64d[7] = 0;
286     rotMatr2_64d[8] = 1;
287
288     transVect2_64d[0] = 0;
289     transVect2_64d[1] = 0;
290     transVect2_64d[2] = 0;
291
292     int status = icvComputeCoeffForStereoV3( quad1,
293                                                 quad2,
294                                                 numScanlines,
295                                                 camMatr1_64d,
296                                                 rotMatr1_64d,
297                                                 transVect1_64d,
298                                                 camMatr2_64d,
299                                                 rotMatr2_64d,
300                                                 transVect2_64d,
301                                                 startCoeffs,
302                                                 needSwapCamera);
303
304
305     return status;
306
307 }
308 /*--------------------------------------------------------------------------------------*/
309 int icvComputeCoeffForStereo(  CvStereoCamera* stereoCamera)
310 {
311     double quad1[4][2];
312     double quad2[4][2];
313
314     int i;
315     for( i = 0; i < 4; i++ )
316     {
317         quad1[i][0] = stereoCamera->quad[0][i].x;
318         quad1[i][1] = stereoCamera->quad[0][i].y;
319
320         quad2[i][0] = stereoCamera->quad[1][i].x;
321         quad2[i][1] = stereoCamera->quad[1][i].y;
322     }
323
324     icvComputeCoeffForStereoNew(        quad1,
325                                         quad2,
326                                         stereoCamera->warpSize.height,
327                                         stereoCamera->camera[0]->matrix,
328                                         stereoCamera->rotMatrix,
329                                         stereoCamera->transVector,
330                                         stereoCamera->camera[1]->matrix,
331                                         stereoCamera->lineCoeffs,
332                                         &(stereoCamera->needSwapCameras));
333     return CV_OK;
334 }
335
336
337
338 /*--------------------------------------------------------------------------------------*/
339 int icvComCoeffForLine(   CvPoint2D64d point1,
340                             CvPoint2D64d point2,
341                             CvPoint2D64d point3,
342                             CvPoint2D64d point4,
343                             CvMatr64d    camMatr1,
344                             CvMatr64d    rotMatr1,
345                             CvMatr64d    transVect1,
346                             CvMatr64d    camMatr2,
347                             CvMatr64d    rotMatr2,
348                             CvMatr64d    transVect2,
349                             CvStereoLineCoeff* coeffs,
350                             int* needSwapCamera)
351 {
352     /* Get direction for all points */
353     /* Direction for camera 1 */
354     
355     double direct1[3];
356     double direct2[3];
357     double camPoint1[3];
358     
359     double directS3[3];
360     double directS4[3];
361     double direct3[3];
362     double direct4[3];
363     double camPoint2[3];
364     
365     icvGetDirectionForPoint(   point1,
366                             camMatr1,
367                             (CvPoint3D64d*)direct1);
368     
369     icvGetDirectionForPoint(   point2,
370                             camMatr1,
371                             (CvPoint3D64d*)direct2);
372
373     /* Direction for camera 2 */
374
375     icvGetDirectionForPoint(   point3,
376                             camMatr2,
377                             (CvPoint3D64d*)directS3);
378     
379     icvGetDirectionForPoint(   point4,
380                             camMatr2,
381                             (CvPoint3D64d*)directS4);
382
383     /* Create convertion for camera 2: two direction and camera point */
384     
385     double convRotMatr[9];
386     double convTransVect[3];
387
388     icvCreateConvertMatrVect(  rotMatr1,
389                             transVect1,
390                             rotMatr2,
391                             transVect2,
392                             convRotMatr,
393                             convTransVect);
394
395     double zeroVect[3];
396     zeroVect[0] = zeroVect[1] = zeroVect[2] = 0.0;
397     camPoint1[0] = camPoint1[1] = camPoint1[2] = 0.0;
398     
399     icvConvertPointSystem(*((CvPoint3D64d*)directS3),(CvPoint3D64d*)direct3,convRotMatr,convTransVect);
400     icvConvertPointSystem(*((CvPoint3D64d*)directS4),(CvPoint3D64d*)direct4,convRotMatr,convTransVect);
401     icvConvertPointSystem(*((CvPoint3D64d*)zeroVect),(CvPoint3D64d*)camPoint2,convRotMatr,convTransVect);
402
403     double pointB[3];
404         
405     int postype = 0;
406     
407     /* Changed order */
408     /* Compute point B: xB,yB,zB */
409     icvGetCrossLines(*((CvPoint3D64d*)camPoint1),*((CvPoint3D64d*)direct2),
410                   *((CvPoint3D64d*)camPoint2),*((CvPoint3D64d*)direct3),
411                   (CvPoint3D64d*)pointB);
412
413     if( pointB[2] < 0 )/* If negative use other lines for cross */
414     {
415         postype = 1;
416         icvGetCrossLines(*((CvPoint3D64d*)camPoint1),*((CvPoint3D64d*)direct1),
417                       *((CvPoint3D64d*)camPoint2),*((CvPoint3D64d*)direct4),
418                       (CvPoint3D64d*)pointB);
419     }
420
421     CvPoint3D64d pointNewA;
422     CvPoint3D64d pointNewC;
423
424     pointNewA.x = pointNewA.y = pointNewA.z = 0;
425     pointNewC.x = pointNewC.y = pointNewC.z = 0;
426
427     if( postype == 0 )
428     {
429         icvGetSymPoint3D(   *((CvPoint3D64d*)camPoint1),
430                             *((CvPoint3D64d*)direct1),
431                             *((CvPoint3D64d*)pointB),
432                             &pointNewA);
433
434         icvGetSymPoint3D(   *((CvPoint3D64d*)camPoint2),
435                             *((CvPoint3D64d*)direct4),
436                             *((CvPoint3D64d*)pointB),
437                             &pointNewC);
438     }
439     else
440     {/* In this case we must change cameras */
441         *needSwapCamera = 1;
442         icvGetSymPoint3D(   *((CvPoint3D64d*)camPoint2),
443                             *((CvPoint3D64d*)direct3),
444                             *((CvPoint3D64d*)pointB),
445                             &pointNewA);
446
447         icvGetSymPoint3D(   *((CvPoint3D64d*)camPoint1),
448                             *((CvPoint3D64d*)direct2),
449                             *((CvPoint3D64d*)pointB),
450                             &pointNewC);
451     }
452
453
454     double gamma;
455     
456     double x1,y1,z1;
457
458     x1 = camPoint1[0];
459     y1 = camPoint1[1];
460     z1 = camPoint1[2];
461
462     double xA,yA,zA;
463     double xB,yB,zB;
464     double xC,yC,zC;
465
466     xA = pointNewA.x;
467     yA = pointNewA.y;
468     zA = pointNewA.z;
469
470     xB = pointB[0];
471     yB = pointB[1];
472     zB = pointB[2];
473
474     xC = pointNewC.x;
475     yC = pointNewC.y;
476     zC = pointNewC.z;
477
478     double len1,len2;
479     len1 = sqrt( (xA-xB)*(xA-xB) + (yA-yB)*(yA-yB) + (zA-zB)*(zA-zB) );
480     len2 = sqrt( (xB-xC)*(xB-xC) + (yB-yC)*(yB-yC) + (zB-zC)*(zB-zC) );
481     gamma = len2 / len1;
482
483     icvComputeStereoLineCoeffs( pointNewA,
484                                 *((CvPoint3D64d*)pointB),
485                                 *((CvPoint3D64d*)camPoint1),
486                                 gamma,
487                                 coeffs);
488     
489     return CV_NO_ERR;
490 }
491
492
493 /*--------------------------------------------------------------------------------------*/
494
495 int icvGetDirectionForPoint(  CvPoint2D64d point,
496                                 CvMatr64d camMatr,
497                                 CvPoint3D64d* direct)
498 {
499     /*  */
500     double invMatr[9];
501     
502     /* Invert matrix */
503
504     icvInvertMatrix_64d(camMatr,3,invMatr);
505     /* TEST FOR ERRORS */
506
507     double vect[3];
508     vect[0] = point.x;
509     vect[1] = point.y;
510     vect[2] = 1;
511
512     /* Mul matr */
513     icvMulMatrix_64d(   invMatr,
514                         3,3,
515                         vect,
516                         1,3, 
517                         (double*)direct);
518
519     return CV_NO_ERR;    
520 }
521
522 /*--------------------------------------------------------------------------------------*/
523
524 int icvGetCrossLines(CvPoint3D64d point11,CvPoint3D64d point12,
525                        CvPoint3D64d point21,CvPoint3D64d point22,
526                        CvPoint3D64d* midPoint)
527 {
528     double xM,yM,zM;
529     double xN,yN,zN;
530
531     double xA,yA,zA;
532     double xB,yB,zB;
533
534     double xC,yC,zC;
535     double xD,yD,zD;
536
537     xA = point11.x;
538     yA = point11.y;
539     zA = point11.z;
540
541     xB = point12.x;
542     yB = point12.y;
543     zB = point12.z;
544
545     xC = point21.x;
546     yC = point21.y;
547     zC = point21.z;
548
549     xD = point22.x;
550     yD = point22.y;
551     zD = point22.z;
552
553     double a11,a12,a21,a22;
554     double b1,b2;
555
556     a11 =  (xB-xA)*(xB-xA)+(yB-yA)*(yB-yA)+(zB-zA)*(zB-zA);
557     a12 = -(xD-xC)*(xB-xA)-(yD-yC)*(yB-yA)-(zD-zC)*(zB-zA);
558     a21 =  (xB-xA)*(xD-xC)+(yB-yA)*(yD-yC)+(zB-zA)*(zD-zC);
559     a22 = -(xD-xC)*(xD-xC)-(yD-yC)*(yD-yC)-(zD-zC)*(zD-zC);
560     b1  = -( (xA-xC)*(xB-xA)+(yA-yC)*(yB-yA)+(zA-zC)*(zB-zA) );
561     b2  = -( (xA-xC)*(xD-xC)+(yA-yC)*(yD-yC)+(zA-zC)*(zD-zC) );
562
563     double delta;
564     double deltaA,deltaB;
565     double alpha,betta;
566
567     delta  = a11*a22-a12*a21;
568     
569     if( fabs(delta) < EPS64D )
570     {
571         /*return ERROR;*/
572     }
573
574     deltaA = b1*a22-b2*a12;
575     deltaB = a11*b2-b1*a21;
576
577     alpha = deltaA / delta;
578     betta = deltaB / delta;
579
580     xM = xA+alpha*(xB-xA);
581     yM = yA+alpha*(yB-yA);
582     zM = zA+alpha*(zB-zA);
583
584     xN = xC+betta*(xD-xC);
585     yN = yC+betta*(yD-yC);
586     zN = zC+betta*(zD-zC);
587
588     /* Compute middle point */
589     midPoint->x = (xM + xN) * 0.5;
590     midPoint->y = (yM + yN) * 0.5;
591     midPoint->z = (zM + zN) * 0.5;
592
593     return CV_NO_ERR;
594 }
595
596 /*--------------------------------------------------------------------------------------*/
597
598 int icvComputeStereoLineCoeffs(   CvPoint3D64d pointA,
599                                     CvPoint3D64d pointB,
600                                     CvPoint3D64d pointCam1,
601                                     double gamma,
602                                     CvStereoLineCoeff*    coeffs)
603 {
604     double x1,y1,z1;
605
606     x1 = pointCam1.x;
607     y1 = pointCam1.y;
608     z1 = pointCam1.z;
609
610     double xA,yA,zA;
611     double xB,yB,zB;
612
613     xA = pointA.x;
614     yA = pointA.y;
615     zA = pointA.z;
616
617     xB = pointB.x;
618     yB = pointB.y;
619     zB = pointB.z;
620
621     if( gamma > 0 )
622     {
623         coeffs->Xcoef   = -x1 + xA;
624         coeffs->XcoefA  =  xB + x1 - xA;
625         coeffs->XcoefB  = -xA - gamma * x1 + gamma * xA;
626         coeffs->XcoefAB = -xB + xA + gamma * xB - gamma * xA;
627
628         coeffs->Ycoef   = -y1 + yA;
629         coeffs->YcoefA  =  yB + y1 - yA;
630         coeffs->YcoefB  = -yA - gamma * y1 + gamma * yA;
631         coeffs->YcoefAB = -yB + yA + gamma * yB - gamma * yA;
632
633         coeffs->Zcoef   = -z1 + zA;
634         coeffs->ZcoefA  =  zB + z1 - zA;
635         coeffs->ZcoefB  = -zA - gamma * z1 + gamma * zA;
636         coeffs->ZcoefAB = -zB + zA + gamma * zB - gamma * zA;
637     }
638     else
639     {
640         gamma = - gamma;
641         coeffs->Xcoef   = -( -x1 + xA);
642         coeffs->XcoefB  = -(  xB + x1 - xA);
643         coeffs->XcoefA  = -( -xA - gamma * x1 + gamma * xA);
644         coeffs->XcoefAB = -( -xB + xA + gamma * xB - gamma * xA);
645
646         coeffs->Ycoef   = -( -y1 + yA);
647         coeffs->YcoefB  = -(  yB + y1 - yA);
648         coeffs->YcoefA  = -( -yA - gamma * y1 + gamma * yA);
649         coeffs->YcoefAB = -( -yB + yA + gamma * yB - gamma * yA);
650
651         coeffs->Zcoef   = -( -z1 + zA);
652         coeffs->ZcoefB  = -(  zB + z1 - zA);
653         coeffs->ZcoefA  = -( -zA - gamma * z1 + gamma * zA);
654         coeffs->ZcoefAB = -( -zB + zA + gamma * zB - gamma * zA);
655     }
656
657
658
659     return CV_NO_ERR;
660 }
661 /*--------------------------------------------------------------------------------------*/
662
663
664 /*---------------------------------------------------------------------------------------*/
665
666 /* This function get minimum angle started at point which contains rect */
667 int icvGetAngleLine( CvPoint2D64d startPoint, CvSize imageSize,CvPoint2D64d *point1,CvPoint2D64d *point2)
668 {
669     /* Get crosslines with image corners */
670
671     /* Find four lines */
672
673     CvPoint2D64d pa,pb,pc,pd;
674     
675     pa.x = 0;
676     pa.y = 0;
677
678     pb.x = imageSize.width-1;
679     pb.y = 0;
680
681     pd.x = imageSize.width-1;
682     pd.y = imageSize.height-1;
683
684     pc.x = 0;
685     pc.y = imageSize.height-1;
686     
687     /* We can compute points for angle */
688     /* Test for place section */
689     
690     if( startPoint.x < 0 )
691     {/* 1,4,7 */
692         if( startPoint.y < 0)
693         {/* 1 */
694             *point1 = pb;
695             *point2 = pc;
696         }
697         else if( startPoint.y > imageSize.height-1 )
698         {/* 7 */
699             *point1 = pa;
700             *point2 = pd;
701         }
702         else
703         {/* 4 */
704             *point1 = pa;
705             *point2 = pc;
706         }
707     }
708     else if ( startPoint.x > imageSize.width-1 )
709     {/* 3,6,9 */
710         if( startPoint.y < 0 )
711         {/* 3 */
712             *point1 = pa;
713             *point2 = pd;
714         }
715         else if ( startPoint.y > imageSize.height-1 )
716         {/* 9 */
717             *point1 = pb;
718             *point2 = pc;
719         }
720         else
721         {/* 6 */
722             *point1 = pb;
723             *point2 = pd;
724         }
725     }
726     else
727     {/* 2,5,8 */
728         if( startPoint.y < 0 )
729         {/* 2 */
730             if( startPoint.x < imageSize.width/2 )
731             {
732                 *point1 = pb;
733                 *point2 = pa;
734             }
735             else
736             {
737                 *point1 = pa;
738                 *point2 = pb;
739             }
740         }
741         else if( startPoint.y > imageSize.height-1 )
742         {/* 8 */
743             if( startPoint.x < imageSize.width/2 )
744             {
745                 *point1 = pc;
746                 *point2 = pd;
747             }
748             else
749             {
750                 *point1 = pd;
751                 *point2 = pc;
752             }
753         }
754         else
755         {/* 5 - point in the image */
756             return 2;
757         }
758     }
759     return 0;
760 }/* GetAngleLine */
761
762 /*---------------------------------------------------------------------------------------*/
763
764 void icvGetCoefForPiece(   CvPoint2D64d p_start,CvPoint2D64d p_end,
765                         double *a,double *b,double *c,
766                         int* result)
767 {
768     double det;
769     double detA,detB,detC;
770
771     det = p_start.x*p_end.y+p_end.x+p_start.y-p_end.y-p_start.y*p_end.x-p_start.x;
772     if( fabs(det) < EPS64D)/* Error */
773     {
774         *result = 0;
775         return;
776     }
777
778     detA = p_start.y - p_end.y;
779     detB = p_end.x - p_start.x;
780     detC = p_start.x*p_end.y - p_end.x*p_start.y;
781
782     double invDet = 1.0 / det;
783     *a = detA * invDet;
784     *b = detB * invDet;
785     *c = detC * invDet;
786
787     *result = 1;
788     return;
789 }
790
791 /*---------------------------------------------------------------------------------------*/
792
793 /* Get common area of rectifying */
794 void icvGetCommonArea( CvSize imageSize,
795                     CvPoint3D64d epipole1,CvPoint3D64d epipole2,
796                     CvMatr64d fundMatr,
797                     CvVect64d coeff11,CvVect64d coeff12,
798                     CvVect64d coeff21,CvVect64d coeff22,
799                     int* result)
800 {
801     int res = 0;
802     CvPoint2D64d point11;
803     CvPoint2D64d point12;
804     CvPoint2D64d point21;
805     CvPoint2D64d point22;
806
807     double corr11[3];
808     double corr12[3];
809     double corr21[3];
810     double corr22[3];
811
812     double pointW11[3];
813     double pointW12[3];
814     double pointW21[3];
815     double pointW22[3];
816
817     double transFundMatr[3*3];
818     /* Compute transpose of fundamental matrix */
819     icvTransposeMatrix_64d( fundMatr, 3, 3, transFundMatr );
820     
821     CvPoint2D64d epipole1_2d;
822     CvPoint2D64d epipole2_2d;
823     
824     if( fabs(epipole1.z) < 1e-8 )
825     {/* epipole1 in infinity */
826         *result = 0;
827         return;
828     }
829     epipole1_2d.x = epipole1.x / epipole1.z;
830     epipole1_2d.y = epipole1.y / epipole1.z;
831
832     if( fabs(epipole2.z) < 1e-8 )
833     {/* epipole2 in infinity */
834         *result = 0;
835         return;
836     }
837     epipole2_2d.x = epipole2.x / epipole2.z;
838     epipole2_2d.y = epipole2.y / epipole2.z;
839
840     int stat = icvGetAngleLine( epipole1_2d, imageSize,&point11,&point12);
841     if( stat == 2 )
842     {
843         /* No angle */
844         *result = 0;
845         return;
846     }
847
848     stat = icvGetAngleLine( epipole2_2d, imageSize,&point21,&point22);
849     if( stat == 2 )
850     {
851         /* No angle */
852         *result = 0;
853         return;
854     }
855
856     /* ============= Computation for line 1 ================ */
857     /* Find correspondence line for angle points11 */
858     /* corr21 = Fund'*p1 */
859
860     pointW11[0] = point11.x;
861     pointW11[1] = point11.y;
862     pointW11[2] = 1.0;
863
864     icvTransformVector_64d( transFundMatr, /* !!! Modified from not transposed */
865                             pointW11, 
866                             corr21,
867                             3,3);
868
869     /* Find crossing of line with image 2 */
870     CvPoint2D64d start;
871     CvPoint2D64d end;
872     icvGetCrossRectDirect( imageSize,
873                         corr21[0],corr21[1],corr21[2],
874                         &start,&end,
875                         &res);
876     
877     if( res == 0 )
878     {/* We have not cross */
879         /* We must define new angle */
880
881         pointW21[0] = point21.x;
882         pointW21[1] = point21.y;
883         pointW21[2] = 1.0;
884
885         /* Find correspondence line for this angle points */
886         /* We know point and try to get corr line */
887         /* For point21 */
888         /* corr11 = Fund * p21 */
889
890         icvTransformVector_64d( fundMatr, /* !!! Modified */
891                                 pointW21, 
892                                 corr11,
893                                 3,3);
894
895         /* We have cross. And it's result cross for up line. Set result coefs */
896
897         /* Set coefs for line 1 image 1 */
898         coeff11[0] = corr11[0];
899         coeff11[1] = corr11[1];
900         coeff11[2] = corr11[2];
901         
902         /* Set coefs for line 1 image 2 */
903         icvGetCoefForPiece(    epipole2_2d,point21,
904                             &coeff21[0],&coeff21[1],&coeff21[2],
905                             &res);
906         if( res == 0 )
907         {
908             *result = 0;
909             return;/* Error */
910         }
911     }
912     else
913     {/* Line 1 cross image 2 */
914         /* Set coefs for line 1 image 1 */
915         icvGetCoefForPiece(    epipole1_2d,point11,
916                             &coeff11[0],&coeff11[1],&coeff11[2],
917                             &res);
918         if( res == 0 )
919         {
920             *result = 0;
921             return;/* Error */
922         }
923         
924         /* Set coefs for line 1 image 2 */
925         coeff21[0] = corr21[0];
926         coeff21[1] = corr21[1];
927         coeff21[2] = corr21[2];
928         
929     }
930
931     /* ============= Computation for line 2 ================ */
932     /* Find correspondence line for angle points11 */
933     /* corr22 = Fund*p2 */
934
935     pointW12[0] = point12.x;
936     pointW12[1] = point12.y;
937     pointW12[2] = 1.0;
938
939     icvTransformVector_64d( transFundMatr,
940                             pointW12, 
941                             corr22,
942                             3,3);
943
944     /* Find crossing of line with image 2 */
945     icvGetCrossRectDirect( imageSize,
946                         corr22[0],corr22[1],corr22[2],
947                         &start,&end,
948                         &res);
949     
950     if( res == 0 )
951     {/* We have not cross */
952         /* We must define new angle */
953
954         pointW22[0] = point22.x;
955         pointW22[1] = point22.y;
956         pointW22[2] = 1.0;
957
958         /* Find correspondence line for this angle points */
959         /* We know point and try to get corr line */
960         /* For point21 */
961         /* corr2 = Fund' * p1 */
962
963         icvTransformVector_64d( fundMatr,
964                                 pointW22, 
965                                 corr12,
966                                 3,3);
967
968         
969         /* We have cross. And it's result cross for down line. Set result coefs */
970
971         /* Set coefs for line 2 image 1 */
972         coeff12[0] = corr12[0];
973         coeff12[1] = corr12[1];
974         coeff12[2] = corr12[2];
975         
976         /* Set coefs for line 1 image 2 */
977         icvGetCoefForPiece(    epipole2_2d,point22,
978                             &coeff22[0],&coeff22[1],&coeff22[2],
979                             &res);
980         if( res == 0 )
981         {
982             *result = 0;
983             return;/* Error */
984         }
985     }
986     else
987     {/* Line 2 cross image 2 */
988         /* Set coefs for line 2 image 1 */
989         icvGetCoefForPiece(    epipole1_2d,point12,
990                             &coeff12[0],&coeff12[1],&coeff12[2],
991                             &res);
992         if( res == 0 )
993         {
994             *result = 0;
995             return;/* Error */
996         }
997         
998         /* Set coefs for line 1 image 2 */
999         coeff22[0] = corr22[0];
1000         coeff22[1] = corr22[1];
1001         coeff22[2] = corr22[2];
1002         
1003     }
1004
1005     /* Now we know common area */
1006
1007     return;
1008
1009 }/* GetCommonArea */
1010
1011 /*---------------------------------------------------------------------------------------*/
1012
1013 /* Get cross for direction1 and direction2 */
1014 /*  Result = 1 - cross */
1015 /*  Result = 2 - parallel and not equal */
1016 /*  Result = 3 - parallel and equal */
1017
1018 void icvGetCrossDirectDirect(  CvVect64d direct1,CvVect64d direct2,
1019                             CvPoint2D64d *cross,int* result)
1020 {
1021     double det  = direct1[0]*direct2[1] - direct2[0]*direct1[1];
1022     double detx = -direct1[2]*direct2[1] + direct1[1]*direct2[2];
1023
1024     if( fabs(det) > EPS64D )
1025     {/* Have cross */
1026         cross->x = detx/det;
1027         cross->y = (-direct1[0]*direct2[2] + direct2[0]*direct1[2])/det;
1028         *result = 1;
1029     }
1030     else
1031     {/* may be parallel */
1032         if( fabs(detx) > EPS64D )
1033         {/* parallel and not equal */
1034             *result = 2;
1035         }
1036         else
1037         {/* equals */
1038             *result = 3;
1039         }
1040     }
1041
1042     return;
1043 }
1044
1045 /*---------------------------------------------------------------------------------------*/
1046
1047 /* Get cross for piece p1,p2 and direction a,b,c */
1048 /*  Result = 0 - no cross */
1049 /*  Result = 1 - cross */
1050 /*  Result = 2 - parallel and not equal */
1051 /*  Result = 3 - parallel and equal */
1052
1053 void icvGetCrossPieceDirect(   CvPoint2D64d p_start,CvPoint2D64d p_end,
1054                             double a,double b,double c,
1055                             CvPoint2D64d *cross,int* result)
1056 {
1057
1058     if( (a*p_start.x + b*p_start.y + c) * (a*p_end.x + b*p_end.y + c) <= 0 )
1059     {/* Have cross */
1060         double det;
1061         double detxc,detyc;
1062         
1063         det = a * (p_end.x - p_start.x) + b * (p_end.y - p_start.y);
1064         
1065         if( fabs(det) < EPS64D )
1066         {/* lines are parallel and may be equal or line is point */
1067             if(  fabs(a*p_start.x + b*p_start.y + c) < EPS64D )
1068             {/* line is point or not diff */
1069                 *result = 3;
1070                 return;
1071             }
1072             else
1073             {
1074                 *result = 2;                
1075             }
1076             return;
1077         }
1078
1079         detxc = b*(p_end.y*p_start.x - p_start.y*p_end.x) + c*(p_start.x - p_end.x);
1080         detyc = a*(p_end.x*p_start.y - p_start.x*p_end.y) + c*(p_start.y - p_end.y);
1081
1082         cross->x = detxc / det;
1083         cross->y = detyc / det;
1084         *result = 1;
1085
1086     }
1087     else
1088     {
1089         *result = 0;
1090     }
1091     return;
1092 }
1093 /*--------------------------------------------------------------------------------------*/
1094
1095 void icvGetCrossPiecePiece( CvPoint2D64d p1_start,CvPoint2D64d p1_end,
1096                             CvPoint2D64d p2_start,CvPoint2D64d p2_end,
1097                             CvPoint2D64d* cross,
1098                             int* result)
1099 {
1100     double ex1,ey1,ex2,ey2;
1101     double px1,py1,px2,py2;
1102     double del;
1103     double delA,delB,delX,delY;
1104     double alpha,betta;
1105
1106     ex1 = p1_start.x;
1107     ey1 = p1_start.y;
1108     ex2 = p1_end.x;
1109     ey2 = p1_end.y;
1110
1111     px1 = p2_start.x;
1112     py1 = p2_start.y;
1113     px2 = p2_end.x;
1114     py2 = p2_end.y;
1115
1116     del = (py1-py2)*(ex1-ex2)-(px1-px2)*(ey1-ey2);
1117     if( fabs(del) <= EPS64D )
1118     {/* May be they are parallel !!! */
1119         *result = 0;
1120         return;
1121     }
1122
1123     delA =  (ey1-ey2)*(ex1-px1) + (ex1-ex2)*(py1-ey1);
1124     delB =  (py1-py2)*(ex1-px1) + (px1-px2)*(py1-ey1);
1125
1126     alpha = delA / del;
1127     betta = delB / del;
1128
1129     if( alpha < 0 || alpha > 1.0 || betta < 0 || betta > 1.0)
1130     {
1131         *result = 0;
1132         return;
1133     }
1134
1135     delX =  (px1-px2)*(ey1*(ex1-ex2)-ex1*(ey1-ey2))+
1136             (ex1-ex2)*(px1*(py1-py2)-py1*(px1-px2));
1137
1138     delY =  (py1-py2)*(ey1*(ex1-ex2)-ex1*(ey1-ey2))+
1139             (ey1-ey2)*(px1*(py1-py2)-py1*(px1-px2));
1140
1141     cross->x = delX / del;
1142     cross->y = delY / del;
1143     
1144     *result = 1;
1145     return;
1146 }
1147
1148
1149 /*---------------------------------------------------------------------------------------*/
1150
1151 void icvGetPieceLength(CvPoint2D64d point1,CvPoint2D64d point2,double* dist)
1152 {
1153     double dx = point2.x - point1.x;
1154     double dy = point2.y - point1.y;
1155     *dist = sqrt( dx*dx + dy*dy );
1156     return;
1157 }
1158
1159 /*---------------------------------------------------------------------------------------*/
1160
1161 void icvGetPieceLength3D(CvPoint3D64d point1,CvPoint3D64d point2,double* dist)
1162 {
1163     double dx = point2.x - point1.x;
1164     double dy = point2.y - point1.y;
1165     double dz = point2.z - point1.z;
1166     *dist = sqrt( dx*dx + dy*dy + dz*dz );
1167     return;
1168 }
1169
1170 /*---------------------------------------------------------------------------------------*/
1171
1172 /* Find line from epipole which cross image rect */
1173 /* Find points of cross 0 or 1 or 2. Return number of points in cross */
1174 void icvGetCrossRectDirect(    CvSize imageSize,
1175                             double a,double b,double c,
1176                             CvPoint2D64d *start,CvPoint2D64d *end,
1177                             int* result)
1178 {
1179     CvPoint2D64d frameBeg;
1180     CvPoint2D64d frameEnd;
1181     CvPoint2D64d cross[4];
1182     int     haveCross[4];
1183     
1184     haveCross[0] = 0;
1185     haveCross[1] = 0;
1186     haveCross[2] = 0;
1187     haveCross[3] = 0;
1188
1189     frameBeg.x = 0;
1190     frameBeg.y = 0;
1191     frameEnd.x = imageSize.width;
1192     frameEnd.y = 0;
1193
1194     icvGetCrossPieceDirect(frameBeg,frameEnd,a,b,c,&cross[0],&haveCross[0]);    
1195     
1196     frameBeg.x = imageSize.width;
1197     frameBeg.y = 0;
1198     frameEnd.x = imageSize.width;
1199     frameEnd.y = imageSize.height;
1200     icvGetCrossPieceDirect(frameBeg,frameEnd,a,b,c,&cross[1],&haveCross[1]);    
1201
1202     frameBeg.x = imageSize.width;
1203     frameBeg.y = imageSize.height;
1204     frameEnd.x = 0;
1205     frameEnd.y = imageSize.height;
1206     icvGetCrossPieceDirect(frameBeg,frameEnd,a,b,c,&cross[2],&haveCross[2]);    
1207
1208     frameBeg.x = 0;
1209     frameBeg.y = imageSize.height;
1210     frameEnd.x = 0;
1211     frameEnd.y = 0;
1212     icvGetCrossPieceDirect(frameBeg,frameEnd,a,b,c,&cross[3],&haveCross[3]);    
1213
1214     double maxDist;
1215
1216     int maxI=0,maxJ=0;
1217
1218
1219     int i,j;
1220
1221     maxDist = -1.0;
1222     
1223     double distance;
1224
1225     for( i = 0; i < 3; i++ )
1226     {
1227         if( haveCross[i] == 1 )
1228         {
1229             for( j = i + 1; j < 4; j++ )
1230             {
1231                 if( haveCross[j] == 1)
1232                 {/* Compute dist */
1233                     icvGetPieceLength(cross[i],cross[j],&distance);
1234                     if( distance > maxDist )
1235                     {
1236                         maxI = i;
1237                         maxJ = j;
1238                         maxDist = distance;
1239                     }
1240                 }
1241             }
1242         }
1243     }
1244
1245     if( maxDist >= 0 )
1246     {/* We have cross */
1247         *start = cross[maxI];
1248         *result = 1;
1249         if( maxDist > 0 )
1250         {
1251             *end   = cross[maxJ];
1252             *result = 2;
1253         }
1254     }
1255     else
1256     {
1257         *result = 0;
1258     }
1259
1260     return;
1261 }/* GetCrossRectDirect */
1262
1263 /*---------------------------------------------------------------------------------------*/
1264 void icvProjectPointToImage(   CvPoint3D64d point,
1265                             CvMatr64d camMatr,CvMatr64d rotMatr,CvVect64d transVect,
1266                             CvPoint2D64d* projPoint)
1267 {
1268
1269     double tmpVect1[3];
1270     double tmpVect2[3];
1271     
1272     icvMulMatrix_64d (  rotMatr,
1273                         3,3,
1274                         (double*)&point,
1275                         1,3,
1276                         tmpVect1);
1277
1278     icvAddVector_64d ( tmpVect1, transVect,tmpVect2, 3);
1279
1280     icvMulMatrix_64d (  camMatr,
1281                         3,3,
1282                         tmpVect2,
1283                         1,3,
1284                         tmpVect1);
1285
1286     projPoint->x = tmpVect1[0] / tmpVect1[2];
1287     projPoint->y = tmpVect1[1] / tmpVect1[2];
1288    
1289     return;
1290 }
1291
1292 /*---------------------------------------------------------------------------------------*/
1293 /* Get quads for transform images */
1294 void icvGetQuadsTransform( 
1295                           CvSize        imageSize,
1296                         CvMatr64d     camMatr1,
1297                         CvMatr64d     rotMatr1,
1298                         CvVect64d     transVect1,
1299                         CvMatr64d     camMatr2,
1300                         CvMatr64d     rotMatr2,
1301                         CvVect64d     transVect2,
1302                         CvSize*       warpSize,
1303                         double quad1[4][2],
1304                         double quad2[4][2],
1305                         CvMatr64d     fundMatr,
1306                         CvPoint3D64d* epipole1,
1307                         CvPoint3D64d* epipole2
1308                         )
1309 {
1310     /* First compute fundamental matrix and epipoles */
1311     int res;
1312
1313
1314     /* Compute epipoles and fundamental matrix using new functions */
1315     {
1316         double convRotMatr[9];
1317         double convTransVect[3];
1318
1319         icvCreateConvertMatrVect( rotMatr1,
1320                                   transVect1,
1321                                   rotMatr2,
1322                                   transVect2,
1323                                   convRotMatr,
1324                                   convTransVect);
1325         float convRotMatr_32f[9];
1326         float convTransVect_32f[3];
1327
1328         icvCvt_64d_32f(convRotMatr,convRotMatr_32f,9);
1329         icvCvt_64d_32f(convTransVect,convTransVect_32f,3);
1330
1331         /* We know R and t */
1332         /* Compute essential matrix */
1333         float essMatr[9];
1334         float fundMatr_32f[9];
1335
1336         float camMatr1_32f[9];
1337         float camMatr2_32f[9];
1338
1339         icvCvt_64d_32f(camMatr1,camMatr1_32f,9);
1340         icvCvt_64d_32f(camMatr2,camMatr2_32f,9);
1341
1342         cvComputeEssentialMatrix(   convRotMatr_32f,
1343                                     convTransVect_32f,
1344                                     essMatr);
1345
1346         cvConvertEssential2Fundamental( essMatr,
1347                                         fundMatr_32f,
1348                                         camMatr1_32f,
1349                                         camMatr2_32f);
1350         
1351         CvPoint3D32f epipole1_32f;
1352         CvPoint3D32f epipole2_32f;
1353         
1354         cvComputeEpipolesFromFundMatrix( fundMatr_32f,
1355                                          &epipole1_32f,
1356                                          &epipole2_32f);
1357         /* copy to 64d epipoles */
1358         epipole1->x = epipole1_32f.x;
1359         epipole1->y = epipole1_32f.y;
1360         epipole1->z = epipole1_32f.z;
1361
1362         epipole2->x = epipole2_32f.x;
1363         epipole2->y = epipole2_32f.y;
1364         epipole2->z = epipole2_32f.z;
1365         
1366         /* Convert fundamental matrix */
1367         icvCvt_32f_64d(fundMatr_32f,fundMatr,9);
1368     }
1369
1370     double coeff11[3];
1371     double coeff12[3];
1372     double coeff21[3];
1373     double coeff22[3];
1374
1375     icvGetCommonArea(   imageSize,
1376                         *epipole1,*epipole2,
1377                         fundMatr,
1378                         coeff11,coeff12,
1379                         coeff21,coeff22,
1380                         &res);
1381
1382     CvPoint2D64d point11, point12,point21, point22;
1383     double width1,width2;
1384     double height1,height2;
1385     double tmpHeight1,tmpHeight2;
1386
1387     CvPoint2D64d epipole1_2d;
1388     CvPoint2D64d epipole2_2d;
1389
1390     /* ----- Image 1 ----- */
1391     if( fabs(epipole1->z) < 1e-8 )
1392     {
1393         return;
1394     }
1395     epipole1_2d.x = epipole1->x / epipole1->z;
1396     epipole1_2d.y = epipole1->y / epipole1->z;
1397
1398     icvGetCutPiece( coeff11,coeff12,
1399                 epipole1_2d,
1400                 imageSize,
1401                 &point11,&point12,
1402                 &point21,&point22,
1403                 &res);
1404
1405     /* Compute distance */
1406     icvGetPieceLength(point11,point21,&width1);
1407     icvGetPieceLength(point11,point12,&tmpHeight1);
1408     icvGetPieceLength(point21,point22,&tmpHeight2);
1409     height1 = MAX(tmpHeight1,tmpHeight2);
1410
1411     quad1[0][0] = point11.x;
1412     quad1[0][1] = point11.y;
1413
1414     quad1[1][0] = point21.x;
1415     quad1[1][1] = point21.y;
1416
1417     quad1[2][0] = point22.x;
1418     quad1[2][1] = point22.y;
1419
1420     quad1[3][0] = point12.x;
1421     quad1[3][1] = point12.y;
1422
1423     /* ----- Image 2 ----- */
1424     if( fabs(epipole2->z) < 1e-8 )
1425     {
1426         return;
1427     }
1428     epipole2_2d.x = epipole2->x / epipole2->z;
1429     epipole2_2d.y = epipole2->y / epipole2->z;
1430
1431     icvGetCutPiece( coeff21,coeff22,
1432                 epipole2_2d,
1433                 imageSize,
1434                 &point11,&point12,
1435                 &point21,&point22,
1436                 &res);
1437
1438     /* Compute distance */
1439     icvGetPieceLength(point11,point21,&width2);
1440     icvGetPieceLength(point11,point12,&tmpHeight1);
1441     icvGetPieceLength(point21,point22,&tmpHeight2);
1442     height2 = MAX(tmpHeight1,tmpHeight2);
1443
1444     quad2[0][0] = point11.x;
1445     quad2[0][1] = point11.y;
1446
1447     quad2[1][0] = point21.x;
1448     quad2[1][1] = point21.y;
1449
1450     quad2[2][0] = point22.x;
1451     quad2[2][1] = point22.y;
1452
1453     quad2[3][0] = point12.x;
1454     quad2[3][1] = point12.y;
1455
1456
1457     /*=======================================================*/
1458     /* This is a new additional way to compute quads. */
1459     /* We must correct quads */
1460     {
1461         double convRotMatr[9];
1462         double convTransVect[3];
1463
1464         double newQuad1[4][2];
1465         double newQuad2[4][2];
1466
1467
1468         icvCreateConvertMatrVect( rotMatr1,
1469                                   transVect1,
1470                                   rotMatr2,
1471                                   transVect2,
1472                                   convRotMatr,
1473                                   convTransVect);
1474
1475         /* -------------Compute for first image-------------- */
1476         CvPoint2D32f pointb1;
1477         CvPoint2D32f pointe1;
1478         
1479         CvPoint2D32f pointb2;
1480         CvPoint2D32f pointe2;
1481
1482         pointb1.x = (float)quad1[0][0];
1483         pointb1.y = (float)quad1[0][1];
1484
1485         pointe1.x = (float)quad1[3][0];
1486         pointe1.y = (float)quad1[3][1];
1487
1488         icvComputeeInfiniteProject1(convRotMatr,
1489                                     camMatr1,
1490                                     camMatr2,
1491                                     pointb1,
1492                                     &pointb2);
1493
1494         icvComputeeInfiniteProject1(convRotMatr,
1495                                     camMatr1,
1496                                     camMatr2,
1497                                     pointe1,
1498                                     &pointe2);
1499
1500         /*  JUST TEST FOR POINT */
1501
1502         /* Compute distances */
1503         double dxOld,dyOld;
1504         double dxNew,dyNew;
1505         double distOld,distNew;
1506         
1507         dxOld = quad2[1][0] - quad2[0][0];
1508         dyOld = quad2[1][1] - quad2[0][1];
1509         distOld = dxOld*dxOld + dyOld*dyOld;
1510         
1511         dxNew = quad2[1][0] - pointb2.x;
1512         dyNew = quad2[1][1] - pointb2.y;
1513         distNew = dxNew*dxNew + dyNew*dyNew;
1514
1515         if( distNew > distOld )
1516         {/* Get new points for second quad */
1517             newQuad2[0][0] = pointb2.x;
1518             newQuad2[0][1] = pointb2.y;
1519             newQuad2[3][0] = pointe2.x;
1520             newQuad2[3][1] = pointe2.y;
1521             newQuad1[0][0] = quad1[0][0];
1522             newQuad1[0][1] = quad1[0][1];
1523             newQuad1[3][0] = quad1[3][0];
1524             newQuad1[3][1] = quad1[3][1];
1525         }
1526         else
1527         {/* Get new points for first quad */
1528
1529             pointb2.x = (float)quad2[0][0];
1530             pointb2.y = (float)quad2[0][1];
1531
1532             pointe2.x = (float)quad2[3][0];
1533             pointe2.y = (float)quad2[3][1];
1534
1535             icvComputeeInfiniteProject2(convRotMatr,
1536                                         camMatr1,
1537                                         camMatr2,
1538                                         &pointb1,
1539                                         pointb2);
1540
1541             icvComputeeInfiniteProject2(convRotMatr,
1542                                         camMatr1,
1543                                         camMatr2,
1544                                         &pointe1,
1545                                         pointe2);
1546
1547
1548             /*  JUST TEST FOR POINT */
1549
1550             newQuad2[0][0] = quad2[0][0];
1551             newQuad2[0][1] = quad2[0][1];
1552             newQuad2[3][0] = quad2[3][0];
1553             newQuad2[3][1] = quad2[3][1];
1554             
1555             newQuad1[0][0] = pointb1.x;
1556             newQuad1[0][1] = pointb1.y;
1557             newQuad1[3][0] = pointe1.x;
1558             newQuad1[3][1] = pointe1.y;
1559         }
1560
1561         /* -------------Compute for second image-------------- */
1562         pointb1.x = (float)quad1[1][0];
1563         pointb1.y = (float)quad1[1][1];
1564
1565         pointe1.x = (float)quad1[2][0];
1566         pointe1.y = (float)quad1[2][1];
1567
1568         icvComputeeInfiniteProject1(convRotMatr,
1569                                     camMatr1,
1570                                     camMatr2,
1571                                     pointb1,
1572                                     &pointb2);
1573
1574         icvComputeeInfiniteProject1(convRotMatr,
1575                                     camMatr1,
1576                                     camMatr2,
1577                                     pointe1,
1578                                     &pointe2);
1579
1580         /* Compute distances */
1581         
1582         dxOld = quad2[0][0] - quad2[1][0];
1583         dyOld = quad2[0][1] - quad2[1][1];
1584         distOld = dxOld*dxOld + dyOld*dyOld;
1585         
1586         dxNew = quad2[0][0] - pointb2.x;
1587         dyNew = quad2[0][1] - pointb2.y;
1588         distNew = dxNew*dxNew + dyNew*dyNew;
1589
1590         if( distNew > distOld )
1591         {/* Get new points for second quad */
1592             newQuad2[1][0] = pointb2.x;
1593             newQuad2[1][1] = pointb2.y;
1594             newQuad2[2][0] = pointe2.x;
1595             newQuad2[2][1] = pointe2.y;
1596             newQuad1[1][0] = quad1[1][0];
1597             newQuad1[1][1] = quad1[1][1];
1598             newQuad1[2][0] = quad1[2][0];
1599             newQuad1[2][1] = quad1[2][1];
1600         }
1601         else
1602         {/* Get new points for first quad */
1603
1604             pointb2.x = (float)quad2[1][0];
1605             pointb2.y = (float)quad2[1][1];
1606
1607             pointe2.x = (float)quad2[2][0];
1608             pointe2.y = (float)quad2[2][1];
1609
1610             icvComputeeInfiniteProject2(convRotMatr,
1611                                         camMatr1,
1612                                         camMatr2,
1613                                         &pointb1,
1614                                         pointb2);
1615
1616             icvComputeeInfiniteProject2(convRotMatr,
1617                                         camMatr1,
1618                                         camMatr2,
1619                                         &pointe1,
1620                                         pointe2);
1621
1622             newQuad2[1][0] = quad2[1][0];
1623             newQuad2[1][1] = quad2[1][1];
1624             newQuad2[2][0] = quad2[2][0];
1625             newQuad2[2][1] = quad2[2][1];
1626             
1627             newQuad1[1][0] = pointb1.x;
1628             newQuad1[1][1] = pointb1.y;
1629             newQuad1[2][0] = pointe1.x;
1630             newQuad1[2][1] = pointe1.y;
1631         }
1632
1633
1634
1635 /*-------------------------------------------------------------------------------*/
1636
1637         /* Copy new quads to old quad */
1638         int i;
1639         for( i = 0; i < 4; i++ )
1640         {
1641             {
1642                 quad1[i][0] = newQuad1[i][0];
1643                 quad1[i][1] = newQuad1[i][1];
1644                 quad2[i][0] = newQuad2[i][0];
1645                 quad2[i][1] = newQuad2[i][1];
1646             }
1647         }
1648     }
1649     /*=======================================================*/
1650
1651     double warpWidth,warpHeight;
1652
1653     warpWidth  = MAX(width1,width2);
1654     warpHeight = MAX(height1,height2);
1655
1656     warpSize->width  = (int)warpWidth;
1657     warpSize->height = (int)warpHeight;
1658
1659     warpSize->width  = cvRound(warpWidth-1);
1660     warpSize->height = cvRound(warpHeight-1);
1661
1662 /* !!! by Valery Mosyagin. this lines added just for test no warp */
1663     warpSize->width  = imageSize.width;
1664     warpSize->height = imageSize.height;
1665
1666     return;
1667 }
1668
1669
1670 /*---------------------------------------------------------------------------------------*/
1671
1672 void icvGetQuadsTransformNew(  CvSize        imageSize,
1673                             CvMatr32f     camMatr1,
1674                             CvMatr32f     camMatr2,
1675                             CvMatr32f     rotMatr1,
1676                             CvVect32f     transVect1,
1677                             CvSize*       warpSize,
1678                             double        quad1[4][2],
1679                             double        quad2[4][2],
1680                             CvMatr32f     fundMatr,
1681                             CvPoint3D32f* epipole1,
1682                             CvPoint3D32f* epipole2
1683                         )
1684 {
1685     /* Convert data */
1686     /* Convert camera matrix */
1687     double camMatr1_64d[9];
1688     double camMatr2_64d[9];
1689     double rotMatr1_64d[9];
1690     double transVect1_64d[3];
1691     double rotMatr2_64d[9];
1692     double transVect2_64d[3];
1693     double fundMatr_64d[9];
1694     CvPoint3D64d epipole1_64d;
1695     CvPoint3D64d epipole2_64d;
1696
1697     icvCvt_32f_64d(camMatr1,camMatr1_64d,9);
1698     icvCvt_32f_64d(camMatr2,camMatr2_64d,9);
1699     icvCvt_32f_64d(rotMatr1,rotMatr1_64d,9);
1700     icvCvt_32f_64d(transVect1,transVect1_64d,3);
1701
1702     /* Create vector and matrix */
1703
1704     rotMatr2_64d[0] = 1;
1705     rotMatr2_64d[1] = 0;
1706     rotMatr2_64d[2] = 0;
1707     rotMatr2_64d[3] = 0;
1708     rotMatr2_64d[4] = 1;
1709     rotMatr2_64d[5] = 0;
1710     rotMatr2_64d[6] = 0;
1711     rotMatr2_64d[7] = 0;
1712     rotMatr2_64d[8] = 1;
1713
1714     transVect2_64d[0] = 0;
1715     transVect2_64d[1] = 0;
1716     transVect2_64d[2] = 0;
1717
1718     icvGetQuadsTransform(   imageSize,
1719                             camMatr1_64d,
1720                             rotMatr1_64d,
1721                             transVect1_64d,
1722                             camMatr2_64d,
1723                             rotMatr2_64d,
1724                             transVect2_64d,
1725                             warpSize,
1726                             quad1,
1727                             quad2,
1728                             fundMatr_64d,
1729                             &epipole1_64d,
1730                             &epipole2_64d
1731                         );
1732
1733     /* Convert epipoles */
1734     epipole1->x = (float)(epipole1_64d.x);
1735     epipole1->y = (float)(epipole1_64d.y);
1736     epipole1->z = (float)(epipole1_64d.z);
1737
1738     epipole2->x = (float)(epipole2_64d.x);
1739     epipole2->y = (float)(epipole2_64d.y);
1740     epipole2->z = (float)(epipole2_64d.z);
1741
1742     /* Convert fundamental matrix */
1743     icvCvt_64d_32f(fundMatr_64d,fundMatr,9);
1744     
1745     return;
1746 }
1747
1748 /*---------------------------------------------------------------------------------------*/
1749 void icvGetQuadsTransformStruct(  CvStereoCamera* stereoCamera)
1750 {
1751     /* Wrapper for icvGetQuadsTransformNew */
1752
1753
1754     double  quad1[4][2];
1755     double  quad2[4][2];
1756
1757     icvGetQuadsTransformNew(     cvSize(cvRound(stereoCamera->camera[0]->imgSize[0]),cvRound(stereoCamera->camera[0]->imgSize[1])),
1758                             stereoCamera->camera[0]->matrix,
1759                             stereoCamera->camera[1]->matrix,
1760                             stereoCamera->rotMatrix,
1761                             stereoCamera->transVector,
1762                             &(stereoCamera->warpSize),
1763                             quad1,
1764                             quad2,
1765                             stereoCamera->fundMatr,
1766                             &(stereoCamera->epipole[0]),
1767                             &(stereoCamera->epipole[1])
1768                         );
1769
1770     int i;
1771     for( i = 0; i < 4; i++ )
1772     {
1773         stereoCamera->quad[0][i] = cvPoint2D32f(quad1[i][0],quad1[i][1]);
1774         stereoCamera->quad[1][i] = cvPoint2D32f(quad2[i][0],quad2[i][1]);
1775     }
1776
1777     return;
1778 }
1779
1780 /*---------------------------------------------------------------------------------------*/
1781 void icvComputeStereoParamsForCameras(CvStereoCamera* stereoCamera)
1782 {
1783     /* For given intrinsic and extrinsic parameters computes rest parameters 
1784     **   such as fundamental matrix. warping coeffs, epipoles, ...
1785     */
1786
1787
1788     /* compute rotate matrix and translate vector */
1789     double rotMatr1[9];
1790     double rotMatr2[9];
1791
1792     double transVect1[3];
1793     double transVect2[3];
1794
1795     double convRotMatr[9];
1796     double convTransVect[3];
1797
1798     /* fill matrices */
1799     icvCvt_32f_64d(stereoCamera->camera[0]->rotMatr,rotMatr1,9);
1800     icvCvt_32f_64d(stereoCamera->camera[1]->rotMatr,rotMatr2,9);
1801
1802     icvCvt_32f_64d(stereoCamera->camera[0]->transVect,transVect1,3);
1803     icvCvt_32f_64d(stereoCamera->camera[1]->transVect,transVect2,3);
1804         
1805     icvCreateConvertMatrVect(   rotMatr1,
1806                                 transVect1,
1807                                 rotMatr2,
1808                                 transVect2,
1809                                 convRotMatr,
1810                                 convTransVect);
1811     
1812     /* copy to stereo camera params */
1813     icvCvt_64d_32f(convRotMatr,stereoCamera->rotMatrix,9);
1814     icvCvt_64d_32f(convTransVect,stereoCamera->transVector,3);
1815
1816
1817     icvGetQuadsTransformStruct(stereoCamera);
1818     icvComputeRestStereoParams(stereoCamera);
1819 }
1820
1821
1822
1823 /*---------------------------------------------------------------------------------------*/
1824
1825 /* Get cut line for one image */
1826 void icvGetCutPiece(   CvVect64d areaLineCoef1,CvVect64d areaLineCoef2,
1827                     CvPoint2D64d epipole,
1828                     CvSize imageSize,
1829                     CvPoint2D64d* point11,CvPoint2D64d* point12,
1830                     CvPoint2D64d* point21,CvPoint2D64d* point22,
1831                     int* result)
1832 {
1833     /* Compute nearest cut line to epipole */
1834     /* Get corners inside sector */
1835     /* Collect all candidate point */
1836
1837     CvPoint2D64d candPoints[8];
1838     CvPoint2D64d midPoint;
1839     int numPoints = 0;
1840     int res;
1841     int i;
1842
1843     double cutLine1[3];
1844     double cutLine2[3];
1845
1846     /* Find middle line of sector */
1847     double midLine[3];
1848
1849     
1850     /* Different way  */
1851     CvPoint2D64d pointOnLine1;  pointOnLine1.x = pointOnLine1.y = 0;
1852     CvPoint2D64d pointOnLine2;  pointOnLine2.x = pointOnLine2.y = 0;
1853
1854     CvPoint2D64d start1,end1;
1855
1856     icvGetCrossRectDirect( imageSize,
1857                         areaLineCoef1[0],areaLineCoef1[1],areaLineCoef1[2],
1858                         &start1,&end1,&res);
1859     if( res > 0 )
1860     {
1861         pointOnLine1 = start1;
1862     }
1863
1864     icvGetCrossRectDirect( imageSize,
1865                         areaLineCoef2[0],areaLineCoef2[1],areaLineCoef2[2],
1866                         &start1,&end1,&res);
1867     if( res > 0 )
1868     {
1869         pointOnLine2 = start1;
1870     }
1871
1872     icvGetMiddleAnglePoint(epipole,pointOnLine1,pointOnLine2,&midPoint);
1873
1874     icvGetCoefForPiece(epipole,midPoint,&midLine[0],&midLine[1],&midLine[2],&res);
1875
1876     /* Test corner points */
1877     CvPoint2D64d cornerPoint;
1878     CvPoint2D64d tmpPoints[2];
1879
1880     cornerPoint.x = 0;
1881     cornerPoint.y = 0;
1882     icvTestPoint( cornerPoint, areaLineCoef1, areaLineCoef2, epipole, &res);
1883     if( res == 1 )
1884     {/* Add point */
1885         candPoints[numPoints] = cornerPoint;
1886         numPoints++;
1887     }
1888
1889     cornerPoint.x = imageSize.width;
1890     cornerPoint.y = 0;
1891     icvTestPoint( cornerPoint, areaLineCoef1, areaLineCoef2, epipole, &res);
1892     if( res == 1 )
1893     {/* Add point */
1894         candPoints[numPoints] = cornerPoint;
1895         numPoints++;
1896     }
1897     
1898     cornerPoint.x = imageSize.width;
1899     cornerPoint.y = imageSize.height;
1900     icvTestPoint( cornerPoint, areaLineCoef1, areaLineCoef2, epipole, &res);
1901     if( res == 1 )
1902     {/* Add point */
1903         candPoints[numPoints] = cornerPoint;
1904         numPoints++;
1905     }
1906
1907     cornerPoint.x = 0;
1908     cornerPoint.y = imageSize.height;
1909     icvTestPoint( cornerPoint, areaLineCoef1, areaLineCoef2, epipole, &res);
1910     if( res == 1 )
1911     {/* Add point */
1912         candPoints[numPoints] = cornerPoint;
1913         numPoints++;
1914     }
1915
1916     /* Find cross line 1 with image border */
1917     icvGetCrossRectDirect( imageSize,
1918                         areaLineCoef1[0],areaLineCoef1[1],areaLineCoef1[2],
1919                         &tmpPoints[0], &tmpPoints[1],
1920                         &res);
1921     for( i = 0; i < res; i++ )
1922     {
1923         candPoints[numPoints++] = tmpPoints[i];
1924     }
1925
1926     /* Find cross line 2 with image border */
1927     icvGetCrossRectDirect( imageSize,
1928                         areaLineCoef2[0],areaLineCoef2[1],areaLineCoef2[2],
1929                         &tmpPoints[0], &tmpPoints[1],
1930                         &res);
1931     
1932     for( i = 0; i < res; i++ )
1933     {
1934         candPoints[numPoints++] = tmpPoints[i];
1935     }
1936
1937     if( numPoints < 2 )
1938     {
1939         *result = 0;
1940         return;/* Error. Not enought points */
1941     }
1942     /* Project all points to middle line and get max and min */
1943
1944     CvPoint2D64d projPoint;
1945     CvPoint2D64d minPoint; minPoint.x = minPoint.y = FLT_MAX;
1946     CvPoint2D64d maxPoint; maxPoint.x = maxPoint.y = -FLT_MAX;
1947
1948
1949     double dist;
1950     double maxDist = 0;
1951     double minDist = 10000000;
1952
1953     
1954     for( i = 0; i < numPoints; i++ )
1955     {
1956         icvProjectPointToDirect(candPoints[i], midLine, &projPoint);
1957         icvGetPieceLength(epipole,projPoint,&dist);
1958         if( dist < minDist)
1959         {
1960             minDist = dist;
1961             minPoint = projPoint;
1962         }
1963
1964         if( dist > maxDist)
1965         {
1966             maxDist = dist;
1967             maxPoint = projPoint;
1968         }
1969     }
1970
1971     /* We know maximum and minimum points. Now we can compute cut lines */
1972     
1973     icvGetNormalDirect(midLine,minPoint,cutLine1);
1974     icvGetNormalDirect(midLine,maxPoint,cutLine2);
1975
1976     /* Test for begin of line. */
1977     CvPoint2D64d tmpPoint2;
1978
1979     /* Get cross with */
1980     icvGetCrossDirectDirect(areaLineCoef1,cutLine1,point11,&res);
1981     icvGetCrossDirectDirect(areaLineCoef2,cutLine1,point12,&res);
1982
1983     icvGetCrossDirectDirect(areaLineCoef1,cutLine2,point21,&res);
1984     icvGetCrossDirectDirect(areaLineCoef2,cutLine2,point22,&res);
1985
1986     if( epipole.x > imageSize.width * 0.5 )
1987     {/* Need to change points */
1988         tmpPoint2 = *point11;
1989         *point11 = *point21;
1990         *point21 = tmpPoint2;
1991
1992         tmpPoint2 = *point12;
1993         *point12 = *point22;
1994         *point22 = tmpPoint2;
1995     }
1996
1997     return;
1998 }
1999 /*---------------------------------------------------------------------------------------*/
2000 /* Get middle angle */
2001 void icvGetMiddleAnglePoint(   CvPoint2D64d basePoint,
2002                             CvPoint2D64d point1,CvPoint2D64d point2,
2003                             CvPoint2D64d* midPoint)
2004 {/* !!! May be need to return error */
2005     
2006     double dist1;
2007     double dist2;
2008     icvGetPieceLength(basePoint,point1,&dist1);
2009     icvGetPieceLength(basePoint,point2,&dist2);
2010     CvPoint2D64d pointNew1;
2011     CvPoint2D64d pointNew2;
2012     double alpha = dist2/dist1;
2013
2014     pointNew1.x = basePoint.x + (1.0/alpha) * ( point2.x - basePoint.x );
2015     pointNew1.y = basePoint.y + (1.0/alpha) * ( point2.y - basePoint.y );
2016
2017     pointNew2.x = basePoint.x + alpha * ( point1.x - basePoint.x );
2018     pointNew2.y = basePoint.y + alpha * ( point1.y - basePoint.y );
2019
2020     int res;
2021     icvGetCrossPiecePiece(point1,point2,pointNew1,pointNew2,midPoint,&res);
2022
2023     return;
2024 }
2025
2026 /*---------------------------------------------------------------------------------------*/
2027 /* Get normal direct to direct in line */
2028 void icvGetNormalDirect(CvVect64d direct,CvPoint2D64d point,CvVect64d normDirect)
2029 {
2030     normDirect[0] =   direct[1];
2031     normDirect[1] = - direct[0];
2032     normDirect[2] = -(normDirect[0]*point.x + normDirect[1]*point.y);  
2033     return;
2034 }
2035
2036 /*---------------------------------------------------------------------------------------*/
2037 CV_IMPL double icvGetVect(CvPoint2D64d basePoint,CvPoint2D64d point1,CvPoint2D64d point2)
2038 {
2039     return  (point1.x - basePoint.x)*(point2.y - basePoint.y) -
2040             (point2.x - basePoint.x)*(point1.y - basePoint.y);
2041 }
2042 /*---------------------------------------------------------------------------------------*/
2043 /* Test for point in sector           */
2044 /* Return 0 - point not inside sector */
2045 /* Return 1 - point inside sector     */
2046 void icvTestPoint( CvPoint2D64d testPoint,
2047                 CvVect64d line1,CvVect64d line2,
2048                 CvPoint2D64d basePoint,
2049                 int* result)
2050 {
2051     CvPoint2D64d point1,point2;
2052
2053     icvProjectPointToDirect(testPoint,line1,&point1);
2054     icvProjectPointToDirect(testPoint,line2,&point2);
2055
2056     double sign1 = icvGetVect(basePoint,point1,point2);
2057     double sign2 = icvGetVect(basePoint,point1,testPoint);
2058     if( sign1 * sign2 > 0 )
2059     {/* Correct for first line */
2060         sign1 = - sign1;
2061         sign2 = icvGetVect(basePoint,point2,testPoint);
2062         if( sign1 * sign2 > 0 )
2063         {/* Correct for both lines */
2064             *result = 1;
2065         }
2066         else
2067         {
2068             *result = 0;
2069         }
2070     }
2071     else
2072     {
2073         *result = 0;
2074     }
2075     
2076     return;
2077 }
2078
2079 /*---------------------------------------------------------------------------------------*/
2080 /* Project point to line */
2081 void icvProjectPointToDirect(  CvPoint2D64d point,CvVect64d lineCoeff,
2082                             CvPoint2D64d* projectPoint)
2083 {
2084     double a = lineCoeff[0];
2085     double b = lineCoeff[1];
2086     
2087     double det =  1.0 / ( a*a + b*b );
2088     double delta =  a*point.y - b*point.x;
2089
2090     projectPoint->x = ( -a*lineCoeff[2] - b * delta ) * det;
2091     projectPoint->y = ( -b*lineCoeff[2] + a * delta ) * det ;
2092
2093     return;
2094 }
2095
2096 /*---------------------------------------------------------------------------------------*/
2097 /* Get distance from point to direction */
2098 void icvGetDistanceFromPointToDirect( CvPoint2D64d point,CvVect64d lineCoef,double*dist)
2099 {
2100     CvPoint2D64d tmpPoint;
2101     icvProjectPointToDirect(point,lineCoef,&tmpPoint);
2102     double dx = point.x - tmpPoint.x;
2103     double dy = point.y - tmpPoint.y;
2104     *dist = sqrt(dx*dx+dy*dy);
2105     return;
2106 }
2107 /*---------------------------------------------------------------------------------------*/
2108
2109 CV_IMPL IplImage* icvCreateIsometricImage( IplImage* src, IplImage* dst,
2110                                        int desired_depth, int desired_num_channels )
2111 {
2112     CvSize src_size ;
2113     src_size.width = src->width;
2114     src_size.height = src->height;
2115     
2116     CvSize dst_size = src_size;
2117
2118     if( dst )
2119     {
2120         dst_size.width = dst->width;
2121         dst_size.height = dst->height;
2122     }
2123
2124     if( !dst || dst->depth != desired_depth ||
2125         dst->nChannels != desired_num_channels ||
2126         dst_size.width != src_size.width ||
2127         dst_size.height != dst_size.height )
2128     {
2129         cvReleaseImage( &dst );
2130         dst = cvCreateImage( src_size, desired_depth, desired_num_channels );
2131         CvRect rect = cvRect(0,0,src_size.width,src_size.height);
2132         cvSetImageROI( dst, rect );
2133
2134     }
2135
2136     return dst;
2137 }
2138
2139 int
2140 icvCvt_32f_64d( float *src, double *dst, int size )
2141 {
2142     int t;
2143
2144     if( !src || !dst )
2145         return CV_NULLPTR_ERR;
2146     if( size <= 0 )
2147         return CV_BADRANGE_ERR;
2148
2149     for( t = 0; t < size; t++ )
2150     {
2151         dst[t] = (double) (src[t]);
2152     }
2153
2154     return CV_OK;
2155 }
2156
2157 /*======================================================================================*/
2158 /* Type conversion double -> float */
2159 int
2160 icvCvt_64d_32f( double *src, float *dst, int size )
2161 {
2162     int t;
2163
2164     if( !src || !dst )
2165         return CV_NULLPTR_ERR;
2166     if( size <= 0 )
2167         return CV_BADRANGE_ERR;
2168
2169     for( t = 0; t < size; t++ )
2170     {
2171         dst[t] = (float) (src[t]);
2172     }
2173
2174     return CV_OK;
2175 }
2176
2177 /*----------------------------------------------------------------------------------*/
2178
2179
2180 /* Find line which cross frame by line(a,b,c) */
2181 void FindLineForEpiline(    CvSize imageSize,
2182                             float a,float b,float c,
2183                             CvPoint2D32f *start,CvPoint2D32f *end,
2184                             int* result)
2185 {
2186     result = result;
2187     CvPoint2D32f frameBeg;
2188
2189     CvPoint2D32f frameEnd;
2190     CvPoint2D32f cross[4];
2191     int     haveCross[4];
2192     float   dist;
2193
2194     haveCross[0] = 0;
2195     haveCross[1] = 0;
2196     haveCross[2] = 0;
2197     haveCross[3] = 0;
2198
2199     frameBeg.x = 0;
2200     frameBeg.y = 0;
2201     frameEnd.x = (float)(imageSize.width);
2202     frameEnd.y = 0;
2203     haveCross[0] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[0]);
2204     
2205     frameBeg.x = (float)(imageSize.width);
2206     frameBeg.y = 0;
2207     frameEnd.x = (float)(imageSize.width);
2208     frameEnd.y = (float)(imageSize.height);
2209     haveCross[1] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[1]);
2210
2211     frameBeg.x = (float)(imageSize.width);
2212     frameBeg.y = (float)(imageSize.height);
2213     frameEnd.x = 0;
2214     frameEnd.y = (float)(imageSize.height);
2215     haveCross[2] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[2]);
2216     
2217     frameBeg.x = 0;
2218     frameBeg.y = (float)(imageSize.height);
2219     frameEnd.x = 0;
2220     frameEnd.y = 0;
2221     haveCross[3] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[3]);
2222
2223     int n;
2224     float minDist = (float)(INT_MAX);
2225     float maxDist = (float)(INT_MIN);
2226
2227     int maxN = -1;
2228     int minN = -1;
2229
2230     double midPointX = imageSize.width  / 2.0;
2231     double midPointY = imageSize.height / 2.0;
2232
2233     for( n = 0; n < 4; n++ )
2234     {
2235         if( haveCross[n] > 0 )
2236         {
2237             dist =  (float)((midPointX - cross[n].x)*(midPointX - cross[n].x) +
2238                             (midPointY - cross[n].y)*(midPointY - cross[n].y));
2239
2240             if( dist < minDist )
2241             {
2242                 minDist = dist;
2243                 minN = n;
2244             }
2245
2246             if( dist > maxDist )
2247             {
2248                 maxDist = dist;
2249                 maxN = n;
2250             }
2251         }
2252     }
2253
2254     if( minN >= 0 && maxN >= 0 && (minN != maxN) )
2255     {
2256         *start = cross[minN];
2257         *end   = cross[maxN];
2258     }
2259     else
2260     {
2261         start->x = 0;
2262         start->y = 0;
2263         end->x = 0;
2264         end->y = 0;
2265     }
2266
2267     return;
2268     
2269 }
2270
2271
2272 /*----------------------------------------------------------------------------------*/
2273
2274 int GetAngleLinee( CvPoint2D32f epipole, CvSize imageSize,CvPoint2D32f point1,CvPoint2D32f point2)
2275 {
2276     float width  = (float)(imageSize.width);
2277     float height = (float)(imageSize.height);
2278
2279     /* Get crosslines with image corners */
2280
2281     /* Find four lines */
2282
2283     CvPoint2D32f pa,pb,pc,pd;
2284     
2285     pa.x = 0;
2286     pa.y = 0;
2287
2288     pb.x = width;
2289     pb.y = 0;
2290
2291     pd.x = width;
2292     pd.y = height;
2293
2294     pc.x = 0;
2295     pc.y = height;
2296
2297     /* We can compute points for angle */
2298     /* Test for place section */
2299
2300     float x,y;
2301     x = epipole.x;
2302     y = epipole.y;
2303     
2304     if( x < 0 )
2305     {/* 1,4,7 */
2306         if( y < 0)
2307         {/* 1 */
2308             point1 = pb;
2309             point2 = pc;
2310         }
2311         else if( y > height )
2312         {/* 7 */
2313             point1 = pa;
2314             point2 = pd;
2315         }
2316         else
2317         {/* 4 */
2318             point1 = pa;
2319             point2 = pc;
2320         }
2321     }
2322     else if ( x > width )
2323     {/* 3,6,9 */
2324         if( y < 0 )
2325         {/* 3 */
2326             point1 = pa;
2327             point2 = pd;
2328         }
2329         else if ( y > height )
2330         {/* 9 */
2331             point1 = pc;
2332             point2 = pb;
2333         }
2334         else
2335         {/* 6 */
2336             point1 = pb;
2337             point2 = pd;
2338         }
2339     }
2340     else
2341     {/* 2,5,8 */
2342         if( y < 0 )
2343         {/* 2 */
2344             point1 = pa;
2345             point2 = pb;
2346         }
2347         else if( y > height )
2348         {/* 8 */
2349             point1 = pc;
2350             point2 = pd;
2351         }
2352         else
2353         {/* 5 - point in the image */
2354             return 2;
2355         }
2356
2357         
2358     }
2359     
2360
2361     return 0;
2362 }
2363
2364 /*--------------------------------------------------------------------------------------*/
2365 void icvComputePerspectiveCoeffs(const CvPoint2D32f srcQuad[4],const CvPoint2D32f dstQuad[4],double coeffs[3][3])
2366 {/* Computes perspective coeffs for transformation from src to dst quad */
2367
2368
2369     CV_FUNCNAME( "icvComputePerspectiveCoeffs" );
2370
2371     __BEGIN__;
2372
2373     double A[64];
2374     double b[8];
2375     double c[8];
2376     CvPoint2D32f pt[4];
2377     int i;
2378
2379     pt[0] = srcQuad[0];
2380     pt[1] = srcQuad[1];
2381     pt[2] = srcQuad[2];
2382     pt[3] = srcQuad[3];
2383
2384     for( i = 0; i < 4; i++ )
2385     {
2386 #if 0
2387         double x = dstQuad[i].x;
2388         double y = dstQuad[i].y;
2389         double X = pt[i].x;
2390         double Y = pt[i].y;
2391 #else
2392         double x = pt[i].x;
2393         double y = pt[i].y;
2394         double X = dstQuad[i].x;
2395         double Y = dstQuad[i].y;
2396 #endif
2397         double* a = A + i*16;
2398         
2399         a[0] = x;
2400         a[1] = y;
2401         a[2] = 1;
2402         a[3] = 0;
2403         a[4] = 0;
2404         a[5] = 0;
2405         a[6] = -X*x;
2406         a[7] = -X*y;
2407
2408         a += 8;
2409
2410         a[0] = 0;
2411         a[1] = 0;
2412         a[2] = 0;
2413         a[3] = x;
2414         a[4] = y;
2415         a[5] = 1;
2416         a[6] = -Y*x;
2417         a[7] = -Y*y;
2418
2419         b[i*2] = X;
2420         b[i*2 + 1] = Y;
2421     }
2422
2423     {
2424     double invA[64];
2425     CvMat matA = cvMat( 8, 8, CV_64F, A );
2426     CvMat matInvA = cvMat( 8, 8, CV_64F, invA );
2427     CvMat matB = cvMat( 8, 1, CV_64F, b );
2428     CvMat matX = cvMat( 8, 1, CV_64F, c );
2429
2430     CV_CALL( cvPseudoInverse( &matA, &matInvA ));
2431     CV_CALL( cvMatMulAdd( &matInvA, &matB, 0, &matX ));
2432     }
2433     
2434     coeffs[0][0] = c[0];
2435     coeffs[0][1] = c[1];
2436     coeffs[0][2] = c[2];
2437     coeffs[1][0] = c[3];
2438     coeffs[1][1] = c[4];
2439     coeffs[1][2] = c[5];
2440     coeffs[2][0] = c[6];
2441     coeffs[2][1] = c[7];
2442     coeffs[2][2] = 1.0;
2443
2444     __END__;
2445
2446     return;
2447 }
2448
2449 /*--------------------------------------------------------------------------------------*/
2450
2451 CV_IMPL void cvComputePerspectiveMap(const double c[3][3], CvArr* rectMapX, CvArr* rectMapY )
2452 {
2453     CV_FUNCNAME( "cvComputePerspectiveMap" );
2454
2455     __BEGIN__;
2456
2457     CvSize size;
2458     CvMat  stubx, *mapx = (CvMat*)rectMapX;
2459     CvMat  stuby, *mapy = (CvMat*)rectMapY;
2460     int i, j;
2461
2462     CV_CALL( mapx = cvGetMat( mapx, &stubx ));
2463     CV_CALL( mapy = cvGetMat( mapy, &stuby ));
2464
2465     if( CV_MAT_TYPE( mapx->type ) != CV_32FC1 || CV_MAT_TYPE( mapy->type ) != CV_32FC1 )
2466         CV_ERROR( CV_StsUnsupportedFormat, "" );
2467
2468     size = cvGetMatSize(mapx);
2469     assert( fabs(c[2][2] - 1.) < FLT_EPSILON );
2470     
2471     for( i = 0; i < size.height; i++ )
2472     {
2473         float* mx = (float*)(mapx->data.ptr + mapx->step*i);
2474         float* my = (float*)(mapy->data.ptr + mapy->step*i);
2475
2476         for( j = 0; j < size.width; j++ )
2477         {
2478             double w = 1./(c[2][0]*j + c[2][1]*i + 1.);
2479             double x = (c[0][0]*j + c[0][1]*i + c[0][2])*w;
2480             double y = (c[1][0]*j + c[1][1]*i + c[1][2])*w;
2481
2482             mx[j] = (float)x;
2483             my[j] = (float)y;
2484         }
2485     }
2486
2487     __END__;
2488 }
2489
2490 /*--------------------------------------------------------------------------------------*/
2491
2492 CV_IMPL void cvInitPerspectiveTransform( CvSize size, const CvPoint2D32f quad[4], double matrix[3][3],
2493                                               CvArr* rectMap )
2494 {
2495     /* Computes Perspective Transform coeffs and map if need
2496         for given image size and given result quad */
2497     CV_FUNCNAME( "cvInitPerspectiveTransform" );
2498
2499     __BEGIN__;
2500
2501     double A[64];
2502     double b[8];
2503     double c[8];
2504     CvPoint2D32f pt[4];
2505     CvMat  mapstub, *map = (CvMat*)rectMap;
2506     int i, j;
2507
2508     if( map )
2509     {
2510         CV_CALL( map = cvGetMat( map, &mapstub ));
2511
2512         if( CV_MAT_TYPE( map->type ) != CV_32FC2 )
2513             CV_ERROR( CV_StsUnsupportedFormat, "" );
2514
2515         if( map->width != size.width || map->height != size.height )
2516             CV_ERROR( CV_StsUnmatchedSizes, "" );
2517     }
2518
2519     pt[0] = cvPoint2D32f( 0, 0 );
2520     pt[1] = cvPoint2D32f( size.width, 0 );
2521     pt[2] = cvPoint2D32f( size.width, size.height );
2522     pt[3] = cvPoint2D32f( 0, size.height );
2523
2524     for( i = 0; i < 4; i++ )
2525     {
2526 #if 0
2527         double x = quad[i].x;
2528         double y = quad[i].y;
2529         double X = pt[i].x;
2530         double Y = pt[i].y;
2531 #else
2532         double x = pt[i].x;
2533         double y = pt[i].y;
2534         double X = quad[i].x;
2535         double Y = quad[i].y;
2536 #endif
2537         double* a = A + i*16;
2538         
2539         a[0] = x;
2540         a[1] = y;
2541         a[2] = 1;
2542         a[3] = 0;
2543         a[4] = 0;
2544         a[5] = 0;
2545         a[6] = -X*x;
2546         a[7] = -X*y;
2547
2548         a += 8;
2549
2550         a[0] = 0;
2551         a[1] = 0;
2552         a[2] = 0;
2553         a[3] = x;
2554         a[4] = y;
2555         a[5] = 1;
2556         a[6] = -Y*x;
2557         a[7] = -Y*y;
2558
2559         b[i*2] = X;
2560         b[i*2 + 1] = Y;
2561     }
2562
2563     {
2564     double invA[64];
2565     CvMat matA = cvMat( 8, 8, CV_64F, A );
2566     CvMat matInvA = cvMat( 8, 8, CV_64F, invA );
2567     CvMat matB = cvMat( 8, 1, CV_64F, b );
2568     CvMat matX = cvMat( 8, 1, CV_64F, c );
2569
2570     CV_CALL( cvPseudoInverse( &matA, &matInvA ));
2571     CV_CALL( cvMatMulAdd( &matInvA, &matB, 0, &matX ));
2572     }
2573     
2574     matrix[0][0] = c[0];
2575     matrix[0][1] = c[1];
2576     matrix[0][2] = c[2];
2577     matrix[1][0] = c[3];
2578     matrix[1][1] = c[4];
2579     matrix[1][2] = c[5];
2580     matrix[2][0] = c[6];
2581     matrix[2][1] = c[7];
2582     matrix[2][2] = 1.0;
2583
2584     if( map )
2585     {
2586         for( i = 0; i < size.height; i++ )
2587         {
2588             CvPoint2D32f* maprow = (CvPoint2D32f*)(map->data.ptr + map->step*i);
2589             for( j = 0; j < size.width; j++ )
2590             {
2591                 double w = 1./(c[6]*j + c[7]*i + 1.);
2592                 double x = (c[0]*j + c[1]*i + c[2])*w;
2593                 double y = (c[3]*j + c[4]*i + c[5])*w;
2594
2595                 maprow[j].x = (float)x;
2596                 maprow[j].y = (float)y;
2597             }
2598         }
2599     }
2600
2601     __END__;
2602
2603     return;
2604 }
2605
2606
2607 /*-----------------------------------------------------------------------*/
2608 /* Compute projected infinite point for second image if first image point is known */
2609 void icvComputeeInfiniteProject1(   CvMatr64d     rotMatr,
2610                                     CvMatr64d     camMatr1,
2611                                     CvMatr64d     camMatr2,
2612                                     CvPoint2D32f  point1,
2613                                     CvPoint2D32f* point2)
2614 {
2615     double invMatr1[9];
2616     icvInvertMatrix_64d(camMatr1,3,invMatr1);
2617     double P1[3];
2618     double p1[3];
2619     p1[0] = (double)(point1.x);
2620     p1[1] = (double)(point1.y);
2621     p1[2] = 1;
2622
2623     icvMulMatrix_64d(   invMatr1,
2624                         3,3,
2625                         p1,
2626                         1,3, 
2627                         P1);
2628
2629     double invR[9];
2630     icvTransposeMatrix_64d( rotMatr, 3, 3, invR );
2631
2632     /* Change system 1 to system 2 */
2633     double P2[3];
2634     icvMulMatrix_64d(   invR,
2635                         3,3,
2636                         P1,
2637                         1,3, 
2638                         P2);
2639
2640     /* Now we can project this point to image 2 */
2641     double projP[3];
2642
2643     icvMulMatrix_64d(   camMatr2,
2644                         3,3,
2645                         P2,
2646                         1,3, 
2647                         projP);
2648
2649     point2->x = (float)(projP[0] / projP[2]);
2650     point2->y = (float)(projP[1] / projP[2]);
2651
2652     return;
2653 }
2654
2655 /*-----------------------------------------------------------------------*/
2656 /* Compute projected infinite point for second image if first image point is known */
2657 void icvComputeeInfiniteProject2(   CvMatr64d     rotMatr,
2658                                     CvMatr64d     camMatr1,
2659                                     CvMatr64d     camMatr2,
2660                                     CvPoint2D32f*  point1,
2661                                     CvPoint2D32f point2)
2662 {
2663     double invMatr2[9];
2664     icvInvertMatrix_64d(camMatr2,3,invMatr2);
2665     double P2[3];
2666     double p2[3];
2667     p2[0] = (double)(point2.x);
2668     p2[1] = (double)(point2.y);
2669     p2[2] = 1;
2670
2671     icvMulMatrix_64d(   invMatr2,
2672                         3,3,
2673                         p2,
2674                         1,3, 
2675                         P2);
2676
2677     /* Change system 1 to system 2 */
2678
2679     double P1[3];
2680     icvMulMatrix_64d(   rotMatr,
2681                         3,3,
2682                         P2,
2683                         1,3, 
2684                         P1);
2685
2686     /* Now we can project this point to image 2 */
2687     double projP[3];
2688
2689     icvMulMatrix_64d(   camMatr1,
2690                         3,3,
2691                         P1,
2692                         1,3, 
2693                         projP);
2694
2695     point1->x = (float)(projP[0] / projP[2]);
2696     point1->y = (float)(projP[1] / projP[2]);
2697
2698     return;
2699 }
2700
2701 /* Select best R and t for given cameras, points, ... */
2702 /* For both cameras */
2703 int icvSelectBestRt(           int           numImages,
2704                                     int*          numPoints,
2705                                     CvPoint2D32f* imagePoints1,
2706                                     CvPoint2D32f* imagePoints2,
2707                                     CvPoint3D32f* objectPoints,
2708
2709                                     CvMatr32f     cameraMatrix1,
2710                                     CvVect32f     distortion1,
2711                                     CvMatr32f     rotMatrs1,
2712                                     CvVect32f     transVects1,
2713
2714                                     CvMatr32f     cameraMatrix2,
2715                                     CvVect32f     distortion2,
2716                                     CvMatr32f     rotMatrs2,
2717                                     CvVect32f     transVects2,
2718
2719                                     CvMatr32f     bestRotMatr,
2720                                     CvVect32f     bestTransVect
2721                                     )
2722 {
2723
2724     /* Need to convert input data 32 -> 64 */
2725     CvPoint3D64d* objectPoints_64d;
2726     
2727     double* rotMatrs1_64d;
2728     double* rotMatrs2_64d;
2729
2730     double* transVects1_64d;
2731     double* transVects2_64d;
2732
2733     double cameraMatrix1_64d[9];
2734     double cameraMatrix2_64d[9];
2735
2736     double distortion1_64d[4];
2737     double distortion2_64d[4];
2738
2739     /* allocate memory for 64d data */
2740     int totalNum = 0;
2741
2742     int i;
2743     for( i = 0; i < numImages; i++ )
2744     {
2745         totalNum += numPoints[i];
2746     }
2747
2748     objectPoints_64d = (CvPoint3D64d*)calloc(totalNum,sizeof(CvPoint3D64d));
2749     
2750     rotMatrs1_64d    = (double*)calloc(numImages,sizeof(double)*9);
2751     rotMatrs2_64d    = (double*)calloc(numImages,sizeof(double)*9);
2752
2753     transVects1_64d  = (double*)calloc(numImages,sizeof(double)*3);
2754     transVects2_64d  = (double*)calloc(numImages,sizeof(double)*3);
2755
2756     /* Convert input data to 64d */
2757     
2758     icvCvt_32f_64d((float*)objectPoints, (double*)objectPoints_64d,  totalNum*3);
2759
2760     icvCvt_32f_64d(rotMatrs1, rotMatrs1_64d,  numImages*9);
2761     icvCvt_32f_64d(rotMatrs2, rotMatrs2_64d,  numImages*9);
2762
2763     icvCvt_32f_64d(transVects1, transVects1_64d,  numImages*3);
2764     icvCvt_32f_64d(transVects2, transVects2_64d,  numImages*3);
2765
2766     /* Convert to arrays */
2767     icvCvt_32f_64d(cameraMatrix1, cameraMatrix1_64d, 9);
2768     icvCvt_32f_64d(cameraMatrix2, cameraMatrix2_64d, 9);
2769
2770     icvCvt_32f_64d(distortion1, distortion1_64d, 4);
2771     icvCvt_32f_64d(distortion2, distortion2_64d, 4);
2772
2773
2774     /* for each R and t compute error for image pair */
2775     float* errors;
2776
2777     errors = (float*)calloc(numImages*numImages,sizeof(float));
2778     if( errors == 0 )
2779     {
2780         return CV_OUTOFMEM_ERR;
2781     }
2782
2783     int currImagePair;
2784     int currRt;
2785     for( currRt = 0; currRt < numImages; currRt++ )
2786     {
2787         int begPoint = 0; 
2788         for(currImagePair = 0; currImagePair < numImages; currImagePair++ )
2789         {
2790             /* For current R,t R,t compute relative position of cameras */
2791
2792             double convRotMatr[9];
2793             double convTransVect[3];
2794             
2795             icvCreateConvertMatrVect( rotMatrs1_64d + currRt*9,
2796                                       transVects1_64d + currRt*3,
2797                                       rotMatrs2_64d + currRt*9,
2798                                       transVects2_64d + currRt*3,
2799                                       convRotMatr,
2800                                       convTransVect);
2801
2802             /* Project points using relative position of cameras */
2803
2804             double convRotMatr2[9];
2805             double convTransVect2[3];
2806
2807             convRotMatr2[0] = 1;
2808             convRotMatr2[1] = 0;
2809             convRotMatr2[2] = 0;
2810
2811             convRotMatr2[3] = 0;
2812             convRotMatr2[4] = 1;
2813             convRotMatr2[5] = 0;
2814
2815             convRotMatr2[6] = 0;
2816             convRotMatr2[7] = 0;
2817             convRotMatr2[8] = 1;
2818
2819             convTransVect2[0] = 0;
2820             convTransVect2[1] = 0;
2821             convTransVect2[2] = 0;
2822
2823             /* Compute error for given pair and Rt */
2824             /* We must project points to image and compute error */
2825
2826             CvPoint2D64d* projImagePoints1;
2827             CvPoint2D64d* projImagePoints2;
2828
2829             CvPoint3D64d* points1;
2830             CvPoint3D64d* points2;
2831
2832             int numberPnt;
2833             numberPnt = numPoints[currImagePair];
2834             projImagePoints1 = (CvPoint2D64d*)calloc(numberPnt,sizeof(CvPoint2D64d));
2835             projImagePoints2 = (CvPoint2D64d*)calloc(numberPnt,sizeof(CvPoint2D64d));
2836
2837             points1 = (CvPoint3D64d*)calloc(numberPnt,sizeof(CvPoint3D64d));
2838             points2 = (CvPoint3D64d*)calloc(numberPnt,sizeof(CvPoint3D64d));
2839
2840             /* Transform object points to first camera position */
2841             int i;
2842             for( i = 0; i < numberPnt; i++ )
2843             {
2844                 /* Create second camera point */
2845                 CvPoint3D64d tmpPoint;
2846                 tmpPoint.x = (double)(objectPoints[i].x);
2847                 tmpPoint.y = (double)(objectPoints[i].y);
2848                 tmpPoint.z = (double)(objectPoints[i].z);
2849                 
2850                 icvConvertPointSystem(  tmpPoint,
2851                                         points2+i,
2852                                         rotMatrs2_64d + currImagePair*9,
2853                                         transVects2_64d + currImagePair*3);
2854
2855                 /* Create first camera point using R, t */
2856                 icvConvertPointSystem(  points2[i],
2857                                         points1+i,
2858                                         convRotMatr,
2859                                         convTransVect);
2860
2861                 CvPoint3D64d tmpPoint2 = { 0, 0, 0 };
2862                 icvConvertPointSystem(  tmpPoint,
2863                                         &tmpPoint2,
2864                                         rotMatrs1_64d + currImagePair*9,
2865                                         transVects1_64d + currImagePair*3);
2866                 double err;
2867                 double dx,dy,dz;
2868                 dx = tmpPoint2.x - points1[i].x;
2869                 dy = tmpPoint2.y - points1[i].y;
2870                 dz = tmpPoint2.z - points1[i].z;
2871                 err = sqrt(dx*dx + dy*dy + dz*dz);
2872
2873
2874             }
2875             
2876 #if 0
2877             cvProjectPointsSimple(  numPoints[currImagePair],
2878                                     objectPoints_64d + begPoint,
2879                                     rotMatrs1_64d + currRt*9,
2880                                     transVects1_64d + currRt*3,
2881                                     cameraMatrix1_64d,
2882                                     distortion1_64d,
2883                                     projImagePoints1);
2884
2885             cvProjectPointsSimple(  numPoints[currImagePair],
2886                                     objectPoints_64d + begPoint,
2887                                     rotMatrs2_64d + currRt*9,
2888                                     transVects2_64d + currRt*3,
2889                                     cameraMatrix2_64d,
2890                                     distortion2_64d,
2891                                     projImagePoints2);
2892 #endif
2893
2894             /* Project with no translate and no rotation */
2895
2896 #if 0
2897             {
2898                 double nodist[4] = {0,0,0,0};
2899                 cvProjectPointsSimple(  numPoints[currImagePair],
2900                                         points1,
2901                                         convRotMatr2,
2902                                         convTransVect2,
2903                                         cameraMatrix1_64d,
2904                                         nodist,
2905                                         projImagePoints1);
2906
2907                 cvProjectPointsSimple(  numPoints[currImagePair],
2908                                         points2,
2909                                         convRotMatr2,
2910                                         convTransVect2,
2911                                         cameraMatrix2_64d,
2912                                         nodist,
2913                                         projImagePoints2);
2914                 
2915             }
2916 #endif
2917
2918             cvProjectPointsSimple(  numPoints[currImagePair],
2919                                     points1,
2920                                     convRotMatr2,
2921                                     convTransVect2,
2922                                     cameraMatrix1_64d,
2923                                     distortion1_64d,
2924                                     projImagePoints1);
2925
2926             cvProjectPointsSimple(  numPoints[currImagePair],
2927                                     points2,
2928                                     convRotMatr2,
2929                                     convTransVect2,
2930                                     cameraMatrix2_64d,
2931                                     distortion2_64d,
2932                                     projImagePoints2);
2933
2934             /* points are projected. Compute error */
2935
2936             int currPoint;
2937             double err1 = 0;
2938             double err2 = 0;
2939             double err;
2940             for( currPoint = 0; currPoint < numberPnt; currPoint++ )
2941             {
2942                 double len1,len2; 
2943                 double dx1,dy1;
2944                 dx1 = imagePoints1[begPoint+currPoint].x - projImagePoints1[currPoint].x;
2945                 dy1 = imagePoints1[begPoint+currPoint].y - projImagePoints1[currPoint].y;
2946                 len1 = sqrt(dx1*dx1 + dy1*dy1);
2947                 err1 += len1;
2948
2949                 double dx2,dy2;
2950                 dx2 = imagePoints2[begPoint+currPoint].x - projImagePoints2[currPoint].x;
2951                 dy2 = imagePoints2[begPoint+currPoint].y - projImagePoints2[currPoint].y;
2952                 len2 = sqrt(dx2*dx2 + dy2*dy2);
2953                 err2 += len2;
2954             }
2955
2956             err1 /= (float)(numberPnt);
2957             err2 /= (float)(numberPnt);
2958
2959             err = (err1+err2) * 0.5;
2960             begPoint += numberPnt;
2961
2962             /* Set this error to */
2963             errors[numImages*currImagePair+currRt] = (float)err;
2964
2965             free(points1);
2966             free(points2);
2967             free(projImagePoints1);
2968             free(projImagePoints2);
2969         }
2970     }
2971
2972     /* Just select R and t with minimal average error */
2973
2974     int bestnumRt = 0;
2975     float minError = 0;/* Just for no warnings. Uses 'first' flag. */
2976     int first = 1;
2977     for( currRt = 0; currRt < numImages; currRt++ )
2978     {
2979         float avErr = 0;
2980         for(currImagePair = 0; currImagePair < numImages; currImagePair++ )
2981         {
2982             avErr += errors[numImages*currImagePair+currRt];
2983         }
2984         avErr /= (float)(numImages);
2985
2986         if( first )
2987         {
2988             bestnumRt = 0;
2989             minError = avErr;
2990             first = 0;
2991         }
2992         else
2993         {
2994             if( avErr < minError )
2995             {
2996                 bestnumRt = currRt;
2997                 minError = avErr;
2998             }
2999         }
3000
3001     }
3002
3003     double bestRotMatr_64d[9];
3004     double bestTransVect_64d[3];
3005
3006     icvCreateConvertMatrVect( rotMatrs1_64d + bestnumRt * 9,
3007                               transVects1_64d + bestnumRt * 3,
3008                               rotMatrs2_64d + bestnumRt * 9,
3009                               transVects2_64d + bestnumRt * 3,
3010                               bestRotMatr_64d,
3011                               bestTransVect_64d);
3012
3013     icvCvt_64d_32f(bestRotMatr_64d,bestRotMatr,9);
3014     icvCvt_64d_32f(bestTransVect_64d,bestTransVect,3);
3015
3016
3017     free(errors);
3018
3019     return CV_OK;
3020 }
3021
3022
3023 /* ----------------- Stereo calibration functions --------------------- */
3024
3025 float icvDefinePointPosition(CvPoint2D32f point1,CvPoint2D32f point2,CvPoint2D32f point)
3026 {
3027     float ax = point2.x - point1.x;
3028     float ay = point2.y - point1.y;
3029
3030     float bx = point.x - point1.x;
3031     float by = point.y - point1.y;
3032
3033     return (ax*by - ay*bx);
3034 }
3035
3036 /* Convert function for stereo warping */
3037 int icvConvertWarpCoordinates(double coeffs[3][3],
3038                                 CvPoint2D32f* cameraPoint,
3039                                 CvPoint2D32f* warpPoint,
3040                                 int direction)
3041 {
3042     double x,y;
3043     double det; 
3044     if( direction == CV_WARP_TO_CAMERA )
3045     {/* convert from camera image to warped image coordinates */
3046         x = warpPoint->x;
3047         y = warpPoint->y;
3048         
3049         det = (coeffs[2][0] * x + coeffs[2][1] * y + coeffs[2][2]);
3050         if( fabs(det) > 1e-8 )
3051         {
3052             cameraPoint->x = (float)((coeffs[0][0] * x + coeffs[0][1] * y + coeffs[0][2]) / det);
3053             cameraPoint->y = (float)((coeffs[1][0] * x + coeffs[1][1] * y + coeffs[1][2]) / det);
3054             return CV_OK;
3055         }
3056     }
3057     else if( direction == CV_CAMERA_TO_WARP )
3058     {/* convert from warped image to camera image coordinates */
3059         x = cameraPoint->x;
3060         y = cameraPoint->y;
3061
3062         det = (coeffs[2][0]*x-coeffs[0][0])*(coeffs[2][1]*y-coeffs[1][1])-(coeffs[2][1]*x-coeffs[0][1])*(coeffs[2][0]*y-coeffs[1][0]);
3063
3064         if( fabs(det) > 1e-8 )
3065         {
3066             warpPoint->x = (float)(((coeffs[0][2]-coeffs[2][2]*x)*(coeffs[2][1]*y-coeffs[1][1])-(coeffs[2][1]*x-coeffs[0][1])*(coeffs[1][2]-coeffs[2][2]*y))/det);
3067             warpPoint->y = (float)(((coeffs[2][0]*x-coeffs[0][0])*(coeffs[1][2]-coeffs[2][2]*y)-(coeffs[0][2]-coeffs[2][2]*x)*(coeffs[2][0]*y-coeffs[1][0]))/det);
3068             return CV_OK;
3069         }
3070     }
3071     
3072     return CV_BADFACTOR_ERR;
3073 }
3074
3075 /* Compute stereo params using some camera params */
3076 /* by Valery Mosyagin. int ComputeRestStereoParams(StereoParams *stereoparams) */
3077 int icvComputeRestStereoParams(CvStereoCamera *stereoparams)
3078 {
3079
3080
3081     icvGetQuadsTransformStruct(stereoparams);
3082
3083     cvInitPerspectiveTransform( stereoparams->warpSize,
3084                                 stereoparams->quad[0],
3085                                 stereoparams->coeffs[0],
3086                                 0);
3087
3088     cvInitPerspectiveTransform( stereoparams->warpSize,
3089                                 stereoparams->quad[1],
3090                                 stereoparams->coeffs[1],
3091                                 0);
3092
3093     /* Create border for warped images */
3094     CvPoint2D32f corns[4];
3095     corns[0].x = 0;
3096     corns[0].y = 0;
3097
3098     corns[1].x = (float)(stereoparams->camera[0]->imgSize[0]-1);
3099     corns[1].y = 0;
3100
3101     corns[2].x = (float)(stereoparams->camera[0]->imgSize[0]-1);
3102     corns[2].y = (float)(stereoparams->camera[0]->imgSize[1]-1);
3103
3104     corns[3].x = 0;
3105     corns[3].y = (float)(stereoparams->camera[0]->imgSize[1]-1);
3106
3107     int i;
3108     for( i = 0; i < 4; i++ )
3109     {
3110         /* For first camera */
3111         icvConvertWarpCoordinates( stereoparams->coeffs[0],
3112                                 corns+i,
3113                                 stereoparams->border[0]+i,
3114                                 CV_CAMERA_TO_WARP);
3115
3116         /* For second camera */
3117         icvConvertWarpCoordinates( stereoparams->coeffs[1],
3118                                 corns+i,
3119                                 stereoparams->border[1]+i,
3120                                 CV_CAMERA_TO_WARP);
3121     }
3122
3123     /* Test compute  */
3124     {
3125         CvPoint2D32f warpPoints[4];
3126         warpPoints[0] = cvPoint2D32f(0,0);
3127         warpPoints[1] = cvPoint2D32f(stereoparams->warpSize.width-1,0);
3128         warpPoints[2] = cvPoint2D32f(stereoparams->warpSize.width-1,stereoparams->warpSize.height-1);
3129         warpPoints[3] = cvPoint2D32f(0,stereoparams->warpSize.height-1);
3130
3131         CvPoint2D32f camPoints1[4];
3132         CvPoint2D32f camPoints2[4];
3133
3134         for( int i = 0; i < 4; i++ )
3135         {
3136             icvConvertWarpCoordinates(stereoparams->coeffs[0],
3137                                 camPoints1+i,
3138                                 warpPoints+i,
3139                                 CV_WARP_TO_CAMERA);
3140
3141             icvConvertWarpCoordinates(stereoparams->coeffs[1],
3142                                 camPoints2+i,
3143                                 warpPoints+i,
3144                                 CV_WARP_TO_CAMERA);
3145         }
3146     }
3147
3148
3149     /* Allocate memory for scanlines coeffs */
3150
3151     stereoparams->lineCoeffs = (CvStereoLineCoeff*)calloc(stereoparams->warpSize.height,sizeof(CvStereoLineCoeff));
3152
3153     /* Compute coeffs for epilines  */
3154
3155     icvComputeCoeffForStereo( stereoparams);
3156
3157     /* all coeffs are known */
3158     return CV_OK;
3159 }
3160
3161 /*-------------------------------------------------------------------------------------------*/
3162
3163 int icvStereoCalibration( int numImages,
3164                             int* nums,
3165                             CvSize imageSize,
3166                             CvPoint2D32f* imagePoints1,
3167                             CvPoint2D32f* imagePoints2,
3168                             CvPoint3D32f* objectPoints,
3169                             CvStereoCamera* stereoparams
3170                            )
3171 {
3172     /* Firstly we must calibrate both cameras */
3173     /*  Alocate memory for data */
3174     /* Allocate for translate vectors */
3175     float* transVects1;
3176     float* transVects2;
3177     float* rotMatrs1;
3178     float* rotMatrs2;
3179
3180     transVects1 = (float*)calloc(numImages,sizeof(float)*3);
3181     transVects2 = (float*)calloc(numImages,sizeof(float)*3);
3182
3183     rotMatrs1   = (float*)calloc(numImages,sizeof(float)*9);
3184     rotMatrs2   = (float*)calloc(numImages,sizeof(float)*9);
3185
3186     /* Calibrate first camera */
3187     cvCalibrateCamera(  numImages,
3188                         nums,
3189                         imageSize,
3190                         imagePoints1,
3191                         objectPoints,
3192                         stereoparams->camera[0]->distortion,
3193                         stereoparams->camera[0]->matrix,
3194                         transVects1,
3195                         rotMatrs1,
3196                         1);
3197
3198     /* Calibrate second camera */
3199     cvCalibrateCamera(  numImages,
3200                         nums,
3201                         imageSize,
3202                         imagePoints2,
3203                         objectPoints,
3204                         stereoparams->camera[1]->distortion,
3205                         stereoparams->camera[1]->matrix,
3206                         transVects2,
3207                         rotMatrs2,
3208                         1);
3209
3210     /* Cameras are calibrated */
3211
3212     stereoparams->camera[0]->imgSize[0] = (float)imageSize.width;
3213     stereoparams->camera[0]->imgSize[1] = (float)imageSize.height;
3214
3215     stereoparams->camera[1]->imgSize[0] = (float)imageSize.width;
3216     stereoparams->camera[1]->imgSize[1] = (float)imageSize.height;
3217
3218     icvSelectBestRt(    numImages,
3219                         nums,
3220                         imagePoints1,
3221                         imagePoints2,
3222                         objectPoints,
3223                         stereoparams->camera[0]->matrix,
3224                         stereoparams->camera[0]->distortion,
3225                         rotMatrs1,
3226                         transVects1,
3227                         stereoparams->camera[1]->matrix,
3228                         stereoparams->camera[1]->distortion,
3229                         rotMatrs2,
3230                         transVects2,
3231                         stereoparams->rotMatrix,
3232                         stereoparams->transVector
3233                         );
3234
3235     /* Free memory */
3236     free(transVects1);
3237     free(transVects2);
3238     free(rotMatrs1);
3239     free(rotMatrs2);
3240
3241     icvComputeRestStereoParams(stereoparams);
3242
3243     return CV_NO_ERR;
3244 }
3245
3246 /* Find line from epipole */
3247 void FindLine(CvPoint2D32f epipole,CvSize imageSize,CvPoint2D32f point,CvPoint2D32f *start,CvPoint2D32f *end)
3248 {
3249     CvPoint2D32f frameBeg;
3250     CvPoint2D32f frameEnd;
3251     CvPoint2D32f cross[4];
3252     int     haveCross[4];
3253     float   dist;
3254
3255     haveCross[0] = 0;
3256     haveCross[1] = 0;
3257     haveCross[2] = 0;
3258     haveCross[3] = 0;
3259
3260     frameBeg.x = 0;
3261     frameBeg.y = 0;
3262     frameEnd.x = (float)(imageSize.width);
3263     frameEnd.y = 0;
3264     haveCross[0] = icvGetCrossPieceVector(frameBeg,frameEnd,epipole,point,&cross[0]);
3265     
3266     frameBeg.x = (float)(imageSize.width);
3267     frameBeg.y = 0;
3268     frameEnd.x = (float)(imageSize.width);
3269     frameEnd.y = (float)(imageSize.height);
3270     haveCross[1] = icvGetCrossPieceVector(frameBeg,frameEnd,epipole,point,&cross[1]);
3271
3272     frameBeg.x = (float)(imageSize.width);
3273     frameBeg.y = (float)(imageSize.height);
3274     frameEnd.x = 0;
3275     frameEnd.y = (float)(imageSize.height);
3276     haveCross[2] = icvGetCrossPieceVector(frameBeg,frameEnd,epipole,point,&cross[2]);
3277     
3278     frameBeg.x = 0;
3279     frameBeg.y = (float)(imageSize.height);
3280     frameEnd.x = 0;
3281     frameEnd.y = 0;
3282     haveCross[3] = icvGetCrossPieceVector(frameBeg,frameEnd,epipole,point,&cross[3]);
3283
3284     int n;
3285     float minDist = (float)(INT_MAX);
3286     float maxDist = (float)(INT_MIN);
3287
3288     int maxN = -1;
3289     int minN = -1;
3290     
3291     for( n = 0; n < 4; n++ )
3292     {
3293         if( haveCross[n] > 0 )
3294         {
3295             dist =  (epipole.x - cross[n].x)*(epipole.x - cross[n].x) +
3296                     (epipole.y - cross[n].y)*(epipole.y - cross[n].y);
3297
3298             if( dist < minDist )
3299             {
3300                 minDist = dist;
3301                 minN = n;
3302             }
3303
3304             if( dist > maxDist )
3305             {
3306                 maxDist = dist;
3307                 maxN = n;
3308             }
3309         }
3310     }
3311
3312     if( minN >= 0 && maxN >= 0 && (minN != maxN) )
3313     {
3314         *start = cross[minN];
3315         *end   = cross[maxN];
3316     }
3317     else
3318     {
3319         start->x = 0;
3320         start->y = 0;
3321         end->x = 0;
3322         end->y = 0;
3323     }
3324
3325     return;
3326 }
3327
3328
3329 /* Find line which cross frame by line(a,b,c) */
3330 void FindLineForEpiline(CvSize imageSize,float a,float b,float c,CvPoint2D32f *start,CvPoint2D32f *end)
3331 {
3332     CvPoint2D32f frameBeg;
3333     CvPoint2D32f frameEnd;
3334     CvPoint2D32f cross[4];
3335     int     haveCross[4];
3336     float   dist;
3337
3338     haveCross[0] = 0;
3339     haveCross[1] = 0;
3340     haveCross[2] = 0;
3341     haveCross[3] = 0;
3342
3343     frameBeg.x = 0;
3344     frameBeg.y = 0;
3345     frameEnd.x = (float)(imageSize.width);
3346     frameEnd.y = 0;
3347     haveCross[0] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[0]);
3348     
3349     frameBeg.x = (float)(imageSize.width);
3350     frameBeg.y = 0;
3351     frameEnd.x = (float)(imageSize.width);
3352     frameEnd.y = (float)(imageSize.height);
3353     haveCross[1] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[1]);
3354
3355     frameBeg.x = (float)(imageSize.width);
3356     frameBeg.y = (float)(imageSize.height);
3357     frameEnd.x = 0;
3358     frameEnd.y = (float)(imageSize.height);
3359     haveCross[2] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[2]);
3360     
3361     frameBeg.x = 0;
3362     frameBeg.y = (float)(imageSize.height);
3363     frameEnd.x = 0;
3364     frameEnd.y = 0;
3365     haveCross[3] = icvGetCrossLineDirect(frameBeg,frameEnd,a,b,c,&cross[3]);
3366
3367     int n;
3368     float minDist = (float)(INT_MAX);
3369     float maxDist = (float)(INT_MIN);
3370
3371     int maxN = -1;
3372     int minN = -1;
3373
3374     double midPointX = imageSize.width  / 2.0;
3375     double midPointY = imageSize.height / 2.0;
3376
3377     for( n = 0; n < 4; n++ )
3378     {
3379         if( haveCross[n] > 0 )
3380         {
3381             dist =  (float)((midPointX - cross[n].x)*(midPointX - cross[n].x) +
3382                             (midPointY - cross[n].y)*(midPointY - cross[n].y));
3383
3384             if( dist < minDist )
3385             {
3386                 minDist = dist;
3387                 minN = n;
3388             }
3389
3390             if( dist > maxDist )
3391             {
3392                 maxDist = dist;
3393                 maxN = n;
3394             }
3395         }
3396     }
3397
3398     if( minN >= 0 && maxN >= 0 && (minN != maxN) )
3399     {
3400         *start = cross[minN];
3401         *end   = cross[maxN];
3402     }
3403     else
3404     {
3405         start->x = 0;
3406         start->y = 0;
3407         end->x = 0;
3408         end->y = 0;
3409     }
3410
3411     return;
3412     
3413 }
3414
3415 /* Cross lines */
3416 int GetCrossLines(CvPoint2D32f p1_start,CvPoint2D32f p1_end,CvPoint2D32f p2_start,CvPoint2D32f p2_end,CvPoint2D32f *cross)
3417 {
3418     double ex1,ey1,ex2,ey2;
3419     double px1,py1,px2,py2;
3420     double del;
3421     double delA,delB,delX,delY;
3422     double alpha,betta;
3423
3424     ex1 = p1_start.x;
3425     ey1 = p1_start.y;
3426     ex2 = p1_end.x;
3427     ey2 = p1_end.y;
3428
3429     px1 = p2_start.x;
3430     py1 = p2_start.y;
3431     px2 = p2_end.x;
3432     py2 = p2_end.y;
3433
3434     del = (ex1-ex2)*(py2-py1)+(ey2-ey1)*(px2-px1);
3435     if( del == 0)
3436     {
3437         return -1;
3438     }
3439
3440     delA =  (px1-ex1)*(py1-py2) + (ey1-py1)*(px1-px2);
3441     delB =  (ex1-px1)*(ey1-ey2) + (py1-ey1)*(ex1-ex2);
3442
3443     alpha =  delA / del;
3444     betta = -delB / del;
3445
3446     if( alpha < 0 || alpha > 1.0 || betta < 0 || betta > 1.0)
3447     {
3448         return -1;
3449     }
3450
3451     delX =  (ex1-ex2)*(py1*(px1-px2)-px1*(py1-py2))+
3452             (px1-px2)*(ex1*(ey1-ey2)-ey1*(ex1-ex2));
3453
3454     delY =  (ey1-ey2)*(px1*(py1-py2)-py1*(px1-px2))+
3455             (py1-py2)*(ey1*(ex1-ex2)-ex1*(ey1-ey2));
3456
3457     cross->x = (float)( delX / del);
3458     cross->y = (float)(-delY / del);
3459     return 1;
3460 }
3461
3462
3463 int icvGetCrossPieceVector(CvPoint2D32f p1_start,CvPoint2D32f p1_end,CvPoint2D32f v2_start,CvPoint2D32f v2_end,CvPoint2D32f *cross)
3464 {
3465     double ex1,ey1,ex2,ey2;
3466     double px1,py1,px2,py2;
3467     double del;
3468     double delA,delB,delX,delY;
3469     double alpha,betta;
3470
3471     ex1 = p1_start.x;
3472     ey1 = p1_start.y;
3473     ex2 = p1_end.x;
3474     ey2 = p1_end.y;
3475
3476     px1 = v2_start.x;
3477     py1 = v2_start.y;
3478     px2 = v2_end.x;
3479     py2 = v2_end.y;
3480
3481     del = (ex1-ex2)*(py2-py1)+(ey2-ey1)*(px2-px1);
3482     if( del == 0)
3483     {
3484         return -1;
3485     }
3486
3487     delA =  (px1-ex1)*(py1-py2) + (ey1-py1)*(px1-px2);
3488     delB =  (ex1-px1)*(ey1-ey2) + (py1-ey1)*(ex1-ex2);
3489
3490     alpha =  delA / del;
3491     betta = -delB / del;
3492
3493     if( alpha < 0 || alpha > 1.0 )
3494     {
3495         return -1;
3496     }
3497
3498     delX =  (ex1-ex2)*(py1*(px1-px2)-px1*(py1-py2))+
3499             (px1-px2)*(ex1*(ey1-ey2)-ey1*(ex1-ex2));
3500
3501     delY =  (ey1-ey2)*(px1*(py1-py2)-py1*(px1-px2))+
3502             (py1-py2)*(ey1*(ex1-ex2)-ex1*(ey1-ey2));
3503
3504     cross->x = (float)( delX / del);
3505     cross->y = (float)(-delY / del);
3506     return 1;
3507 }
3508
3509
3510 int icvGetCrossLineDirect(CvPoint2D32f p1,CvPoint2D32f p2,float a,float b,float c,CvPoint2D32f* cross)
3511 {
3512     double del;
3513     double delX,delY,delA;
3514
3515     double px1,px2,py1,py2;
3516     double X,Y,alpha;
3517
3518     px1 = p1.x;
3519     py1 = p1.y;
3520
3521     px2 = p2.x;
3522     py2 = p2.y;
3523
3524     del = a * (px2 - px1) + b * (py2-py1);
3525     if( del == 0 )
3526     {
3527         return -1;
3528     }
3529
3530     delA = - c - a*px1 - b*py1;
3531     alpha = delA / del;
3532
3533     if( alpha < 0 || alpha > 1.0 )
3534     {
3535         return -1;/* no cross */
3536     }
3537
3538     delX = b * (py1*(px1-px2) - px1*(py1-py2)) + c * (px1-px2);
3539     delY = a * (px1*(py1-py2) - py1*(px1-px2)) + c * (py1-py2);
3540
3541     X = delX / del;
3542     Y = delY / del;
3543
3544     cross->x = (float)X;
3545     cross->y = (float)Y;
3546     
3547     return 1;
3548 }
3549
3550 int cvComputeEpipoles( CvMatr32f camMatr1,  CvMatr32f camMatr2,
3551                             CvMatr32f rotMatr1,  CvMatr32f rotMatr2,
3552                             CvVect32f transVect1,CvVect32f transVect2,
3553                             CvVect32f epipole1,
3554                             CvVect32f epipole2)
3555 {
3556
3557     /* Copy matrix */
3558
3559     CvMat ccamMatr1 = cvMat(3,3,CV_MAT32F,camMatr1);
3560     CvMat ccamMatr2 = cvMat(3,3,CV_MAT32F,camMatr2);
3561     CvMat crotMatr1 = cvMat(3,3,CV_MAT32F,rotMatr1);
3562     CvMat crotMatr2 = cvMat(3,3,CV_MAT32F,rotMatr2);
3563     CvMat ctransVect1 = cvMat(3,1,CV_MAT32F,transVect1);
3564     CvMat ctransVect2 = cvMat(3,1,CV_MAT32F,transVect2);
3565     CvMat cepipole1 = cvMat(3,1,CV_MAT32F,epipole1);
3566     CvMat cepipole2 = cvMat(3,1,CV_MAT32F,epipole2);
3567
3568
3569     CvMat cmatrP1   = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&cmatrP1);
3570     CvMat cmatrP2   = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&cmatrP2);
3571     CvMat cvectp1   = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&cvectp1);
3572     CvMat cvectp2   = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&cvectp2);
3573     CvMat ctmpF1    = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&ctmpF1);
3574     CvMat ctmpM1    = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&ctmpM1);
3575     CvMat ctmpM2    = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&ctmpM2);
3576     CvMat cinvP1    = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&cinvP1);
3577     CvMat cinvP2    = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&cinvP2);
3578     CvMat ctmpMatr  = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&ctmpMatr);
3579     CvMat ctmpVect1 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&ctmpVect1);
3580     CvMat ctmpVect2 = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&ctmpVect2);
3581     CvMat cmatrF1   = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&cmatrF1);
3582     CvMat ctmpF     = cvMat(3,3,CV_MAT32F,0); cvmAlloc(&ctmpF);
3583     CvMat ctmpE1    = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&ctmpE1);
3584     CvMat ctmpE2    = cvMat(3,1,CV_MAT32F,0); cvmAlloc(&ctmpE2);
3585
3586     /* Compute first */
3587     cvmMul( &ccamMatr1, &crotMatr1, &cmatrP1);
3588     cvmInvert( &cmatrP1,&cinvP1 );
3589     cvmMul( &ccamMatr1, &ctransVect1, &cvectp1 );
3590     
3591     /* Compute second */
3592     cvmMul( &ccamMatr2, &crotMatr2, &cmatrP2 );
3593     cvmInvert( &cmatrP2,&cinvP2 );
3594     cvmMul( &ccamMatr2, &ctransVect2, &cvectp2 );
3595
3596     cvmMul( &cmatrP1, &cinvP2, &ctmpM1);
3597     cvmMul( &ctmpM1, &cvectp2, &ctmpVect1);
3598     cvmSub( &cvectp1,&ctmpVect1,&ctmpE1);
3599
3600     cvmMul( &cmatrP2, &cinvP1, &ctmpM2);
3601     cvmMul( &ctmpM2, &cvectp1, &ctmpVect2);
3602     cvmSub( &cvectp2, &ctmpVect2, &ctmpE2);
3603
3604
3605     /* Need scale */
3606
3607     cvmScale(&ctmpE1,&cepipole1,1.0);
3608     cvmScale(&ctmpE2,&cepipole2,1.0);
3609
3610     cvmFree(&cmatrP1);
3611     cvmFree(&cmatrP1);
3612     cvmFree(&cvectp1);
3613     cvmFree(&cvectp2);
3614     cvmFree(&ctmpF1);
3615     cvmFree(&ctmpM1);
3616     cvmFree(&ctmpM2);
3617     cvmFree(&cinvP1);
3618     cvmFree(&cinvP2);
3619     cvmFree(&ctmpMatr);
3620     cvmFree(&ctmpVect1);
3621     cvmFree(&ctmpVect2);
3622     cvmFree(&cmatrF1);
3623     cvmFree(&ctmpF);
3624     cvmFree(&ctmpE1);
3625     cvmFree(&ctmpE2);
3626
3627     return CV_NO_ERR;
3628 }/* cvComputeEpipoles */
3629
3630
3631 /* Compute epipoles for fundamental matrix */
3632 int cvComputeEpipolesFromFundMatrix(CvMatr32f fundMatr,
3633                                          CvPoint3D32f* epipole1,
3634                                          CvPoint3D32f* epipole2)
3635 {
3636     /* Decompose fundamental matrix using SVD ( A = U W V') */
3637     CvMat fundMatrC = cvMat(3,3,CV_MAT32F,fundMatr);
3638
3639     CvMat* matrW = cvCreateMat(3,3,CV_MAT32F);
3640     CvMat* matrU = cvCreateMat(3,3,CV_MAT32F);
3641     CvMat* matrV = cvCreateMat(3,3,CV_MAT32F);
3642
3643     /* From svd we need just last vector of U and V or last row from U' and V' */
3644     /* We get transposed matrixes U and V */
3645     cvSVD(&fundMatrC,matrW,matrU,matrV,CV_SVD_V_T|CV_SVD_U_T);
3646
3647     /* Get last row from U' and compute epipole1 */
3648     epipole1->x = matrU->data.fl[6];
3649     epipole1->y = matrU->data.fl[7];
3650     epipole1->z = matrU->data.fl[8];
3651     
3652     /* Get last row from V' and compute epipole2 */
3653     epipole2->x = matrV->data.fl[6];
3654     epipole2->y = matrV->data.fl[7];
3655     epipole2->z = matrV->data.fl[8];
3656
3657     cvReleaseMat(&matrW);
3658     cvReleaseMat(&matrU);
3659     cvReleaseMat(&matrV);    
3660     return CV_OK;
3661 }
3662
3663 int cvConvertEssential2Fundamental( CvMatr32f essMatr,
3664                                          CvMatr32f fundMatr,
3665                                          CvMatr32f cameraMatr1,
3666                                          CvMatr32f cameraMatr2)
3667 {/* Fund = inv(CM1') * Ess * inv(CM2) */
3668
3669     CvMat essMatrC     = cvMat(3,3,CV_MAT32F,essMatr);
3670     CvMat fundMatrC    = cvMat(3,3,CV_MAT32F,fundMatr);
3671     CvMat cameraMatr1C = cvMat(3,3,CV_MAT32F,cameraMatr1);
3672     CvMat cameraMatr2C = cvMat(3,3,CV_MAT32F,cameraMatr2);
3673
3674     CvMat* invCM2  = cvCreateMat(3,3,CV_MAT32F);
3675     CvMat* tmpMatr = cvCreateMat(3,3,CV_MAT32F);
3676     CvMat* invCM1T = cvCreateMat(3,3,CV_MAT32F);
3677
3678     cvTranspose(&cameraMatr1C,tmpMatr);
3679     cvInvert(tmpMatr,invCM1T);       
3680     cvmMul(invCM1T,&essMatrC,tmpMatr);
3681     cvInvert(&cameraMatr2C,invCM2);
3682     cvmMul(tmpMatr,invCM2,&fundMatrC);
3683
3684     /* Scale fundamental matrix */
3685     double scale;
3686     scale = 1.0/fundMatrC.data.fl[8];
3687     cvConvertScale(&fundMatrC,&fundMatrC,scale);
3688
3689     cvReleaseMat(&invCM2);
3690     cvReleaseMat(&tmpMatr);
3691     cvReleaseMat(&invCM1T);
3692     
3693     return CV_OK;
3694 }
3695
3696 /* Compute essential matrix */
3697
3698 int cvComputeEssentialMatrix(  CvMatr32f rotMatr,
3699                                     CvMatr32f transVect,
3700                                     CvMatr32f essMatr)
3701 {
3702     float transMatr[9];
3703
3704     /* Make antisymmetric matrix from transpose vector */
3705     transMatr[0] =   0;
3706     transMatr[1] = - transVect[2];
3707     transMatr[2] =   transVect[1];
3708     
3709     transMatr[3] =   transVect[2];
3710     transMatr[4] =   0;
3711     transMatr[5] = - transVect[0];
3712     
3713     transMatr[6] = - transVect[1];
3714     transMatr[7] =   transVect[0];
3715     transMatr[8] =   0;
3716
3717     icvMulMatrix_32f(transMatr,3,3,rotMatr,3,3,essMatr);
3718
3719     return CV_OK;
3720 }
3721
3722