Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                        Intel License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
     14 // Third party copyrights are property of their respective owners.
     15 //
     16 // Redistribution and use in source and binary forms, with or without modification,
     17 // are permitted provided that the following conditions are met:
     18 //
     19 //   * Redistribution's of source code must retain the above copyright notice,
     20 //     this list of conditions and the following disclaimer.
     21 //
     22 //   * Redistribution's in binary form must reproduce the above copyright notice,
     23 //     this list of conditions and the following disclaimer in the documentation
     24 //     and/or other materials provided with the distribution.
     25 //
     26 //   * The name of Intel Corporation may not be used to endorse or promote products
     27 //     derived from this software without specific prior written permission.
     28 //
     29 // This software is provided by the copyright holders and contributors "as is" and
     30 // any express or implied warranties, including, but not limited to, the implied
     31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     32 // In no event shall the Intel Corporation or contributors be liable for any direct,
     33 // indirect, incidental, special, exemplary, or consequential damages
     34 // (including, but not limited to, procurement of substitute goods or services;
     35 // loss of use, data, or profits; or business interruption) however caused
     36 // and on any theory of liability, whether in contract, strict liability,
     37 // or tort (including negligence or otherwise) arising in any way out of
     38 // the use of this software, even if advised of the possibility of such damage.
     39 //
     40 //M*/
     41 
     42 #include "_cvaux.h"
     43 
     44 #include "cvtypes.h"
     45 #include <float.h>
     46 #include <limits.h>
     47 #include "cv.h"
     48 
     49 /* Valery Mosyagin */
     50 
     51 typedef void (*pointer_LMJac)( const CvMat* src, CvMat* dst );
     52 typedef void (*pointer_LMFunc)( const CvMat* src, CvMat* dst );
     53 
     54 void cvLevenbergMarquardtOptimization(pointer_LMJac JacobianFunction,
     55                                     pointer_LMFunc function,
     56                                     /*pointer_Err error_function,*/
     57                                     CvMat *X0,CvMat *observRes,CvMat *resultX,
     58                                     int maxIter,double epsilon);
     59 
     60 void icvReconstructPointsFor3View( CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
     61                                 CvMat* projPoints1,CvMat* projPoints2,CvMat* projPoints3,
     62                                 CvMat* points4D);
     63 
     64 
     65 /* Jacobian computation for trifocal case */
     66 void icvJacobianFunction_ProjTrifocal(const CvMat *vectX,CvMat *Jacobian)
     67 {
     68     CV_FUNCNAME( "icvJacobianFunction_ProjTrifocal" );
     69     __BEGIN__;
     70 
     71     /* Test data for errors */
     72     if( vectX == 0 || Jacobian == 0 )
     73     {
     74         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
     75     }
     76 
     77     if( !CV_IS_MAT(vectX) || !CV_IS_MAT(Jacobian) )
     78     {
     79         CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
     80     }
     81 
     82     int numPoints;
     83     numPoints = (vectX->rows - 36)/4;
     84 
     85     if( numPoints < 1 )//!!! Need to correct this minimal number of points
     86     {
     87         CV_ERROR( CV_StsUnmatchedSizes, "number of points must be more than 0" );
     88     }
     89 
     90     if( Jacobian->rows == numPoints*6 || Jacobian->cols != 36+numPoints*4 )
     91     {
     92         CV_ERROR( CV_StsUnmatchedSizes, "Size of Jacobian is not correct it must be 6*numPoints x (36+numPoints*4)" );
     93     }
     94 
     95     /* Computed Jacobian in a given point */
     96     /* This is for function with 3 projection matrices */
     97     /* vector X consists of projection matrices and points3D */
     98     /* each 3D points has X,Y,Z,W */
     99     /* each projection matrices has 3x4 coeffs */
    100     /* For N points 4D we have Jacobian 2N x (12*3+4N) */
    101 
    102     /* Will store derivates as  */
    103     /* Fill Jacobian matrix */
    104     int currProjPoint;
    105     int currMatr;
    106 
    107     cvZero(Jacobian);
    108     for( currMatr = 0; currMatr < 3; currMatr++ )
    109     {
    110         double p[12];
    111         for( int i=0;i<12;i++ )
    112         {
    113             p[i] = cvmGet(vectX,currMatr*12+i,0);
    114         }
    115 
    116         int currVal = 36;
    117         for( currProjPoint = 0; currProjPoint < numPoints; currProjPoint++ )
    118         {
    119             /* Compute */
    120             double X[4];
    121             X[0] = cvmGet(vectX,currVal++,0);
    122             X[1] = cvmGet(vectX,currVal++,0);
    123             X[2] = cvmGet(vectX,currVal++,0);
    124             X[3] = cvmGet(vectX,currVal++,0);
    125 
    126             double piX[3];
    127             piX[0] = X[0]*p[0] + X[1]*p[1] + X[2]*p[2]  + X[3]*p[3];
    128             piX[1] = X[0]*p[4] + X[1]*p[5] + X[2]*p[6]  + X[3]*p[7];
    129             piX[2] = X[0]*p[8] + X[1]*p[9] + X[2]*p[10] + X[3]*p[11];
    130 
    131             int i,j;
    132             /* fill derivate by point */
    133 
    134             double tmp3 = 1/(piX[2]*piX[2]);
    135 
    136             double tmp1 = -piX[0]*tmp3;
    137             double tmp2 = -piX[1]*tmp3;
    138             for( j = 0; j < 2; j++ )//for x and y
    139             {
    140                 for( i = 0; i < 4; i++ )// for X,Y,Z,W
    141                 {
    142                     cvmSet( Jacobian,
    143                             currMatr*numPoints*2+currProjPoint*2+j, 36+currProjPoint*4+i,
    144                             (p[j*4+i]*piX[2]-p[8+i]*piX[j]) * tmp3  );
    145                 }
    146             }
    147                 /* fill derivate by projection matrix */
    148             for( i = 0; i < 4; i++ )
    149             {
    150                 /* derivate for x */
    151                 cvmSet(Jacobian,currMatr*numPoints*2+currProjPoint*2,currMatr*12+i,X[i]/piX[2]);//x' p1i
    152                 cvmSet(Jacobian,currMatr*numPoints*2+currProjPoint*2,currMatr*12+8+i,X[i]*tmp1);//x' p3i
    153 
    154                 /* derivate for y */
    155                 cvmSet(Jacobian,currMatr*numPoints*2+currProjPoint*2+1,currMatr*12+4+i,X[i]/piX[2]);//y' p2i
    156                 cvmSet(Jacobian,currMatr*numPoints*2+currProjPoint*2+1,currMatr*12+8+i,X[i]*tmp2);//y' p3i
    157             }
    158 
    159         }
    160     }
    161 
    162     __END__;
    163     return;
    164 }
    165 
    166 void icvFunc_ProjTrifocal(const CvMat *vectX, CvMat *resFunc)
    167 {
    168     /* Computes function in a given point */
    169     /* Computers project points using 3 projection matrices and points 3D */
    170 
    171     /* vector X consists of projection matrices and points3D */
    172     /* each projection matrices has 3x4 coeffs */
    173     /* each 3D points has X,Y,Z,W(?) */
    174 
    175     /* result of function is projection of N 3D points using 3 projection matrices */
    176     /* projected points store as (projection by matrix P1),(projection by matrix P2),(projection by matrix P3) */
    177     /* each projection is x1,y1,x2,y2,x3,y3,x4,y4 */
    178 
    179     /* Compute projection of points */
    180 
    181     /* Fill projection matrices */
    182 
    183     CV_FUNCNAME( "icvFunc_ProjTrifocal" );
    184     __BEGIN__;
    185 
    186     /* Test data for errors */
    187     if( vectX == 0 || resFunc == 0 )
    188     {
    189         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
    190     }
    191 
    192     if( !CV_IS_MAT(vectX) || !CV_IS_MAT(resFunc) )
    193     {
    194         CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
    195     }
    196 
    197     int numPoints;
    198     numPoints = (vectX->rows - 36)/4;
    199 
    200     if( numPoints < 1 )//!!! Need to correct this minimal number of points
    201     {
    202         CV_ERROR( CV_StsUnmatchedSizes, "number of points must be more than 0" );
    203     }
    204 
    205     if( resFunc->rows == 2*numPoints*3 || resFunc->cols != 1 )
    206     {
    207         CV_ERROR( CV_StsUnmatchedSizes, "Size of resFunc is not correct it must be 2*numPoints*3 x 1");
    208     }
    209 
    210 
    211     CvMat projMatrs[3];
    212     double projMatrs_dat[36];
    213     projMatrs[0] = cvMat(3,4,CV_64F,projMatrs_dat);
    214     projMatrs[1] = cvMat(3,4,CV_64F,projMatrs_dat+12);
    215     projMatrs[2] = cvMat(3,4,CV_64F,projMatrs_dat+24);
    216 
    217     CvMat point3D;
    218     double point3D_dat[3];
    219     point3D = cvMat(3,1,CV_64F,point3D_dat);
    220 
    221     int currMatr;
    222     int currV;
    223     int i,j;
    224 
    225     currV=0;
    226     for( currMatr = 0; currMatr < 3; currMatr++ )
    227     {
    228         for( i = 0; i < 3; i++ )
    229         {
    230             for( j = 0;j < 4; j++ )
    231             {
    232                 double val = cvmGet(vectX,currV,0);
    233                 cvmSet(&projMatrs[currMatr],i,j,val);
    234                 currV++;
    235             }
    236         }
    237     }
    238 
    239     /* Project points */
    240     int currPoint;
    241     CvMat point4D;
    242     double point4D_dat[4];
    243     point4D = cvMat(4,1,CV_64F,point4D_dat);
    244     for( currPoint = 0; currPoint < numPoints; currPoint++ )
    245     {
    246         /* get curr point */
    247         point4D_dat[0] = cvmGet(vectX,currV++,0);
    248         point4D_dat[1] = cvmGet(vectX,currV++,0);
    249         point4D_dat[2] = cvmGet(vectX,currV++,0);
    250         point4D_dat[3] = cvmGet(vectX,currV++,0);
    251 
    252         for( currMatr = 0; currMatr < 3; currMatr++ )
    253         {
    254             /* Compute projection for current point */
    255             cvmMul(&projMatrs[currMatr],&point4D,&point3D);
    256             double z = point3D_dat[2];
    257             cvmSet(resFunc,currMatr*numPoints*2 + currPoint*2,  0,point3D_dat[0]/z);
    258             cvmSet(resFunc,currMatr*numPoints*2 + currPoint*2+1,0,point3D_dat[1]/z);
    259         }
    260     }
    261 
    262     __END__;
    263     return;
    264 }
    265 
    266 
    267 /*----------------------------------------------------------------------------------------*/
    268 
    269 void icvOptimizeProjectionTrifocal(CvMat **projMatrs,CvMat **projPoints,
    270                                 CvMat **resultProjMatrs, CvMat *resultPoints4D)
    271 {
    272 
    273     CvMat *optimX    = 0;
    274     CvMat *points4D  = 0;
    275     CvMat *vectorX0  = 0;
    276     CvMat *observRes = 0;
    277     //CvMat *error     = 0;
    278 
    279     CV_FUNCNAME( "icvOptimizeProjectionTrifocal" );
    280     __BEGIN__;
    281 
    282     /* Test data for errors */
    283     if( projMatrs == 0 || projPoints == 0 || resultProjMatrs == 0 || resultPoints4D == 0)
    284     {
    285         CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
    286     }
    287 
    288     if( !CV_IS_MAT(resultPoints4D) )
    289     {
    290         CV_ERROR( CV_StsUnsupportedFormat, "resultPoints4D must be a matrix" );
    291     }
    292 
    293     int numPoints;
    294     numPoints = resultPoints4D->cols;
    295     if( numPoints < 1 )
    296     {
    297         CV_ERROR( CV_StsOutOfRange, "Number points of resultPoints4D must be more than 0" );
    298     }
    299 
    300     if( resultPoints4D->rows != 4 )
    301     {
    302         CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of points4D must be 4" );
    303     }
    304 
    305     int i;
    306     for( i = 0; i < 3; i++ )
    307     {
    308         if( projMatrs[i] == 0 )
    309         {
    310             CV_ERROR( CV_StsNullPtr, "Some of projMatrs is a NULL pointer" );
    311         }
    312 
    313         if( projPoints[i] == 0 )
    314         {
    315             CV_ERROR( CV_StsNullPtr, "Some of projPoints is a NULL pointer" );
    316         }
    317 
    318         if( resultProjMatrs[i] == 0 )
    319         {
    320             CV_ERROR( CV_StsNullPtr, "Some of resultProjMatrs is a NULL pointer" );
    321         }
    322 
    323         /* ----------- test for matrix ------------- */
    324         if( !CV_IS_MAT(projMatrs[i]) )
    325         {
    326             CV_ERROR( CV_StsUnsupportedFormat, "Each of projMatrs must be a matrix" );
    327         }
    328 
    329         if( !CV_IS_MAT(projPoints[i]) )
    330         {
    331             CV_ERROR( CV_StsUnsupportedFormat, "Each of projPoints must be a matrix" );
    332         }
    333 
    334         if( !CV_IS_MAT(resultProjMatrs[i]) )
    335         {
    336             CV_ERROR( CV_StsUnsupportedFormat, "Each of resultProjMatrs must be a matrix" );
    337         }
    338 
    339         /* ------------- Test sizes --------------- */
    340         if( projMatrs[i]->rows != 3 || projMatrs[i]->cols != 4 )
    341         {
    342             CV_ERROR( CV_StsUnmatchedSizes, "Size of projMatr must be 3x4" );
    343         }
    344 
    345         if( projPoints[i]->rows != 2 || projPoints[i]->cols != numPoints )
    346         {
    347             CV_ERROR( CV_StsUnmatchedSizes, "Size of resultProjMatrs must be 3x4" );
    348         }
    349 
    350         if( resultProjMatrs[i]->rows != 3 || resultProjMatrs[i]->cols != 4 )
    351         {
    352             CV_ERROR( CV_StsUnmatchedSizes, "Size of resultProjMatrs must be 3x4" );
    353         }
    354     }
    355 
    356 
    357     /* Allocate memory for points 4D */
    358     CV_CALL( points4D  = cvCreateMat(4,numPoints,CV_64F) );
    359     CV_CALL( vectorX0  = cvCreateMat(36 + numPoints*4,1,CV_64F) );
    360     CV_CALL( observRes = cvCreateMat(2*numPoints*3,1,CV_64F) );
    361     CV_CALL( optimX    = cvCreateMat(36+numPoints*4,1,CV_64F) );
    362     //CV_CALL( error     = cvCreateMat(numPoints*2*3,1,CV_64F) );
    363 
    364 
    365     /* Reconstruct points 4D using projected points and projection matrices */
    366     icvReconstructPointsFor3View( projMatrs[0],projMatrs[1],projMatrs[2],
    367                                   projPoints[0],projPoints[1],projPoints[2],
    368                                   points4D);
    369 
    370 
    371 
    372     /* Fill observed points on images */
    373     /* result of function is projection of N 3D points using 3 projection matrices */
    374     /* projected points store as (projection by matrix P1),(projection by matrix P2),(projection by matrix P3) */
    375     /* each projection is x1,y1,x2,y2,x3,y3,x4,y4 */
    376     int currMatr;
    377     for( currMatr = 0; currMatr < 3; currMatr++ )
    378     {
    379         for( i = 0; i < numPoints; i++ )
    380         {
    381             cvmSet(observRes,currMatr*numPoints*2+i*2  ,0,cvmGet(projPoints[currMatr],0,i) );/* x */
    382             cvmSet(observRes,currMatr*numPoints*2+i*2+1,0,cvmGet(projPoints[currMatr],1,i) );/* y */
    383         }
    384     }
    385 
    386     /* Fill with projection matrices */
    387     for( currMatr = 0; currMatr < 3; currMatr++ )
    388     {
    389         int i;
    390         for( i = 0; i < 12; i++ )
    391         {
    392             cvmSet(vectorX0,currMatr*12+i,0,cvmGet(projMatrs[currMatr],i/4,i%4));
    393         }
    394     }
    395 
    396     /* Fill with 4D points */
    397 
    398     int currPoint;
    399     for( currPoint = 0; currPoint < numPoints; currPoint++ )
    400     {
    401         cvmSet(vectorX0,36 + currPoint*4 + 0,0,cvmGet(points4D,0,currPoint));
    402         cvmSet(vectorX0,36 + currPoint*4 + 1,0,cvmGet(points4D,1,currPoint));
    403         cvmSet(vectorX0,36 + currPoint*4 + 2,0,cvmGet(points4D,2,currPoint));
    404         cvmSet(vectorX0,36 + currPoint*4 + 3,0,cvmGet(points4D,3,currPoint));
    405     }
    406 
    407 
    408     /* Allocate memory for result */
    409     cvLevenbergMarquardtOptimization( icvJacobianFunction_ProjTrifocal, icvFunc_ProjTrifocal,
    410                                       vectorX0,observRes,optimX,100,1e-6);
    411 
    412     /* Copy results */
    413     for( currMatr = 0; currMatr < 3; currMatr++ )
    414     {
    415         /* Copy projection matrices */
    416         for(int i=0;i<12;i++)
    417         {
    418             cvmSet(resultProjMatrs[currMatr],i/4,i%4,cvmGet(optimX,currMatr*12+i,0));
    419         }
    420     }
    421 
    422     /* Copy 4D points */
    423     for( currPoint = 0; currPoint < numPoints; currPoint++ )
    424     {
    425         cvmSet(resultPoints4D,0,currPoint,cvmGet(optimX,36 + currPoint*4,0));
    426         cvmSet(resultPoints4D,1,currPoint,cvmGet(optimX,36 + currPoint*4+1,0));
    427         cvmSet(resultPoints4D,2,currPoint,cvmGet(optimX,36 + currPoint*4+2,0));
    428         cvmSet(resultPoints4D,3,currPoint,cvmGet(optimX,36 + currPoint*4+3,0));
    429     }
    430 
    431     __END__;
    432 
    433     /* Free allocated memory */
    434     cvReleaseMat(&optimX);
    435     cvReleaseMat(&points4D);
    436     cvReleaseMat(&vectorX0);
    437     cvReleaseMat(&observRes);
    438 
    439     return;
    440 
    441 
    442 }
    443 
    444 /*------------------------------------------------------------------------------*/
    445 /* Create good points using status information */
    446 void icvCreateGoodPoints(CvMat *points,CvMat **goodPoints, CvMat *status)
    447 {
    448     *goodPoints = 0;
    449 
    450     CV_FUNCNAME( "icvCreateGoodPoints" );
    451     __BEGIN__;
    452 
    453     int numPoints;
    454     numPoints = points->cols;
    455 
    456     if( numPoints < 1 )
    457     {
    458         CV_ERROR( CV_StsOutOfRange, "Number of points must be more than 0" );
    459     }
    460 
    461     int numCoord;
    462     numCoord = points->rows;
    463     if( numCoord < 1 )
    464     {
    465         CV_ERROR( CV_StsOutOfRange, "Number of points coordinates must be more than 0" );
    466     }
    467 
    468     /* Define number of good points */
    469     int goodNum;
    470     int i,j;
    471 
    472     goodNum = 0;
    473     for( i = 0; i < numPoints; i++)
    474     {
    475         if( cvmGet(status,0,i) > 0 )
    476             goodNum++;
    477     }
    478 
    479     /* Allocate memory for good points */
    480     CV_CALL( *goodPoints = cvCreateMat(numCoord,goodNum,CV_64F) );
    481 
    482     for( i = 0; i < numCoord; i++ )
    483     {
    484         int currPoint = 0;
    485         for( j = 0; j < numPoints; j++)
    486         {
    487             if( cvmGet(status,0,j) > 0 )
    488             {
    489                 cvmSet(*goodPoints,i,currPoint,cvmGet(points,i,j));
    490                 currPoint++;
    491             }
    492         }
    493     }
    494     __END__;
    495     return;
    496 }
    497 
    498