/*
eigen_verify

Verify properties of the eigen vectors.

The eigenbasis should be ortonormal: R'*R - I == 0
The basis should be decomposed such that: MR - RD == 0
returns true if tests fail.
*/
int eigen_verify(Matrix M, Matrix lambda, Matrix R) {
    Matrix RtR = transposeMultiplyMatrixL(R, R);
    Matrix identity = makeIdentityMatrix(R->col_dim);

    Matrix MR = multiplyMatrix(M, R);
    Matrix D = makeIdentityMatrix(lambda->row_dim);
    Matrix RD;
    Matrix test;
    int i, j;
    int failed = 0;
    const double tol = 1.0e-7;

    for (i = 0; i < lambda->row_dim; i++) {
        ME(D, i, i) = ME(lambda, i, 0);
    }
    RD = multiplyMatrix(R, D);
    freeMatrix(D);

    DEBUG(2, "Checking orthogonality of eigenvectors");
    test = subtractMatrix(RtR, identity);
    freeMatrix(RtR);
    freeMatrix(identity);

    for (i = 0; i < test->row_dim; i++) {
        for (j = 0; j < test->col_dim; j++) {
            if (!EQUAL_ZERO(ME(test, i, j), tol)) {
                failed = 1;
                MESSAGE("Eigenvectors are not orthogonal to within tolerance.");
                DEBUG_DOUBLE(1, "Matrix Element", ME(test, i, j));
                DEBUG_DOUBLE(1, "Tolerance", tol);
                exit(1);
            }
        }
    }
    freeMatrix(test);

    DEBUG(2, "Checking reconstruction property of eigensystem");
    test = subtractMatrix(MR, RD);
    freeMatrix(MR);
    freeMatrix(RD);

    for (i = 0; i < test->row_dim; i++) {
        for (j = 0; j < test->col_dim; j++) {
            if (!EQUAL_ZERO(ME(test, i, j), tol)) {
                failed = 1;
                MESSAGE("Covariance matrix is not reconstructable to within tolerance.");
                DEBUG_DOUBLE(1, "Matrix Element", ME(test, i, j));
                DEBUG_DOUBLE(1, "Tolerance", tol);
                exit(1);
            }
        }
    }
    freeMatrix(test);

    return failed;
}
Matrix reflectMatrix(int bool_x, int bool_y){
    Matrix transform = makeIdentityMatrix(3);

    if(bool_x) ME(transform,0,0) = -1;
    if(bool_y) ME(transform,1,1) = -1;
    return transform;
}
/* Return a scale Matrix */
Matrix scaleMatrix(double s){
    Matrix transform = makeIdentityMatrix(3);
    ME(transform,0,0) = s;
    ME(transform,1,1) = s;

    return transform;
}
void fisherVerify(Matrix fisherBasis, Matrix fisherValues, Matrix Sw, Matrix Sb) {
    Matrix SbW = multiplyMatrix(Sb, fisherBasis);
    Matrix SwW = multiplyMatrix(Sw, fisherBasis);
    Matrix D = makeIdentityMatrix(fisherBasis->row_dim);
    Matrix DSwW;
    Matrix zeroMat;
    int i, j;


    MESSAGE("Verifying Fisher Basis.");

    for (i = 0; i < D->row_dim; i++) {
        ME(D, i, i) = ME(fisherValues, i, 0);
    }

    DSwW = multiplyMatrix(D, SwW);
    zeroMat = subtractMatrix(SbW, DSwW);

    for (i = 0; i < zeroMat->row_dim; i++) {
        for (j = 0; j < zeroMat->col_dim; j++) {
            if (!EQUAL_ZERO(ME(zeroMat, i, j), 0.000001)) {
                DEBUG( -1, "Fisher validation failed.");
                printf("Element: (%d,%d) value = %f", i, j, ME(zeroMat, i, j));
                exit(1);
            }
        }
    }
}
/* Return a translation matrix */
Matrix translateMatrix(double dx, double dy){
    Matrix transform = makeIdentityMatrix(3);

    ME(transform,0,2) = dx;
    ME(transform,1,2) = dy;

    return transform;
}
/* Return a rotation matrix */
Matrix rotateMatrix(double theta){
    Matrix transform = makeIdentityMatrix(3);

    ME(transform,0,0) = cos(theta);
    ME(transform,1,1) = cos(theta);
    ME(transform,0,1) = -sin(theta);
    ME(transform,1,0) = sin(theta);

    return transform;
}
/**
Verify properties of the eigen basis used for pca.

The eigenbasis should be ortonormal: U'*U - I == 0
The basis should be decomposed such that: X == U*D*V'

returns true if tests fail.
*/
int basis_verify(Matrix X, Matrix U) {
    Matrix UtX = transposeMultiplyMatrixL(U, X);
    Matrix UUtX = multiplyMatrix(U, UtX);
    Matrix UtU = transposeMultiplyMatrixL(U, U);
    Matrix identity = makeIdentityMatrix(U->col_dim);
    Matrix test;
    int i, j;
    int failed = 0;
    const double tol = 1.0e-7;

    freeMatrix(UtX);

    DEBUG(2, "Checking orthogonality of eigenbasis");
    test = subtractMatrix(UtU, identity);
    freeMatrix(UtU);
    freeMatrix(identity);

    for (i = 0; i < test->row_dim; i++) {
        for (j = 0; j < test->col_dim; j++) {
            if (!EQUAL_ZERO(ME(test, i, j), tol)) {
                failed = 1;
                MESSAGE("Eigenbasis is not orthogonal to within tolerance.");
                DEBUG_DOUBLE(1, "Matrix Element", ME(test, i, j));
                DEBUG_DOUBLE(1, "Tolerance", tol);
                exit(1);
            }
        }
    }
    freeMatrix(test);

    DEBUG(2, "Checking reconstruction property of the eigen decomposition");
    test = subtractMatrix(X, UUtX);
    freeMatrix(UUtX);

    for (i = 0; i < test->row_dim; i++) {
        for (j = 0; j < test->col_dim; j++) {
            if (!EQUAL_ZERO(ME(test, i, j), tol)) {
                failed = 1;
                MESSAGE("Data matrix is not reconstructable to within tolerance.");
                DEBUG_DOUBLE(1, "Matrix Element", ME(test, i, j));
                DEBUG_DOUBLE(1, "Tolarence", tol);
                exit(1);
            }
        }
    }
    freeMatrix(test);

    return failed;


}
Beispiel #8
0
   void
   MetricBundleOptimizerBase::poseDerivatives(int i, int j, Vector3d& XX,
                                              Matrix3x6d& d_dRT, Matrix3x3d& d_dX) const
   {
      XX = _cams[i].transformPointIntoCameraSpace(_Xs[j]);

      // See Frank Dellaerts bundle adjustment tutorial.
      // d(dR * R0 * X + t)/d omega = -[R0 * X]_x
      Matrix3x3d J;
      makeCrossProductMatrix(XX - _cams[i].getTranslation(), J);
      scaleMatrixIP(-1.0, J);

      // Now the transformation from world coords into camera space is xx = Rx + T
      // Hence the derivative of x wrt. T is just the identity matrix.
      makeIdentityMatrix(d_dRT);
      copyMatrixSlice(J, 0, 0, 3, 3, d_dRT, 0, 3);

      // The derivative of Rx+T wrt x is just R.
      copyMatrix(_cams[i].getRotation(), d_dX);
   } // end MetricBundleOptimizerBase::poseDerivatives()
void convertImages(Arguments* args){
    char** mask = NULL;
    TwoPoints source, dest;
    FILE* eyeList;
    char line[ FILE_LINE_LENGTH ];
    char filename[MAX_FILENAME_LENGTH];
    char imagename[MAX_FILENAME_LENGTH];
    char suffix[MAX_FILENAME_LENGTH];
    int i;

    scaleArgs(args, args->scale);

    dest.x1 = args->eyeLx;
    dest.y1 = args->eyeLy;
    dest.x2 = args->eyeRx;
    dest.y2 = args->eyeRy;

    /* Prepare file suffix encoding preprocessing settings, blank if not requested */
    if (args->configSuffix) {
        sprintf(suffix,"_%s", imageSuffix(args)); }
    else {
        suffix[0] = '\0'; }	

    if(args->maskType == CL_YES){
        MESSAGE("Creating Mask.");
        mask = generateMask(args->sizeWidth, args->sizeHeight, args->ellipseX, args->ellipseY, args->ellipseA, args->ellipseB);
    }

    eyeList = fopen(args->eyeFile,"r");
    DEBUG_CHECK(eyeList,"Error opening eye coordinates file");

    for(i = 1;;i++){
        Image pgm;
        Image geo;
        Matrix transform;

        fgets(line, FILE_LINE_LENGTH, eyeList);
        if(feof(eyeList)) break;

        if(sscanf(line,"%s %lf %lf %lf %lf",filename, &(source.x1), &(source.y1), &(source.x2), &(source.y2)) != 5){
            printf("Error parsing line %d of eye coordinate file. Exiting...",i);
            exit(1);
        }

        /* shift the eye coordinates if neccessary */
        source.x1 += args->shiftX;
        source.y1 += args->shiftY;
        source.x2 += args->shiftX;
        source.y2 += args->shiftY;

        sprintf(imagename,"%s\\%s.pgm",args->inputDir,filename);

        MESSAGE1ARG("Processing image: %s",filename);

        pgm = readPGMImage(imagename);

        if(args->histType == HIST_PRE){
            DEBUG(1,"   Performing Pre Histogram Equalization.");
            histEqual(pgm,256);
        }

        if(args->preNormType == CL_YES){
            DEBUG(1,"   Performing Pre Pixel Normalization.");
            ZeroMeanOneStdDev(pgm);
        }

        if(args->preEdge){
            smoothImageEdge(pgm, args->preEdge);
        }

        if(args->geoType == CL_YES){
            DEBUG(1,"   Performing Geometric Normalization.");
            transform = generateTransform(&source,&dest,args->reflect);
            geo = transformImage(pgm,args->sizeWidth,args->sizeHeight,transform);
        }
        else{
            transform = makeIdentityMatrix(3);
            geo = transformImage(pgm,args->sizeWidth,args->sizeHeight,transform);
        }

        if(args->noise != 0.0){
            DEBUG(1,"   Adding Gausian Noise.");
            gaussianNoise(geo,args->noise);
        }


        if(args->histType == HIST_POST){
            DEBUG(1,"   Performing Post Histogram Equalization.");
            histEqualMask(geo,256, (const char**) mask);
        }

        if(args->nrmType == CL_YES){
            DEBUG(1,"   Performing final value normalization and Applying Mask.");
            ZeroMeanOneStdDevMasked(geo, (const char **) mask);
        }
        else{
            DEBUG(1,"   No Value Normalization. Just Applying Mask.");
            applyMask(geo, (const char **) mask);
        }

        if(args->postEdge){
            smoothImageEdge(geo, args->postEdge);
        }

        if(args->nrmDir){
            sprintf(imagename,"%s\\%s%s.nrm", args->nrmDir, filename, suffix);
            DEBUG_STRING(1,"   Saving nrm: %s",imagename);
            writeFeretImage(geo,imagename);
        }
        if(args->pgmDir){
            sprintf(imagename,"%s\\%s%s.pgm", args->pgmDir, filename, suffix);
            DEBUG_STRING(1,"   Saving pgm: %s",imagename);
            writePGMImage(geo,imagename,0);
        }
        if(args->sfiDir){
            sprintf(imagename,"%s\\%s%s.sfi", args->sfiDir, filename, suffix);
            DEBUG_STRING(1,"   Saving sfi: %s",imagename);
            writeRawImage(geo,imagename);
        }

        freeImage(geo);
        freeImage(pgm);
        freeMatrix(transform);
    }

    fclose(eyeList);

}
void fisherTrain(Matrix imspca, ImageList *srt, Matrix *fisherBasis, Matrix *fisherValues, int writeTextInterm) {
    int i;
    int numberOfClasses;
    Matrix G, N, Tmp;
    Matrix Rw = makeIdentityMatrix(imspca->row_dim);
    Matrix Siw = makeIdentityMatrix(imspca->row_dim);
    Matrix Ev = makeMatrix(imspca->row_dim, 1);
    Matrix Evecs = makeMatrix(imspca->row_dim, imspca->row_dim);
    Matrix Mw = findWCSMatrix(imspca, srt, &numberOfClasses, writeTextInterm);
    Matrix Mb = findBCSMatrix(imspca, Mw);
    *fisherValues = makeMatrix(imspca->row_dim, 1);

    MESSAGE2ARG("LDA Training started with %d classes and %d total training images.", numberOfClasses, imspca->col_dim);

    if (writeTextInterm) { SAVE_MATRIX(Mw); SAVE_MATRIX(Mb); } /* output textfiles of intermediate matrices */


    MESSAGE("Computing eigenspace decomposition of within class scatter matrix.");
    cvJacobiEigens_64d(Mw->data, Rw->data, Ev->data, Mw->row_dim, 0.0);

    MESSAGE("Computing the inverse scale matrix derived from eigenvalues and transformed scatter matrix.");
    for (i = 0; i < Ev->row_dim; i++)
        ME(Siw, i, i) = (ME(Ev, i, 0) <= 0.0) ? 0.0 : 1 / ( sqrt( ME(Ev, i, 0) ) );

    G = transposeMultiplyMatrixR(Siw, Rw);
    Tmp = transposeMultiplyMatrixR(Mb, G);
    N = multiplyMatrix(G, Tmp);
    freeMatrix(Tmp);

    if (writeTextInterm) {
        SAVE_MATRIX(Rw);
        SAVE_MATRIX(Ev);
        SAVE_MATRIX(N);
        SAVE_MATRIX(G);
        SAVE_MATRIX(Siw);
    } /* output textfiles of intermediate matrices */

    MESSAGE("Computing eigenspace of transformed between class scatter matrix.");
    cvJacobiEigens_64d(N->data, Evecs->data, (*fisherValues)->data, N->row_dim, 0.0);
    DEBUG(3, "FINSISHED");

    Tmp = multiplyMatrix(Siw, Evecs);
    DEBUG(1, "Calculating fisher basis");
    *fisherBasis = multiplyMatrix(Rw, Tmp);

    if (writeTextInterm) { SAVE_MATRIX(*fisherBasis); SAVE_MATRIX(*fisherValues); SAVE_MATRIX(Evecs); } /* output textfiles of intermediate matrices */

    /* The following verification code does not seem to work so it has been commented out. */
    /* fisherVerify(*fisherBasis, *fisherValues, Mw, Mb); */

    /* Crop the basis to the proper number of vectors */
    (*fisherBasis)->col_dim = numberOfClasses - 1;
    (*fisherValues)->row_dim = numberOfClasses - 1;

    basis_normalize(*fisherBasis);

    MESSAGE2ARG("Completed LDA Training. Fisher basis projection matrix has dimensions %d by %d.", (*fisherBasis)->row_dim, (*fisherBasis)->col_dim);

    /*Freeing memory allocated during LDA Training. */
    freeMatrix(Tmp);
    freeMatrix(Rw);
    freeMatrix(Siw);
    freeMatrix(Ev);
    freeMatrix(Mw);
    freeMatrix(Mb);
    freeMatrix(G);
    freeMatrix(N);
}
   void
   computeConsistentRotations(int const nViews,
                              std::vector<Matrix3x3d> const& relativeRotations,
                              std::vector<std::pair<int, int> > const& viewPairs,
                              std::vector<Matrix3x3d>& rotations, int method)
   {
#if !defined(V3DLIB_ENABLE_ARPACK)
      if (method == V3D_CONSISTENT_ROTATION_METHOD_SPARSE_EIG)
         method = V3D_CONSISTENT_ROTATION_METHOD_EIG_ATA;
#endif

      int const nRelPoses = relativeRotations.size();

      rotations.resize(nViews);

      switch (method)
      {
         case V3D_CONSISTENT_ROTATION_METHOD_SVD:
         {
            Matrix<double> A(3*nRelPoses, 3*nViews, 0.0);
            Matrix3x3d I;
            makeIdentityMatrix(I);
            scaleMatrixIP(-1.0, I);

            for (int i = 0; i < nRelPoses; ++i)
            {
               int const view1 = viewPairs[i].first;
               int const view2 = viewPairs[i].second;

               Matrix3x3d const& Rrel = relativeRotations[i];

               copyMatrixSlice(Rrel, 0, 0, 3, 3, A, 3*i, 3*view1);
               copyMatrixSlice(I,    0, 0, 3, 3, A, 3*i, 3*view2);
            } // end for (i)

            SVD<double> svd(A);
            int const startColumn = A.num_cols()-3; // last columns of right sing. vec for SVD

            Matrix<double> const& V = svd.getV();

            for (int i = 0; i < nViews; ++i)
            {
               copyMatrixSlice(V, 3*i, startColumn, 3, 3, rotations[i], 0, 0);
               enforceRotationMatrix(rotations[i]);
            }
            break;
         }
         case V3D_CONSISTENT_ROTATION_METHOD_SVD_ATA:
         case V3D_CONSISTENT_ROTATION_METHOD_EIG_ATA:
         case V3D_CONSISTENT_ROTATION_METHOD_SPARSE_EIG:
         {
            vector<pair<int, int> > nzA;
            vector<double> valsA;
            nzA.reserve(12*nRelPoses);
            valsA.reserve(12*nRelPoses);

            for (int i = 0; i < nRelPoses; ++i)
            {
               int const view1 = viewPairs[i].first;
               int const view2 = viewPairs[i].second;

               Matrix3x3d const& Rrel = relativeRotations[i];

               nzA.push_back(make_pair(3*i+0, 3*view1+0)); valsA.push_back(Rrel[0][0]);
               nzA.push_back(make_pair(3*i+0, 3*view1+1)); valsA.push_back(Rrel[0][1]);
               nzA.push_back(make_pair(3*i+0, 3*view1+2)); valsA.push_back(Rrel[0][2]);
               nzA.push_back(make_pair(3*i+1, 3*view1+0)); valsA.push_back(Rrel[1][0]);
               nzA.push_back(make_pair(3*i+1, 3*view1+1)); valsA.push_back(Rrel[1][1]);
               nzA.push_back(make_pair(3*i+1, 3*view1+2)); valsA.push_back(Rrel[1][2]);
               nzA.push_back(make_pair(3*i+2, 3*view1+0)); valsA.push_back(Rrel[2][0]);
               nzA.push_back(make_pair(3*i+2, 3*view1+1)); valsA.push_back(Rrel[2][1]);
               nzA.push_back(make_pair(3*i+2, 3*view1+2)); valsA.push_back(Rrel[2][2]);

               nzA.push_back(make_pair(3*i+0, 3*view2+0)); valsA.push_back(-1.0);
               nzA.push_back(make_pair(3*i+1, 3*view2+1)); valsA.push_back(-1.0);
               nzA.push_back(make_pair(3*i+2, 3*view2+2)); valsA.push_back(-1.0);
            } // end for (i)

            CCS_Matrix<double> A(3*nRelPoses, 3*nViews, nzA, valsA);

            if (method == V3D_CONSISTENT_ROTATION_METHOD_SPARSE_EIG)
            {
#if defined(V3DLIB_ENABLE_ARPACK)
               Vector<double> sigma;
               Matrix<double> V;
               SparseSymmetricEigConfig cfg;
               cfg.maxArnoldiIterations = 100000;
               computeSparseSVD(A, V3D_ARPACK_SMALLEST_MAGNITUDE_EIGENVALUES, 3, sigma, V, cfg);
               //computeSparseSVD(A, V3D_ARPACK_SMALLEST_EIGENVALUES, 3, sigma, V, cfg);
               for (int i = 0; i < nViews; ++i)
               {
                  copyMatrixSlice(V, 3*i, 0, 3, 1, rotations[i], 0, 2);
                  copyMatrixSlice(V, 3*i, 1, 3, 1, rotations[i], 0, 1);
                  copyMatrixSlice(V, 3*i, 2, 3, 1, rotations[i], 0, 0);
               }
#endif
            }
            else
            {
               Matrix<double> AtA(3*nViews, 3*nViews);
               multiply_At_A_SparseDense(A, AtA);

               if (method == V3D_CONSISTENT_ROTATION_METHOD_SVD_ATA)
               {
                  SVD<double> svd(AtA);
                  int const startColumn = A.num_cols()-3; // last columns of right sing. vec for SVD
                  Matrix<double> const& V = svd.getV();
                  for (int i = 0; i < nViews; ++i)
                     copyMatrixSlice(V, 3*i, startColumn, 3, 3, rotations[i], 0, 0);
               }
               else
               {
                  Eigenvalue<double> svd(AtA);
                  int const startColumn = 0; // first columns of eigenvector matrix
                  Matrix<double> const& V = svd.getV();
                  for (int i = 0; i < nViews; ++i)
                     copyMatrixSlice(V, 3*i, startColumn, 3, 3, rotations[i], 0, 0);
               } // end if
            } // end if
            break;
         }
         default:
            throwV3DErrorHere("Unknown method argument for computeConsistentRotations().");
      } // end switch

      for (int i = 0; i < nViews; ++i)
         enforceRotationMatrix(rotations[i]);

      // Remove gauge freedom by setting R[0] = I.
      Matrix3x3d const R0t = rotations[0].transposed();
      for (int i = 0; i < nViews; ++i)
         rotations[i] = rotations[i] * R0t;

      // Note: it seems, that either all Rs have det(R)=1 or all have det(R)=-1.
      // Since we remove the gauge freedem by multiplying all rotations with R_0^t,
      // we always end up with det(R)=1 and any code to enforce a positive determinant
      // is not necessary.
   } // end computeConsistentRotations()