removed svd and dependent methods and tests
							parent
							
								
									1a2e1e11b4
								
							
						
					
					
						commit
						6c85702ee6
					
				| 
						 | 
				
			
			@ -915,80 +915,6 @@ Matrix cholesky_inverse(const Matrix &A)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
/** SVD                                                                      */
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
 | 
			
		||||
// version with in place modification of A
 | 
			
		||||
void svd(Matrix& A, Vector& s, Matrix& V, bool sort) {
 | 
			
		||||
 | 
			
		||||
  const size_t m=A.size1(), n=A.size2();
 | 
			
		||||
  if( m < n )
 | 
			
		||||
	 throw invalid_argument("in-place svd calls NRC which needs matrix A with m>n");
 | 
			
		||||
 | 
			
		||||
  double * q = new double[n]; // singular values
 | 
			
		||||
 | 
			
		||||
  // create NRC matrices, u is in place
 | 
			
		||||
  V = Matrix(n,n);
 | 
			
		||||
  double **u = createNRC(A), **v = createNRC(V);
 | 
			
		||||
 | 
			
		||||
  // perform SVD
 | 
			
		||||
  // need to pass pointer - 1 in NRC routines so u[1][1] is first element !
 | 
			
		||||
  svdcmp(u-1,m,n,q-1,v-1, sort);
 | 
			
		||||
	
 | 
			
		||||
  // copy singular values back
 | 
			
		||||
  s.resize(n);
 | 
			
		||||
  copy(q,q+n,s.begin());
 | 
			
		||||
 | 
			
		||||
  delete[] v;
 | 
			
		||||
  delete[] q; //switched to array delete
 | 
			
		||||
  delete[] u;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
void svd(const Matrix& A, Matrix& U, Vector& s, Matrix& V, bool sort) {
 | 
			
		||||
  const size_t m=A.size1(), n=A.size2();
 | 
			
		||||
  if( m < n ) {
 | 
			
		||||
	  V = trans(A);
 | 
			
		||||
	  svd(V,s,U,sort); // A'=V*diag(s)*U'
 | 
			
		||||
  }
 | 
			
		||||
  else{
 | 
			
		||||
	  U = A;      // copy
 | 
			
		||||
	  svd(U,s,V,sort); // call in-place version
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
boost::tuple<int, double, Vector> DLT(const Matrix& A, double rank_tol) {
 | 
			
		||||
 | 
			
		||||
	// Check size of A
 | 
			
		||||
	int m = A.size1(), n = A.size2();
 | 
			
		||||
	if (m<n) throw invalid_argument("DLT: m<n, pad A with zero rows if needed.");
 | 
			
		||||
 | 
			
		||||
	// Do SVD on A
 | 
			
		||||
	Matrix U, V;
 | 
			
		||||
	Vector S;
 | 
			
		||||
	static const bool sort = false;
 | 
			
		||||
	svd(A, U, S, V, sort);
 | 
			
		||||
 | 
			
		||||
	// Find rank
 | 
			
		||||
	int rank = 0;
 | 
			
		||||
	for (int j = 0; j < n; j++)
 | 
			
		||||
		if (S(j) > rank_tol)
 | 
			
		||||
			rank++;
 | 
			
		||||
	// Find minimum singular value and corresponding column index
 | 
			
		||||
	int min_j = n - 1;
 | 
			
		||||
	double min_S = S(min_j);
 | 
			
		||||
	for (int j = 0; j < n - 1; j++)
 | 
			
		||||
		if (S(j) < min_S) {
 | 
			
		||||
			min_j = j;
 | 
			
		||||
			min_S = S(j);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	// Return rank, minimum singular value, and corresponding column of V
 | 
			
		||||
	return boost::tuple<int, double, Vector>(rank, min_S, column_(V, min_j));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
// TODO, would be faster with Cholesky
 | 
			
		||||
| 
						 | 
				
			
			@ -1023,22 +949,6 @@ Matrix inverse_square_root(const Matrix& A) {
 | 
			
		|||
	return inv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
Matrix square_root_positive(const Matrix& A) {
 | 
			
		||||
  size_t m = A.size2(), n = A.size1();
 | 
			
		||||
  if (m!=n)
 | 
			
		||||
    throw invalid_argument("inverse_square_root: A must be square");
 | 
			
		||||
 | 
			
		||||
  // Perform SVD, TODO: symmetric SVD?
 | 
			
		||||
  Matrix U,V;
 | 
			
		||||
  Vector S;
 | 
			
		||||
  svd(A,U,S,V,false);
 | 
			
		||||
 | 
			
		||||
  // invert and sqrt diagonal of S
 | 
			
		||||
  // We also arbitrarily choose sign to make result have positive signs
 | 
			
		||||
  for(size_t i = 0; i<m; i++) S(i) = - pow(S(i),0.5);
 | 
			
		||||
  return vector_scale(S, V); // V*S;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
Matrix expm(const Matrix& A, size_t K) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -360,47 +360,9 @@ Matrix vector_scale(const Matrix& A, const Vector& v); // column
 | 
			
		|||
Matrix skewSymmetric(double wx, double wy, double wz);
 | 
			
		||||
inline Matrix skewSymmetric(const Vector& w) { return skewSymmetric(w(0),w(1),w(2));}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SVD computes economy SVD A=U*S*V'
 | 
			
		||||
 * @param A an m*n matrix
 | 
			
		||||
 * @param U output argument: rotation matrix
 | 
			
		||||
 * @param S output argument: vector of singular values, sorted by default, pass false as last argument to avoid sorting!!!
 | 
			
		||||
 * @param V output argument: rotation matrix
 | 
			
		||||
 * @param sort boolean flag to sort singular values and V
 | 
			
		||||
 * if m > n then U*S*V' = (m*n)*(n*n)*(n*n) (the m-n columns of U are of no use)
 | 
			
		||||
 * if m < n then U*S*V' = (m*m)*(m*m)*(m*n) (the n-m columns of V are of no use)
 | 
			
		||||
 * Careful! The dimensions above reflect V', not V, which is n*m if m<n.
 | 
			
		||||
 * U is a basis in R^m, V is a basis in R^n
 | 
			
		||||
 * You can just pass empty matrices U,V, and vector S, they will be re-allocated.
 | 
			
		||||
 */ 
 | 
			
		||||
void svd(const Matrix& A, Matrix& U, Vector& S, Matrix& V, bool sort=true);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * In place SVD, will throw an exception when m < n
 | 
			
		||||
 * @param A an m*n matrix is modified to contain U
 | 
			
		||||
 * @param S output argument: vector of singular values, sorted by default, pass false as last argument to avoid sorting!!!
 | 
			
		||||
 * @param V output argument: rotation matrix
 | 
			
		||||
 * @param sort boolean flag to sort singular values and V
 | 
			
		||||
 * if m > n then U*S*V' = (m*n)*(n*n)*(n*n) (the m-n columns of U are of no use)
 | 
			
		||||
 * You can just pass empty matrix V and vector S, they will be re-allocated.
 | 
			
		||||
 */
 | 
			
		||||
void svd(Matrix& A, Vector& S, Matrix& V, bool sort=true);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Direct linear transform algorithm that calls svd
 | 
			
		||||
 * to find a vector v that minimizes the algebraic error A*v
 | 
			
		||||
 * @param A of size m*n, where m>=n (pad with zero rows if not!)
 | 
			
		||||
 * Returns rank of A, minimum error (singular value),
 | 
			
		||||
 * and corresponding eigenvector (column of V, with A=U*S*V')
 | 
			
		||||
 */
 | 
			
		||||
boost::tuple<int,double,Vector> DLT(const Matrix& A, double rank_tol=1e-9);
 | 
			
		||||
 | 
			
		||||
/** Use SVD to calculate inverse square root of a matrix */
 | 
			
		||||
Matrix inverse_square_root(const Matrix& A);
 | 
			
		||||
 | 
			
		||||
/** Use SVD to calculate the positive square root of a matrix */
 | 
			
		||||
Matrix square_root_positive(const Matrix& A);
 | 
			
		||||
 | 
			
		||||
/** Calculate the LL^t decomposition of a S.P.D matrix */
 | 
			
		||||
Matrix LLt(const Matrix& A);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -729,106 +729,6 @@ TEST( matrix, row_major_access )
 | 
			
		|||
	DOUBLES_EQUAL(3,a[2],1e-9);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
TEST( matrix, svd1 )
 | 
			
		||||
{
 | 
			
		||||
	double data[] = { 2, 1, 0 };
 | 
			
		||||
	Vector v(3);
 | 
			
		||||
	copy(data, data + 3, v.begin());
 | 
			
		||||
	Matrix U1 = eye(4, 3), S1 = diag(v), V1 = eye(3, 3), A = (U1 * S1)
 | 
			
		||||
			* Matrix(trans(V1));
 | 
			
		||||
	Matrix U, V;
 | 
			
		||||
	Vector s;
 | 
			
		||||
	svd(A, U, s, V);
 | 
			
		||||
	Matrix S = diag(s);
 | 
			
		||||
	EQUALITY(U*S*Matrix(trans(V)),A);
 | 
			
		||||
	EQUALITY(S,S1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
/// Sample A matrix for SVD
 | 
			
		||||
static double sampleData[] ={0,-2, 0,0, 3,0};
 | 
			
		||||
static Matrix sampleA = Matrix_(3, 2, sampleData);
 | 
			
		||||
static Matrix sampleAt = trans(sampleA);
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
TEST( matrix, svd2 )
 | 
			
		||||
{
 | 
			
		||||
	Matrix U, V;
 | 
			
		||||
	Vector s;
 | 
			
		||||
 | 
			
		||||
	Matrix expectedU = Matrix_(3, 2, 0.,1.,0.,0.,-1.,0.);
 | 
			
		||||
	Vector expected_s = Vector_(2, 3.,2.);
 | 
			
		||||
	Matrix expectedV = Matrix_(2, 2, -1.,0.,0.,-1.);
 | 
			
		||||
 | 
			
		||||
	svd(sampleA, U, s, V);
 | 
			
		||||
 | 
			
		||||
	EQUALITY(expectedU,U);
 | 
			
		||||
	CHECK(equal_with_abs_tol(expected_s,s,1e-9));
 | 
			
		||||
	EQUALITY(expectedV,V);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
TEST( matrix, svd3 )
 | 
			
		||||
{
 | 
			
		||||
	Matrix U, V;
 | 
			
		||||
	Vector s;
 | 
			
		||||
 | 
			
		||||
	Matrix expectedU = Matrix_(2, 2, -1.,0.,0.,-1.);
 | 
			
		||||
	Vector expected_s = Vector_(2, 3.0,2.0);
 | 
			
		||||
	Matrix expectedV = Matrix_(3, 2, 0.,1.,0.,0.,-1.,0.);
 | 
			
		||||
 | 
			
		||||
	svd(sampleAt, U, s, V);
 | 
			
		||||
	Matrix S = diag(s);
 | 
			
		||||
	Matrix t = prod(U,S);
 | 
			
		||||
	Matrix Vt = trans(V);
 | 
			
		||||
 | 
			
		||||
	EQUALITY(sampleAt, prod(t,Vt));
 | 
			
		||||
	EQUALITY(expectedU,U);
 | 
			
		||||
	CHECK(equal_with_abs_tol(expected_s,s,1e-9));
 | 
			
		||||
	EQUALITY(expectedV,V);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
/// Homography matrix for points
 | 
			
		||||
//Point2h(0, 0, 1), Point2h(4, 5, 1);
 | 
			
		||||
//Point2h(1, 0, 1), Point2h(5, 5, 1);
 | 
			
		||||
//Point2h(1, 1, 1), Point2h(5, 6, 1);
 | 
			
		||||
//Point2h(0, 1, 1), Point2h(4, 6, 1);
 | 
			
		||||
static double homography_data[] = {0,0,0,-4,-5,-1,0,0,0,
 | 
			
		||||
				4,5,1,0,0,0,0,0,0,
 | 
			
		||||
				0,0,0,0,0,0,0,0,0,
 | 
			
		||||
				0,0,0,-5,-5,-1,0,0,0,
 | 
			
		||||
				5,5,1,0,0,0,-5,-5,-1,
 | 
			
		||||
				0,0,0,5,5,1,0,0,0,
 | 
			
		||||
				0,0,0,-5,-6,-1,5,6,1,
 | 
			
		||||
				5,6,1,0,0,0,-5,-6,-1,
 | 
			
		||||
			   -5,-6,-1,5,6,1,0,0,0,
 | 
			
		||||
				0,0,0,-4,-6,-1,4,6,1,
 | 
			
		||||
				4,6,1,0,0,0,0,0,0,
 | 
			
		||||
			   -4,-6,-1,0,0,0,0,0,0};
 | 
			
		||||
static Matrix homographyA = Matrix_(12, 9, homography_data);
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
TEST( matrix, svd_sort )
 | 
			
		||||
{
 | 
			
		||||
	Matrix U1, U2, V1, V2;
 | 
			
		||||
	Vector s1, s2;
 | 
			
		||||
	svd(homographyA, U1, s1, V1);
 | 
			
		||||
	for(int i = 0 ; i < 8 ; i++)
 | 
			
		||||
		CHECK(s1[i]>=s1[i+1]); // Check if singular values are sorted
 | 
			
		||||
 | 
			
		||||
	svd(homographyA, U2, s2, V2, false);
 | 
			
		||||
	CHECK(s1[8]==s2[7]); // Check if swapping is done
 | 
			
		||||
	CHECK(s1[7]==s2[8]);
 | 
			
		||||
	Vector v17 = column_(V1, 7);
 | 
			
		||||
	Vector v18 = column_(V1, 8);
 | 
			
		||||
	Vector v27 = column_(V2, 7);
 | 
			
		||||
	Vector v28 = column_(V2, 8);
 | 
			
		||||
	CHECK(v17==v28); // Check if vectors are also swapped correctly
 | 
			
		||||
	CHECK(v18==v27); // Check if vectors are also swapped correctly
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
// update A, b
 | 
			
		||||
// A' \define A_{S}-ar and b'\define b-ad
 | 
			
		||||
| 
						 | 
				
			
			@ -939,19 +839,6 @@ TEST( matrix, LLt )
 | 
			
		|||
	EQUALITY(expected, LLt(M));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
TEST( matrix, square_root_positive )
 | 
			
		||||
{
 | 
			
		||||
	Matrix cov = Matrix_(3, 3, 4.0, 0.0, 0.0, 0.0, 4.0, 0.0, 0.0, 0.0, 100.0);
 | 
			
		||||
 | 
			
		||||
	Matrix expected = Matrix_(3, 3, 2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0,
 | 
			
		||||
			10.0);
 | 
			
		||||
 | 
			
		||||
	Matrix actual = square_root_positive(cov);
 | 
			
		||||
	CHECK(assert_equal(expected, actual));
 | 
			
		||||
	CHECK(assert_equal(cov, prod(trans(actual),actual)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
TEST( matrix, multiplyAdd )
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ check_PROGRAMS += tests/testStereoCamera
 | 
			
		|||
headers += tensors.h Tensor1.h Tensor2.h Tensor3.h Tensor4.h Tensor5.h
 | 
			
		||||
headers += Tensor1Expression.h Tensor2Expression.h Tensor3Expression.h Tensor5Expression.h
 | 
			
		||||
sources += projectiveGeometry.cpp tensorInterface.cpp
 | 
			
		||||
check_PROGRAMS += tests/testTensors tests/testHomography2 tests/testTrifocal tests/testFundamental
 | 
			
		||||
check_PROGRAMS += tests/testTensors tests/testHomography2 tests/testFundamental
 | 
			
		||||
 | 
			
		||||
# Timing tests
 | 
			
		||||
noinst_PROGRAMS = tests/timeRot3 tests/timeCalibratedCamera
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -77,61 +77,6 @@ namespace gtsam {
 | 
			
		|||
		return data;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* ************************************************************************* */
 | 
			
		||||
	Homography2 estimateHomography2(const list<Correspondence>& correspondences) {
 | 
			
		||||
		// Generate entries of A matrix for linear estimation
 | 
			
		||||
		size_t m = correspondences.size();
 | 
			
		||||
		if (m<4) throw invalid_argument("estimateHomography2: need at least 4 correspondences");
 | 
			
		||||
		Matrix A;
 | 
			
		||||
		BOOST_FOREACH(const Correspondence& p, correspondences) {
 | 
			
		||||
			Matrix Ap = reshape(p.first(a) * (eta(_b, _c, _d) * p.second(b)),3,9);
 | 
			
		||||
			A = stack(2,&A,&Ap);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Call DLT and reshape to Homography
 | 
			
		||||
		int rank; double error; Vector v;
 | 
			
		||||
		boost::tie(rank, error, v) = DLT(A);
 | 
			
		||||
		if (rank < 8) throw invalid_argument("estimateHomography2: not enough data");
 | 
			
		||||
		return reshape2<3, 3> (v);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* ************************************************************************* */
 | 
			
		||||
	FundamentalMatrix estimateFundamentalMatrix(const list<Correspondence>& correspondences) {
 | 
			
		||||
		// Generate entries of A matrix for linear estimation
 | 
			
		||||
		size_t m = correspondences.size();
 | 
			
		||||
		if (m<8) throw invalid_argument("estimateFundamentalMatrix: need at least 8 correspondences");
 | 
			
		||||
		if (m<9) m = 9; // make sure to pad with zeros in minimal case
 | 
			
		||||
		Matrix A = zeros(m,9);
 | 
			
		||||
		size_t i = 0;
 | 
			
		||||
		BOOST_FOREACH(const Correspondence& p, correspondences)
 | 
			
		||||
			Row(A,i++) = toVector(p.first(a) * p.second(b));
 | 
			
		||||
 | 
			
		||||
		// Call DLT and reshape to Homography
 | 
			
		||||
		int rank; double error; Vector v;
 | 
			
		||||
		boost::tie(rank, error, v) = DLT(A);
 | 
			
		||||
		if (rank < 8) throw invalid_argument("estimateFundamentalMatrix: not enough data");
 | 
			
		||||
		return reshape2<3, 3> (v);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* ************************************************************************* */
 | 
			
		||||
	TrifocalTensor estimateTrifocalTensor(const list<Triplet>& triplets) {
 | 
			
		||||
		// Generate entries of A matrix for linear estimation
 | 
			
		||||
		Matrix A;
 | 
			
		||||
		BOOST_FOREACH(const Triplet& p, triplets) {
 | 
			
		||||
			Tensor3<3,3,3> T3 = p.first(a)* (eta(_d,_b,_e) * p.second(d));
 | 
			
		||||
			Tensor2<3,3> T2 = eta(_f,_c,_g) * p.third(f);
 | 
			
		||||
			// Take outer product of rank 3 and rank 2, then swap indices 3,4 for reshape
 | 
			
		||||
			// We get a rank 5 tensor T5(a,_b,_c,_e,_g), where _e and _g index the rows...
 | 
			
		||||
			Matrix Ap = reshape((T3(a,_b,_e) * T2(_c,_g)).swap34(), 9, 27);
 | 
			
		||||
			A = stack(2,&A,&Ap);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Call DLT and reshape to Homography
 | 
			
		||||
		int rank; double error; Vector v;
 | 
			
		||||
		boost::tie(rank, error, v) = DLT(A);
 | 
			
		||||
		if (rank < 26) throw invalid_argument("estimateTrifocalTensor: not enough data");
 | 
			
		||||
		return reshape3<3,3,3>(v);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* ************************************************************************* */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,23 +50,9 @@ namespace gtsam {
 | 
			
		|||
	/** 2D-2D Homography */
 | 
			
		||||
	typedef tensors::Tensor2<3, 3> Homography2;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Estimate homography from point correspondences
 | 
			
		||||
	 * Result is H(_a,b) s.t. p.second(b) = H(_a,b) * p.first(a) for all p
 | 
			
		||||
	 */
 | 
			
		||||
	Homography2 estimateHomography2(
 | 
			
		||||
			const std::list<Correspondence>& correspondences);
 | 
			
		||||
 | 
			
		||||
	/** Fundamental Matrix */
 | 
			
		||||
	typedef tensors::Tensor2<3, 3> FundamentalMatrix;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Estimate fundamental matrix from point correspondences
 | 
			
		||||
	 * Result is F(_a,_b) s.t. H(_a,_b) * p.first(a) * p.second(b) == 0 for all p
 | 
			
		||||
	 */
 | 
			
		||||
	FundamentalMatrix estimateFundamentalMatrix(
 | 
			
		||||
			const std::list<Correspondence>& correspondences);
 | 
			
		||||
 | 
			
		||||
	/** Triplet of points */
 | 
			
		||||
	struct Triplet {
 | 
			
		||||
		Point2h first, second, third;
 | 
			
		||||
| 
						 | 
				
			
			@ -84,12 +70,6 @@ namespace gtsam {
 | 
			
		|||
	/** Trifocal Tensor */
 | 
			
		||||
	typedef tensors::Tensor3<3, 3, 3> TrifocalTensor;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Estimate trifocal Tensor from point triplets
 | 
			
		||||
	 * Result is T(_a,b,c)
 | 
			
		||||
	 */
 | 
			
		||||
	TrifocalTensor estimateTrifocalTensor(const std::list<Triplet>& triplets);
 | 
			
		||||
 | 
			
		||||
	/** 3D Point */
 | 
			
		||||
	typedef tensors::Tensor1<4> Point3h;
 | 
			
		||||
	Point3h point3h(double X, double Y, double Z, double W);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,56 +63,6 @@ TEST( Tensors, FundamentalMatrix)
 | 
			
		|||
	CHECK(l2(a)*p(a) == 0); // p is on line l2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
// Stereo setup, -1,1
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
// t points towards origin
 | 
			
		||||
double left__[4][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { +1, 0, 0 } };
 | 
			
		||||
double right_[4][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { -1, 0, 0 } };
 | 
			
		||||
//double right_[4][3] = { { cos(0.1), -sin(0.1), 0 }, { sin(0.1), cos(0.1), 0 }, { 0, 0, 1 }, { -1, 0, 0 } };
 | 
			
		||||
ProjectiveCamera ML(left__), MR(right_);
 | 
			
		||||
 | 
			
		||||
// Cube
 | 
			
		||||
Point3h P1 = point3h(-1, -1, 3 - 1, 1);
 | 
			
		||||
Point3h P2 = point3h(-1, -1, 3 + 1, 1);
 | 
			
		||||
Point3h P3 = point3h(-1, +1, 3 - 1, 1);
 | 
			
		||||
Point3h P4 = point3h(-1, +1, 3 + 1, 1);
 | 
			
		||||
Point3h P5 = point3h(+1, -1, 3 - 1, 1);
 | 
			
		||||
Point3h P6 = point3h(+1, -1, 3 + 1, 1);
 | 
			
		||||
Point3h P7 = point3h(+1, +1, 3 - 1, 1);
 | 
			
		||||
Point3h P8 = point3h(+1, +1, 3 + 1, 1);
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
TEST( Tensors, FundamentalMatrix2)
 | 
			
		||||
{
 | 
			
		||||
	// The correct fundamental matrix is given by formula 9.1 in HZ 2nd ed., p. 244
 | 
			
		||||
	// F = \hat(e')P'P+
 | 
			
		||||
	// and is very simple
 | 
			
		||||
	double f[3][3] = {{0,0,0}
 | 
			
		||||
	,{0,0,-1}
 | 
			
		||||
	,{0,1,0}
 | 
			
		||||
	};
 | 
			
		||||
	FundamentalMatrix F(f);
 | 
			
		||||
 | 
			
		||||
	// Create a list of correspondences
 | 
			
		||||
	list<Point3h> points;
 | 
			
		||||
	Point3h P9 = point3h(-2,3,4,1);
 | 
			
		||||
	Point3h P10 = point3h(1,1,5,1);
 | 
			
		||||
	points += P1, P2, P3, P4, P5, P6, P7, P8, P9, P10;
 | 
			
		||||
	list<Correspondence> correspondences;
 | 
			
		||||
	BOOST_FOREACH(const Point3h& P, points) {
 | 
			
		||||
		Correspondence p(ML(a,A)*P(A), MR(b,A)*P(A));
 | 
			
		||||
		DOUBLES_EQUAL(0,F(a,b) * p.first(a) * p.second(b),1e-9);
 | 
			
		||||
		correspondences += p;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// let's check it for another arbitrary point
 | 
			
		||||
	Point2h left(ML(a,A)*P9(A)), right(MR(b,A)*P9(A));
 | 
			
		||||
	DOUBLES_EQUAL(0,F(a,b) * left(a) * right(b),1e-9);
 | 
			
		||||
 | 
			
		||||
	FundamentalMatrix actual = estimateFundamentalMatrix(correspondences);
 | 
			
		||||
	CHECK(assert_equivalent(F(a,b),actual(a,b),0.1));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
int main() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -87,27 +87,6 @@ TEST( Homography2, TestCase)
 | 
			
		|||
	CHECK(assert_equality(l1(a), H(a,b)*l2(b)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
TEST( Homography2, Estimate)
 | 
			
		||||
{
 | 
			
		||||
	list<Correspondence> correspondences;
 | 
			
		||||
	correspondences += p1, p2, p3, p4;
 | 
			
		||||
	Homography2 estimatedH = estimateHomography2(correspondences);
 | 
			
		||||
	CHECK(assert_equivalent(H(_a,b),estimatedH(_a,b)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
TEST( Homography2, EstimateReverse)
 | 
			
		||||
{
 | 
			
		||||
	double h[3][3] = { { 1, 0, -4 }, { 0, 1, -5 }, { 0, 0, 1 } };
 | 
			
		||||
	Homography2 reverse(h);
 | 
			
		||||
 | 
			
		||||
	list<Correspondence> correspondences;
 | 
			
		||||
	correspondences += p1.swap(), p2.swap(), p3.swap(), p4.swap();
 | 
			
		||||
	Homography2 estimatedH = estimateHomography2(correspondences);
 | 
			
		||||
	CHECK(assert_equality(reverse(_a,b),estimatedH(_a,b)*(1.0/estimatedH(2,2))));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
/**
 | 
			
		||||
 * Computes the homography H(I,_T) from template to image
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,178 +0,0 @@
 | 
			
		|||
/* ----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
 * GTSAM Copyright 2010, Georgia Tech Research Corporation, 
 | 
			
		||||
 * Atlanta, Georgia 30332-0415
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
 | 
			
		||||
 | 
			
		||||
 * See LICENSE for the license information
 | 
			
		||||
 | 
			
		||||
 * -------------------------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * testTrifocal.cpp
 | 
			
		||||
 * @brief trifocal tensor estimation
 | 
			
		||||
 * Created on: Feb 9, 2010
 | 
			
		||||
 * @author: Frank Dellaert
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <boost/foreach.hpp>
 | 
			
		||||
#include <boost/assign/std/list.hpp> // for operator +=
 | 
			
		||||
using namespace boost::assign;
 | 
			
		||||
 | 
			
		||||
#include <gtsam/CppUnitLite/TestHarness.h>
 | 
			
		||||
 | 
			
		||||
#include <gtsam/geometry/tensors.h>
 | 
			
		||||
#include <gtsam/geometry/tensorInterface.h>
 | 
			
		||||
#include <gtsam/geometry/projectiveGeometry.h>
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
using namespace gtsam;
 | 
			
		||||
using namespace tensors;
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
// Indices
 | 
			
		||||
 | 
			
		||||
Index<3, 'a'> a, _a;
 | 
			
		||||
Index<3, 'b'> b, _b;
 | 
			
		||||
Index<3, 'c'> c, _c;
 | 
			
		||||
Index<3, 'd'> d, _d;
 | 
			
		||||
Index<3, 'e'> e, _e;
 | 
			
		||||
Index<3, 'f'> f, _f;
 | 
			
		||||
Index<3, 'g'> g, _g;
 | 
			
		||||
 | 
			
		||||
Index<4, 'A'> A;
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
// 3 Camera setup in trifocal stereo setup, -1,0,1
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
double left__[4][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { -1, 0, 0 } };
 | 
			
		||||
double middle[4][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { +0, 0, 0 } };
 | 
			
		||||
double right_[4][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { +1, 0, 0 } };
 | 
			
		||||
ProjectiveCamera ML(left__), MM(middle), MR(right_);
 | 
			
		||||
 | 
			
		||||
// Cube
 | 
			
		||||
Point3h P1 = point3h(-1, -1, 3 - 1, 1);
 | 
			
		||||
Point3h P2 = point3h(-1, -1, 3 + 1, 1);
 | 
			
		||||
Point3h P3 = point3h(-1, +1, 3 - 1, 1);
 | 
			
		||||
Point3h P4 = point3h(-1, +1, 3 + 1, 1);
 | 
			
		||||
Point3h P5 = point3h(+1, -1, 3 - 1, 1);
 | 
			
		||||
Point3h P6 = point3h(+1, -1, 3 + 1, 1);
 | 
			
		||||
Point3h P7 = point3h(+1, +1, 3 - 1, 1);
 | 
			
		||||
Point3h P8 = point3h(+1, +1, 3 + 1, 1);
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
// Manohar's homework
 | 
			
		||||
TEST(Tensors, TrifocalTensor)
 | 
			
		||||
{
 | 
			
		||||
	// Checked with MATLAB !
 | 
			
		||||
	double t[3][3][3] = {
 | 
			
		||||
		{ { -0.301511, 0, 0 }, { 0, -0.603023, 0 }, { 0, 0,-0.603023 } },
 | 
			
		||||
		{ {  0, 0.301511, 0 }, { 0, 0, 0 }, { 0, 0, 0 } },
 | 
			
		||||
		{ {  0, 0, 0.301511 }, { 0, 0, 0 }, { 0, 0, 0 } }
 | 
			
		||||
	};
 | 
			
		||||
	TrifocalTensor T(t);
 | 
			
		||||
	//print(T(a,b,c));
 | 
			
		||||
 | 
			
		||||
	list<Point3h> points;
 | 
			
		||||
	points += P1, P2, P3, P4, P5, P6, P7, P8;
 | 
			
		||||
 | 
			
		||||
	Eta3 eta;
 | 
			
		||||
 | 
			
		||||
	list<Triplet> triplets;
 | 
			
		||||
	double data[3][3] = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } };
 | 
			
		||||
	Tensor2<3,3> zero(data);
 | 
			
		||||
	BOOST_FOREACH(const Point3h& P, points) {
 | 
			
		||||
		// form triplet
 | 
			
		||||
		Triplet p(ML(a,A)*P(A), MM(b,A)*P(A), MR(c,A)*P(A));
 | 
			
		||||
		// check trifocal constraint
 | 
			
		||||
		Tensor2<3,3> T1 = T(_a,b,c) * p.first(a);
 | 
			
		||||
		Tensor2<3,3> T2 = eta(_d,_b,_e) * p.second(d);
 | 
			
		||||
		Tensor2<3,3> T3 = eta(_f,_c,_g) * p.third(f);
 | 
			
		||||
		CHECK(assert_equality(zero(_e,_g), (T1(b,c) * T2(_b,_e)) * T3(_c,_g),1e-4));
 | 
			
		||||
		triplets += p;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// We will form the rank 5 tensor by multiplying a rank 3 and rank 2
 | 
			
		||||
	// Let's check the answer for the first point:
 | 
			
		||||
	Triplet p = triplets.front();
 | 
			
		||||
 | 
			
		||||
	// This checks the rank 3 (with answer checked in MATLAB);
 | 
			
		||||
	double matlab3[3][3][3] = {
 | 
			
		||||
		{{ -0, -0, 0}, { 4, 2, -4}, { 2, 1, -2}},
 | 
			
		||||
		{{ -4, -2, 4}, {-0, -0, 0}, {-2, -1, 2}},
 | 
			
		||||
		{{ -2, -1, 2}, { 2, 1, -2}, {-0, -0, 0}}
 | 
			
		||||
	};
 | 
			
		||||
	Tensor3<3,3,3> expected3(matlab3);
 | 
			
		||||
	CHECK(assert_equality(expected3(a,_b,_e), p.first(a)* (eta(_d,_b,_e) * p.second(d))));
 | 
			
		||||
 | 
			
		||||
	// This checks the rank 2 (with answer checked in MATLAB);
 | 
			
		||||
	double matlab2[3][3] = { {0, -2, -1}, {2, 0, 0}, {1, 0, 0}};
 | 
			
		||||
	Tensor2<3,3> expected2(matlab2);
 | 
			
		||||
	CHECK(assert_equality(expected2(_c,_g), eta(_f,_c,_g) * p.third(f)));
 | 
			
		||||
 | 
			
		||||
	TrifocalTensor actual = estimateTrifocalTensor(triplets);
 | 
			
		||||
 | 
			
		||||
	//print(actual(a,b,c));
 | 
			
		||||
	CHECK(assert_equality(T(_a,b,c),actual(_a,b,c),1e-6));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(Tensors, TrifocalTensor1){
 | 
			
		||||
	// Manually clicked points
 | 
			
		||||
	// Points in frame1
 | 
			
		||||
	// 339   336   281    51   367   265   135
 | 
			
		||||
	// 152   344   246   210    76   248   246
 | 
			
		||||
	// Points in frame2
 | 
			
		||||
	// 380   381   311   108   395   294   161
 | 
			
		||||
	// 148   340   242   208    73   243   242
 | 
			
		||||
	// Points in frame3
 | 
			
		||||
	// 440   441   360   181   444   344   207
 | 
			
		||||
	// 151   343   246   212    74   247   245
 | 
			
		||||
 | 
			
		||||
	Triplet p1(point2h(339,152,1), point2h(380,148,1), point2h(440,151,1));
 | 
			
		||||
	Triplet p2(point2h(336,344,1), point2h(381,340,1), point2h(441,343,1));
 | 
			
		||||
	Triplet p3(point2h(281,246,1), point2h(311,242,1), point2h(360,246,1));
 | 
			
		||||
	Triplet p4(point2h(51,210,1 ), point2h(108,208,1), point2h(181,212,1));
 | 
			
		||||
	Triplet p5(point2h(367,76,1 ), point2h(395,73,1 ), point2h(444,74,1) );
 | 
			
		||||
	Triplet p6(point2h(265,248,1), point2h(294,243,1), point2h(344,247,1));
 | 
			
		||||
	Triplet p7(point2h(135,246,1), point2h(161,242,1), point2h(207,245,1));
 | 
			
		||||
	list<Triplet> triplets;
 | 
			
		||||
	triplets += p1, p2, p3, p4, p5, p6, p7;
 | 
			
		||||
 | 
			
		||||
	// Checked with MATLAB !
 | 
			
		||||
	/*double t[3][3][3] = {
 | 
			
		||||
	{ {	-0.0145,0.0081,0.0000}, {-0.0004,-0.0180,0.0000}, {0.2334,-0.6283,-0.0230}},
 | 
			
		||||
	{ {	-0.0162,-0.0001,0.0000}, {0.0049,-0.0075,0.0000}, {0.7406,0.0209,-0.0140}},
 | 
			
		||||
	{ {	-0.0001,-0.0000,-0.0000}, {-0.0000,-0.0001,0.0000}, {0.0096,0.0063,-0.0000}}
 | 
			
		||||
	};*/
 | 
			
		||||
	double t[3][3][3] = {
 | 
			
		||||
	{ {	0.0145,0.0004,-0.2334}, {-0.0081,0.0180,0.6283}, {0.0000,0.0000,0.0230}},
 | 
			
		||||
	{ {	0.0162,-0.0049,-0.7406}, {0.0001,-0.0075,-0.0209}, {0.0000,0.0000,0.0140}},
 | 
			
		||||
	{ {	0.0001,-0.0000,-0.0096}, {0.0000,0.0001,-0.0063}, {0.0000,-0.0000,-0.0000}}
 | 
			
		||||
	};
 | 
			
		||||
	TrifocalTensor T(t);
 | 
			
		||||
 | 
			
		||||
	TrifocalTensor actual = estimateTrifocalTensor(triplets);
 | 
			
		||||
 | 
			
		||||
	Eta3 eta;
 | 
			
		||||
	double data[3][3] = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } };
 | 
			
		||||
	Tensor2<3,3> zero(data);
 | 
			
		||||
 | 
			
		||||
	BOOST_FOREACH(const Triplet& t, triplets) {
 | 
			
		||||
		Tensor2<3,3> T1 = actual(_a,b,c) * t.first(a);
 | 
			
		||||
		Tensor2<3,3> T2 = eta(_d,_b,_e) * t.second(d);
 | 
			
		||||
		Tensor2<3,3> T3 = eta(_f,_c,_g) * t.third(f);
 | 
			
		||||
		CHECK(assert_equality(zero(_e,_g), (T1(b,c) * T2(_b,_e)) * T3(_c,_g),1e-2));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	CHECK(assert_equality(T(_a,b,c), actual(_a,b,c),1e-1));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
int main() {
 | 
			
		||||
	TestResult tr;
 | 
			
		||||
	return TestRegistry::runAllTests(tr);
 | 
			
		||||
}
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -125,13 +125,6 @@ namespace gtsam {
 | 
			
		|||
			 */
 | 
			
		||||
			static shared_ptr Covariance(const Matrix& covariance, bool smart=false);
 | 
			
		||||
 | 
			
		||||
			/**
 | 
			
		||||
			 * A Gaussian noise model created by specifying an information matrix.
 | 
			
		||||
			 */
 | 
			
		||||
			static shared_ptr Information(const Matrix& Q)  {
 | 
			
		||||
				return shared_ptr(new Gaussian(Q.size1(),square_root_positive(Q)));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			virtual void print(const std::string& name) const;
 | 
			
		||||
			virtual bool equals(const Base& expected, double tol) const;
 | 
			
		||||
			virtual Vector whiten(const Vector& v) const;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,7 +55,7 @@ TEST(NoiseModel, constructors)
 | 
			
		|||
	vector<Gaussian::shared_ptr> m;
 | 
			
		||||
	m.push_back(Gaussian::SqrtInformation(R));
 | 
			
		||||
	m.push_back(Gaussian::Covariance(Sigma));
 | 
			
		||||
	m.push_back(Gaussian::Information(Q));
 | 
			
		||||
	//m.push_back(Gaussian::Information(Q));
 | 
			
		||||
	m.push_back(Diagonal::Sigmas(Vector_(3, sigma, sigma, sigma)));
 | 
			
		||||
	m.push_back(Diagonal::Variances(Vector_(3, var, var, var)));
 | 
			
		||||
	m.push_back(Diagonal::Precisions(Vector_(3, prc, prc, prc)));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue