/** * Extracts the epipoles from the trifocal tensor. Extracted epipoles will have a norm of 1 as an * artifact of using SVD. * * @param tensor Input: Trifocal tensor. Not Modified * @param e2 Output: Epipole in image 2. Homogeneous coordinates. Modified * @param e3 Output: Epipole in image 3. Homogeneous coordinates. Modified */ public void process(TrifocalTensor tensor, Point3D_F64 e2, Point3D_F64 e3) { svd.decompose(tensor.T1); SingularOps.nullVector(svd, true, v1); SingularOps.nullVector(svd, false, u1); svd.decompose(tensor.T2); SingularOps.nullVector(svd, true, v2); SingularOps.nullVector(svd, false, u2); svd.decompose(tensor.T3); SingularOps.nullVector(svd, true, v3); SingularOps.nullVector(svd, false, u3); for (int i = 0; i < 3; i++) { U.set(i, 0, u1.get(i)); U.set(i, 1, u2.get(i)); U.set(i, 2, u3.get(i)); V.set(i, 0, v1.get(i)); V.set(i, 1, v2.get(i)); V.set(i, 2, v3.get(i)); } svd.decompose(U); SingularOps.nullVector(svd, false, tempE); e2.set(tempE.get(0), tempE.get(1), tempE.get(2)); svd.decompose(V); SingularOps.nullVector(svd, false, tempE); e3.set(tempE.get(0), tempE.get(1), tempE.get(2)); }
@Override public void encode(CalibratedPoseAndPoint model, double[] param) { int paramIndex = 0; // first decode the transformation for (int i = 0; i < numViews; i++) { // don't encode if it is already known if (knownView[i]) continue; Se3_F64 se = model.getWorldToCamera(i); // force the "rotation matrix" to be an exact rotation matrix // otherwise Rodrigues will have issues with the noise if (!svd.decompose(se.getR())) throw new RuntimeException("SVD failed"); DenseMatrix64F U = svd.getU(null, false); DenseMatrix64F V = svd.getV(null, false); CommonOps.multTransB(U, V, R); // extract Rodrigues coordinates RotationMatrixGenerator.matrixToRodrigues(R, rotation); param[paramIndex++] = rotation.unitAxisRotation.x * rotation.theta; param[paramIndex++] = rotation.unitAxisRotation.y * rotation.theta; param[paramIndex++] = rotation.unitAxisRotation.z * rotation.theta; Vector3D_F64 T = se.getT(); param[paramIndex++] = T.x; param[paramIndex++] = T.y; param[paramIndex++] = T.z; } for (int i = 0; i < numPoints; i++) { Point3D_F64 p = model.getPoint(i); param[paramIndex++] = p.x; param[paramIndex++] = p.y; param[paramIndex++] = p.z; } }
/** * Computes a basis (the principle components) from the most dominant eigenvectors. * * @param numComponents Number of vectors it will use to describe the data. Typically much smaller * than the number of elements in the input vector. */ public void computeBasis(int numComponents) { if (numComponents > A.getNumCols()) throw new IllegalArgumentException("More components requested that the data's length."); if (sampleIndex != A.getNumRows()) throw new IllegalArgumentException("Not all the data has been added"); if (numComponents > sampleIndex) throw new IllegalArgumentException( "More data needed to compute the desired number of components"); this.numComponents = numComponents; // compute the mean of all the samples for (int i = 0; i < A.getNumRows(); i++) { for (int j = 0; j < mean.length; j++) { mean[j] += A.get(i, j); } } for (int j = 0; j < mean.length; j++) { mean[j] /= A.getNumRows(); } // subtract the mean from the original data for (int i = 0; i < A.getNumRows(); i++) { for (int j = 0; j < mean.length; j++) { A.set(i, j, A.get(i, j) - mean[j]); } } // Compute SVD and save time by not computing U SingularValueDecomposition<DenseMatrix64F> svd = DecompositionFactory.svd(A.numRows, A.numCols, false, true, false); if (!svd.decompose(A)) throw new RuntimeException("SVD failed"); V_t = svd.getV(null, true); DenseMatrix64F W = svd.getW(null); // Singular values are in an arbitrary order initially SingularOps.descendingOrder(null, false, W, V_t, true); // strip off unneeded components and find the basis V_t.reshape(numComponents, mean.length, true); }