Exemplo n.º 1
0
// compute optimal pose and scale using a procedure described by Umeyame,
// Least-squares estimation of transformation parameters between two point patterns (IEEE Pami 1991)
double computeScalingFactor(MeshType* mesh1, MeshType* mesh2)
{
    if (mesh1->GetNumberOfPoints() != mesh2->GetNumberOfPoints()) {
        throw std::runtime_error("meshes should be in correspondence when computing specificity");
    }

    PointListType points1;
    PointListType points2;
    for (unsigned i = 0; i < mesh1->GetNumberOfPoints(); i++) {

        MeshType::PointType pt1;
        mesh1->GetPoint(i, &pt1);
        points1.push_back(pt1);

        MeshType::PointType pt2;
        mesh2->GetPoint(i, &pt2);
        points2.push_back(pt2);
    }

    vnlMatrixType X  = createMatrixFromPoints(points1);
    vnlMatrixType Y =  createMatrixFromPoints(points2);

    vnlVectorType mu_x = calcMean(X);
    vnlVectorType mu_y = calcMean(Y);

    ElementType sigma2_x = calcVar(X, mu_x);
    ElementType sigma2_y = calcVar(Y, mu_y);

    vnlMatrixType Sigma_xy = calcCov(X, Y, mu_x, mu_y);

    vnl_svd<ElementType> SVD(Sigma_xy);

    unsigned m = X.rows();

    vnlMatrixType S(m,m);
    S.set_identity();
    ElementType detU = vnl_qr<ElementType>(SVD.U()).determinant();
    ElementType detV = vnl_qr<ElementType>(SVD.V()).determinant();
    if ( detU * detV == -1) {
        S[m-1][m-1] = -1;
    }


    // the procedure actually computes the optimal rotation, translation and scale. We only
    // use the scaling factor
    vnlMatrixType R = SVD.U() * S * SVD.V().transpose();

    ElementType c = 1/sigma2_x * vnl_trace(SVD.W()*S);
    vnlVectorType t = mu_y - c * R * mu_x;
    ElementType epsilon2 = sigma2_y -  pow(vnl_trace(SVD.W()*S), 2) / sigma2_x;

    return c;
}
Exemplo n.º 2
0
double TpsRegistration::BendingEnergy() {
  return vnl_trace(param_tps_.transpose() * kernel_ * param_tps_);
}
Exemplo n.º 3
0
bool arlCore::ICP::solve( void )
{
    const double Tau = 10e-8;
    const bool Verbose = false;
    m_startError = -1.0;
    m_nbIterations = 0;
#ifdef ANN
    if(!m_point2PointMode) return false;
    m_endError = FLT_MAX/2.0;
    double previousRMS = FLT_MAX;
    if(!m_initialization)
        if(!initialization())
            return false;
//  http://csdl2.computer.org/persagen/DLAbsToc.jsp?resourcePath=/dl/trans/tp/&toc=comp/trans/tp/1992/02/i2toc.xml&DOI=10.1109/34.121791
//  http://ieeexplore.ieee.org/iel1/34/3469/00121791.pdf?tp=&arnumber=121791&isnumber=3469
    unsigned int i, j, k;
    vnl_quaternion<double> qr(0,0,0,1);
    vnl_matrix_fixed<double,3,3> Id3, Ricp, Spy;
    Id3.set_identity();
    vnl_matrix_fixed<double,4,4> QSpy;
    vnl_vector_fixed<double,3> Delta;
    while( fabs(m_endError-previousRMS)>Tau && m_nbIterations<m_maxIterations ) //&& RMS>RMSMax )
    {
        ++m_nbIterations;
        std::cout<<m_nbIterations<<" ";
        previousRMS = m_endError;
        computeError(); // step 1
        if(m_startError<0) m_startError = m_endError;
        // step 2
        // Calculate the cross-variance matrix between m_Pk and Yo
        // Cov( P0, m_Yk ) = 1/n*somme(P0*m_Yk') - ComP0*Comm_Yk'
        Spy.set_identity();
        for( i=0 ; i<m_cloudSize ; ++i )
          for( j=0 ; j<3 ; ++j )
            for( k=0 ; k<3 ; ++k )
            Spy[j][k]+= m_Pi[i][j]*m_Yk[i][k];
        for( i=0 ; i<3 ; ++i )
          for( j=0 ; j<3 ; ++j )
            Spy[i][j] = Spy[i][j]/(double)m_cloudSize - m_cloudGravity[i]*m_modelGravity[j];
        // Delta = [A23 A31 A12] with Amn = Spy[m][n]-Spy[n][m]
        Delta[0] = Spy[1][2]-Spy[2][1];
        Delta[1] = Spy[2][0]-Spy[0][2];
        Delta[2] = Spy[0][1]-Spy[1][0];
        // calculate the symmetric 4x4 matrix needed to determine
        // the max eigenvalue
        QSpy[0][0] = vnl_trace( Spy );
        for( i=1 ; i<4 ; ++i )
        {
            QSpy[i][0] = Delta[i-1];
            for( j = 1; j < 4; ++j )
            {
                QSpy[0][j] = Delta[j-1];
                QSpy[i][j] = Spy[i-1][j-1]+Spy[j-1][i-1] - QSpy[0][0]*Id3[i-1][j-1];
            }
        }
        vnl_symmetric_eigensystem<double> eigQSpy(QSpy);
        // Optimal rotation matrix calculate from the quaternion
        // vector qr=[q0 q1 q2 q3] obtained by obtained the max eigen value
        // http://paine.wiau.man.ac.uk/pub/doc_vxl/core/vnl/html/vnl__symmetric__eigensystem_8h.html
        qr.update(eigQSpy.get_eigenvector(3));
        qr = vnl_quaternion<double>(qr[1], qr[2], qr[3], qr[0]);
        Ricp = vnl_transpose(qr.rotation_matrix_transpose()).asMatrix();
        // Optimal translation vector Ticp T = ComY - Ricp.ComP
        vnl_vector<double> TraTemp = m_modelGravity - Ricp*m_cloudGravity;
        // step 3 : Application of the transformation
        for( i=0 ; i<m_cloudSize ; ++i )
          for( j=0 ; j<3 ; ++j )
            m_Pk[i][j] = Ricp[j][0]*m_Pi[i][0] + Ricp[j][1]*m_Pi[i][1] + Ricp[j][2]*m_Pi[i][2] + TraTemp[j];
    }
    // Give the transformation from model ==> cloud
    // First we add the first transformation to Rend
    vnl_matrix_fixed<double,3,3> Rend = Ricp.transpose();
    vnl_vector_fixed<double,3> Tend;
    for( i=0 ; i<3 ; ++i )
        Tend[i] = m_cloudGravity[i]-(Rend[i][0]*m_modelGravity[0]+Rend[i][1]*m_modelGravity[1]+Rend[i][2]*m_modelGravity[2]);
    // Initial matrix [m_rotInit ; m_traInit ; 0 0 0 1]
    // Found matrix [Rend ; Tend ; 0 0 0 1]
    m_solution.vnl_matrix_fixed<double,4,4>::update(vnl_inverse(m_rotInit)*Rend);
    m_solution.set_column(3,vnl_inverse(m_rotInit)*(Tend-m_traInit));
    m_solution[3][3] = 1.0;
    m_solution.setRMS( m_endError );
    if(Verbose)
    {
        std::cout<<"ICP registration\n";
        std::cout<<"First RMS="<<m_startError<<"\nLast RMS="<<m_endError<<"\nIterations="<<m_nbIterations<<"\nPtsModel="<<m_modelSize<<"\nPtsCloud="<<m_cloudSize<<"\n";
        std::cout<<"Tau ="<<fabs(m_endError-previousRMS)<<"\n";
        std::cout<<"Matrix ="<<m_solution<<"\n";
    }
    return true;
#else // ANN
    m_endError = -1.0;
    return false;
#endif // ANN
}