Example #1
0
double volume(OpenMesh::Vec3f& pointA, OpenMesh::Vec3f& pointB, OpenMesh::Vec3f& pointC)
{
	// http://www.ditutor.com/vectors/volume_tetrahedron.html
	Mat3 m = pointsToMat(pointA , pointB, pointC);
	// use minus sign or change the order of the points in above function call 
	return -m.determinant()/6.0;
}
// Check the properties of a fundamental matrix:
//
//   1. The determinant is 0 (rank deficient)
//   2. The condition x'T*F*x = 0 is satisfied to precision.
//
bool ExpectFundamentalProperties(const Mat3 &F,
                                 const Mat &ptsA,
                                 const Mat &ptsB,
                                 double precision) {
  bool bOk = true;
  bOk &= F.determinant() < precision;
  assert(ptsA.cols() == ptsB.cols());
  const Mat hptsA = ptsA.colwise().homogeneous();
  const Mat hptsB = ptsB.colwise().homogeneous();
  for (int i = 0; i < ptsA.cols(); ++i) {
    const double residual = hptsB.col(i).dot(F * hptsA.col(i));
    bOk &= residual < precision;
  }
  return bOk;
}
Example #3
0
IGL_INLINE void igl::fit_rotations(
  const Eigen::PlainObjectBase<DerivedS> & S,
  const bool single_precision,
  Eigen::PlainObjectBase<DerivedD> & R)
{
  using namespace std;
  const int dim = S.cols();
  const int nr = S.rows()/dim;
  assert(nr * dim == S.rows());
  assert(dim == 3);

  // resize output
  R.resize(dim,dim*nr); // hopefully no op (should be already allocated)

  //std::cout<<"S=["<<std::endl<<S<<std::endl<<"];"<<std::endl;
  //MatrixXd si(dim,dim);
  Eigen::Matrix<typename DerivedS::Scalar,3,3> si;// = Eigen::Matrix3d::Identity();
  // loop over number of rotations we're computing
  for(int r = 0;r<nr;r++)
  {
    // build this covariance matrix
    for(int i = 0;i<dim;i++)
    {
      for(int j = 0;j<dim;j++)
      {
        si(i,j) = S(i*nr+r,j);
      }
    }
    typedef Eigen::Matrix<typename DerivedD::Scalar,3,3> Mat3;
    typedef Eigen::Matrix<typename DerivedD::Scalar,3,1> Vec3;
    Mat3 ri;
    if(single_precision)
    {
      polar_svd3x3(si, ri);
    }else
    {
      Mat3 ti,ui,vi;
      Vec3 _;
      igl::polar_svd(si,ri,ti,ui,_,vi);
    }
    assert(ri.determinant() >= 0);
    R.block(0,r*dim,dim,dim) = ri.block(0,0,dim,dim).transpose();
    //cout<<matlab_format(si,C_STR("si_"<<r))<<endl;
    //cout<<matlab_format(ri.transpose().eval(),C_STR("ri_"<<r))<<endl;
  }
}
Example #4
0
void KRt_From_P(const Mat34 &P, Mat3 *Kp, Mat3 *Rp, Vec3 *tp) {
  // Decompose using the RQ decomposition HZ A4.1.1 pag.579.
  Mat3 K = P.block(0, 0, 3, 3);

  Mat3 Q;
  Q.setIdentity();

  // Set K(2,1) to zero.
  if (K(2,1) != 0) {
    double c = -K(2,2);
    double s = K(2,1);
    double l = sqrt(c * c + s * s);
    c /= l; s /= l;
    Mat3 Qx;
    Qx << 1, 0, 0,
          0, c, -s,
          0, s, c;
    K = K * Qx;
    Q = Qx.transpose() * Q;
  }
  // Set K(2,0) to zero.
  if (K(2,0) != 0) {
    double c = K(2,2);
    double s = K(2,0);
    double l = sqrt(c * c + s * s);
    c /= l; s /= l;
    Mat3 Qy;
    Qy << c, 0, s,
          0, 1, 0,
         -s, 0, c;
    K = K * Qy;
    Q = Qy.transpose() * Q;
  }
  // Set K(1,0) to zero.
  if (K(1,0) != 0) {
    double c = -K(1,1);
    double s = K(1,0);
    double l = sqrt(c * c + s * s);
    c /= l; s /= l;
    Mat3 Qz;
    Qz << c,-s, 0,
          s, c, 0,
          0, 0, 1;
    K = K * Qz;
    Q = Qz.transpose() * Q;
  }

  Mat3 R = Q;

  //Mat3 H = P.block(0, 0, 3, 3);
  // RQ decomposition
  //Eigen::HouseholderQR<Mat3> qr(H);
  //Mat3 K = qr.matrixQR().triangularView<Eigen::Upper>();
  //Mat3 R = qr.householderQ();

  // Ensure that the diagonal is positive and R determinant == 1.
  if (K(2,2) < 0) {
    K = -K;
    R = -R;
  }
  if (K(1,1) < 0) {
    Mat3 S;
    S << 1, 0, 0,
         0,-1, 0,
         0, 0, 1;
    K = K * S;
    R = S * R;
  }
  if (K(0,0) < 0) {
    Mat3 S;
    S << -1, 0, 0,
          0, 1, 0,
          0, 0, 1;
    K = K * S;
    R = S * R;
  }

  // Compute translation.
  Eigen::PartialPivLU<Mat3> lu(K);
  Vec3 t = lu.solve(P.col(3));

  if(R.determinant()<0) {
    R = -R;
    t = -t;
  }

  // scale K so that K(2,2) = 1
  K = K / K(2,2);

  *Kp = K;
  *Rp = R;
  *tp = t;
}
Example #5
0
void DecomposeProjectionMatrix(const Mat& P, Mat3* K, Mat3* R, Vec3* t)
{
    // This is a modified version of the function "KRt_From_P", found in libmv and openMVG.
    // It is subject to the terms of the Mozilla Public License, v. 2.0, a copy of the MPL
    // can be found under "license.openMVG"

    // Decompose using the RQ decomposition HZ A4.1.1 pag.579.
    Mat3 Kp = P.block(0, 0, 3, 3);
    Mat3 Q; Q.setIdentity();

    // Set K(2, 1) to zero.
    if (Kp(2, 1) != 0)
    {
        double c = -Kp(2, 2);
        double s =  Kp(2, 1);
        double l = sqrt(c * c + s * s);
        c /= l; s /= l;
        Mat3 Qx;
        Qx <<  1,  0,  0,
               0,  c, -s,
               0,  s,  c;
        Kp = Kp * Qx;
        Q = Qx.transpose() * Q;
    }

    // Set K(2, 0) to zero.
    if (Kp(2, 0) != 0)
    {
        double c = Kp(2, 2);
        double s = Kp(2, 0);
        double l = sqrt(c * c + s * s);
        c /= l; s /= l;
        Mat3 Qy;
        Qy <<  c,  0,  s,
               0,  1,  0,
              -s,  0,  c;
        Kp = Kp * Qy;
        Q = Qy.transpose() * Q;
    }

    // Set K(1, 0) to zero.
    if (Kp(1, 0) != 0)
    {
        double c = -Kp(1, 1);
        double s =  Kp(1, 0);
        double l = sqrt(c * c + s * s);
        c /= l; s /= l;
        Mat3 Qz;
        Qz <<  c, -s,  0,
               s,  c,  0,
               0,  0,  1;
        Kp = Kp * Qz;
        Q = Qz.transpose() * Q;
    }

    Mat3 Rp = Q;

    // Ensure that the diagonal is positive and R determinant == 1
    if (Kp(2, 2) < 0)
    {
        Kp = -Kp;
        Rp = -Rp;
    }

    if (Kp(1, 1) < 0)
    {
        Mat3 S;
        S <<  1,  0,  0,
              0, -1,  0,
              0,  0,  1;
        Kp = Kp * S;
        Rp = S  * Rp;
    }

    if (Kp(0, 0) < 0)
    {
        Mat3 S;
        S << -1,  0,  0,
              0,  1,  0,
              0,  0,  1;
        Kp = Kp * S;
        Rp = S  * Rp;
    }

    // Compute translation.
    Vec3 tp = Kp.colPivHouseholderQr().solve(P.col(3));

    if(Rp.determinant() < 0)
    {
        Rp = -Rp;
        tp = -tp;
    }

    // Scale K so that K(2, 2) = 1
    Kp = Kp / Kp(2, 2);

    *K = Kp;
    *R = Rp;
    *t = tp;
}
Example #6
0
bool FindExtrinsics(const Mat3& E, const Point2Vec& pts1, const Point2Vec& pts2, Mat3* R, Vec3* t)
{
    const auto num_correspondences = pts1.size();

    // Put first camera at origin
    Mat3 R0;    R0.setIdentity();
    Vec3 t0;    t0.setZero();

    // Find the SVD of E
    Eigen::JacobiSVD<Mat3> svd{E, Eigen::ComputeFullU | Eigen::ComputeFullV};
    Mat3 U  = svd.matrixU();
    Mat3 Vt = svd.matrixV().transpose();

    // Find R and t
    Mat3 D;
    D << 0,  1,  0,
        -1,  0,  0,
         0,  0,  1;

    Mat3 Ra = U * D * Vt;
    Mat3 Rb = U * D.transpose() * Vt;

    if (Ra.determinant() < 0.0) Ra *= -1.0;
    if (Rb.determinant() < 0.0) Rb *= -1.0;

    Vec3 tu = U.col(2);

    // Figure out which configuration is correct using the supplied points
    int c1_pos = 0, c2_pos = 0, c1_neg = 0, c2_neg = 0;

    for (std::size_t i = 0; i < num_correspondences; i++)
    {
        const Point3 Q = Triangulate(Observations{Observation{pts1[i], R0, t0}, Observation{pts2[i], Ra, tu}});
        const Point3 PQ = (Ra * Q) + tu;

        if (Q.z() > 0)  c1_pos++;
        else            c1_neg++;
        
        if (PQ.z() > 0) c2_pos++;
        else            c2_neg++;
    }

    if (c1_pos < c1_neg && c2_pos < c2_neg)
    {
        *R =  Ra;
        *t =  tu;
    } else if (c1_pos > c1_neg && c2_pos > c2_neg)
    {
        *R =  Ra;
        *t = -tu;
    } else
    {
        // Triangulate again
        c1_pos = c1_neg = c2_pos = c2_neg = 0;

        for (std::size_t i = 0; i < num_correspondences; i++)
        {
            const Point3 Q = Triangulate(Observations{Observation{pts1[i], R0, t0}, Observation{pts2[i], Rb, tu}});
            const Point3 PQ = (Rb * Q) + tu;

            if (Q.z() > 0)  c1_pos++;
            else            c1_neg++;
        
            if (PQ.z() > 0) c2_pos++;
            else            c2_neg++;
        }

        if (c1_pos < c1_neg && c2_pos < c2_neg)
        {
            *R =  Rb;
            *t =  tu;
        } else if (c1_pos > c1_neg && c2_pos > c2_neg)
        {
            *R =  Rb;
            *t = -tu;
        } else
        {
            std::cerr << "[FindExtrinsics] Error: no case found!";
            return false;
        }
    }

    return true;
}