void Reconstruction::ReconstructPlanarUnconstrOnce( const mat& matchesInit, LaplacianMesh& resMesh) { // Input check if (matchesInit.n_rows == 0) { return; } Timer timer; double meanZ = mean(resMesh.GetVertexCoords().col(2)); // scale wr due to distance : 0 - 200 double wr = this->wrInit * (meanZ / 200.); // Currently used regularization weight // double radius = this->radiusInit; // Currently used radius of the estimator // vec reprojErrors; // Reprojection errors // First, we need to build the correspondent matrix with all given matches to avoid re-computation this->buildCorrespondenceMatrix(matchesInit); // Then compute MPinit. Function reconstructPlanarUnconstr() will use part of MPinit w.r.t currently used matches this->MPinit = this->Minit * this->refMesh.GetBigParamMat(); uvec matchesInitIdxs = linspace<uvec>(0, matchesInit.n_rows-1, matchesInit.n_rows); // Currently used matches represented by their indices. Initially, use all matches: [0,1,2..n-1] this->reconstructPlanarUnconstr(matchesInitIdxs, wr, resMesh); }
void Reconstruction::updateMesh( LaplacianMesh& resMesh ) { const mat& paramMat = this->refMesh.GetParamMatrix(); mat matC = TraceManager::imageDatabase->getRefCamera().ReprojectPoints(reshape(c, refMesh.GetNCtrlPoints(), 2)); // mat matC = reshape(c, refMesh.GetNCtrlPoints(), 3); // Update vertex coordinates resMesh.SetVertexCoords(paramMat * matC); // Resulting mesh yields a correct projection on image but it does not preserve lengths. // So we need to compute the scale factor and multiply with matC // Determine on which side the mesh lies: -Z or Z double meanZ = mean(resMesh.GetVertexCoords().col(2)); int globalSign = meanZ > 0 ? 1 : -1; const vec& resMeshEdgeLens = resMesh.ComputeEdgeLengths(); const vec& refMeshEdgeLens = refMesh.GetEdgeLengths(); // this seems no difference if do not scale the points? double scale = globalSign * norm(refMeshEdgeLens, 2) / norm(resMeshEdgeLens, 2); // Update vertex coordinates resMesh.SetVertexCoords(scale * paramMat * matC); }
void Reconstruction::reconstructPlanarUnconstr( const uvec& matchIdxs, double wr, LaplacianMesh& resMesh ) { Timer timer; const mat& paramMat = this->refMesh.GetParamMatrix(); // Parameterization matrix // Build the matrix MPwAP = [MP; wr*AP] and compute: (MPwAP)' * (MPwAP) this->computeCurrentMatrices( matchIdxs, wr); // --------------- Eigen value decomposition -------------------------- mat V; vec s; timer.start(); // 此处最小的特征值只是其中一个解,在下面会对这个解进行Scale使得它的边长和ref mesh的边长相等 eig_sym(s, V, this->MPwAPtMPwAP); timer.stop(); // cout << "Eigen(): " << timer.getElapsedTimeInMilliSec() << " ms"<< endl; const vec& c = V.col(0); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mat matC = reshape(c, refMesh.GetNCtrlPoints(), 3); // Update vertex coordinates resMesh.SetVertexCoords(paramMat * matC); // Resulting mesh yields a correct projection on image but it does not preserve lengths. // So we need to compute the scale factor and multiply with matC // Determine on which side the mesh lies: -Z or Z double meanZ = mean(resMesh.GetVertexCoords().col(2)); int globalSign = meanZ > 0 ? 1 : -1; const vec& resMeshEdgeLens = resMesh.ComputeEdgeLengths(); const vec& refMeshEdgeLens = refMesh.GetEdgeLengths(); double scale = globalSign * norm(refMeshEdgeLens, 2) / norm(resMeshEdgeLens, 2); // Update vertex coordinates resMesh.SetVertexCoords(scale * paramMat * matC); }
void Reconstruction::ReconstructPlanarUnconstrIter( const mat& matchesInit, LaplacianMesh& resMesh, uvec& inlierMatchIdxs ) { // Input check if (matchesInit.n_rows == 0) { inlierMatchIdxs.resize(0); return; } Timer timer; double wr = this->wrInit; // Currently used regularization weight double radius = this->radiusInit; // Currently used radius of the estimator vec reprojErrors; // Reprojection errors // First, we need to build the correspondent matrix with all given matches to avoid re-computation this->buildCorrespondenceMatrix(matchesInit); // Then compute MPinit. Function reconstructPlanarUnconstr() will use part of MPinit w.r.t currently used matches this->MPinit = this->Minit * this->refMesh.GetBigParamMat(); uvec matchesInitIdxs = linspace<uvec>(0, matchesInit.n_rows-1, matchesInit.n_rows); // Currently used matches represented by their indices. Initially, use all matches: [0,1,2..n-1] inlierMatchIdxs = matchesInitIdxs; for (int i = 0; i < nUncstrIters; i++) { // If it is the final iteration, break and don't update "inlierMatchIdxs" or "weights", "radius" if (i == nUncstrIters - 1) { double meanZ = mean(resMesh.GetVertexCoords().col(2)); this->reconstructPlanarUnconstr(inlierMatchIdxs, this->wrInit * (meanZ / 200.), resMesh); //cout << "Current radius: " << radius << endl; //cout << "Current wr: " << wr << endl; //Reconstruction::computeCurrentMatrices( currentMatchIdxs, 325 ); // For Fern break; } else { this->reconstructPlanarUnconstr(inlierMatchIdxs, wr, resMesh); } // Otherwise, remove outliers int iterTO = nUncstrIters - 2; if (i >= iterTO) reprojErrors = this->computeReprojectionErrors(resMesh, matchesInit, matchesInitIdxs); else reprojErrors = this->computeReprojectionErrors(resMesh, matchesInit, inlierMatchIdxs); uvec idxs = find( reprojErrors < radius ); if ( idxs.n_elem == 0 ) break; if (i >= iterTO) inlierMatchIdxs = matchesInitIdxs.elem( idxs ); else inlierMatchIdxs = inlierMatchIdxs.elem( idxs ); // Update parameters wr = wr / Reconstruction::ROBUST_SCALE; radius = radius / Reconstruction::ROBUST_SCALE; } }