49 #include <QSharedPointer>
57 #include <Eigen/Dense>
58 #include <Eigen/Eigenvalues>
59 #include <Eigen/Geometry>
65 using namespace MNELIB;
66 using namespace RTPROCESSINGLIB;
67 using namespace Eigen;
68 using namespace FIFFLIB;
75 const Eigen::MatrixXf& matPointCloud,
81 const VectorXf& vecWeitgths)
88 if(matPointCloud.rows() == 0){
89 qWarning() <<
"[RTPROCESSINGLIB::icp] Passed point cloud is empty.";
94 int iNP = matPointCloud.rows();
95 float fMSEPrev = 0.0f;
98 MatrixXf matP0 = matPointCloud;
99 MatrixXf matPk = matP0;
100 MatrixXf matYk(matPk.rows(),matPk.cols());
101 MatrixXf matDiff = matYk;
102 VectorXf vecSE(matDiff.rows());
112 for(
int iIter = 0; iIter < iMaxIter; ++iIter) {
115 if(!mneSurfacePoints->mne_find_closest_on_surface(matPk, iNP, matYk, vecNearest, vecDist)) {
116 qWarning() <<
"[RTPROCESSINGLIB::icp] mne_find_closest_on_surface was not sucessfull.";
121 if(!
fitMatchedPoints(matP0, matYk, matTrans, fScale, bScale, vecWeitgths)) {
122 qWarning() <<
"[RTPROCESSINGLIB::icp] point cloud registration not succesfull";
126 transICP.
trans = matTrans;
130 vecDist = vecDist.cwiseProduct(vecDist);
131 fMSE = vecDist.sum() / iNP;
132 fRMSE = std::sqrt(fMSE);
134 if(std::sqrt(std::fabs(fMSE - fMSEPrev)) < fTol) {
135 transFromTo = transICP;
136 qInfo() <<
"[RTPROCESSINGLIB::icp] ICP was succesfull and exceeded after " << iIter +1 <<
" Iterations with RMSE dist: " << fRMSE * 1000 <<
" mm.";
140 qInfo() <<
"[RTPROCESSINGLIB::icp] ICP iteration " << iIter + 1 <<
" with RMSE: " << fRMSE * 1000 <<
" mm.";
142 transFromTo = transICP;
144 qWarning() <<
"[RTPROCESSINGLIB::icp] Maximum number of " << iMaxIter <<
" Iterations exceeded with RMSE: " << fRMSE * 1000 <<
" mm.";
151 const MatrixXf& matDstPoint,
152 Eigen::Matrix4f& matTrans,
155 const VectorXf& vecWeitgths)
165 MatrixXf matP = matSrcPoint;
166 MatrixXf matX = matDstPoint;
167 VectorXf vecW = vecWeitgths;
174 Matrix4f matQ = Matrix4f::Identity(4,4);
175 Matrix3f matScale = Matrix3f::Identity(3,3);
176 Matrix3f matRot = Matrix3f::Identity(3,3);
182 if(matSrcPoint.size() != matDstPoint.size()) {
183 qWarning() <<
"[RTPROCESSINGLIB::fitMatched] Point clouds do not match.";
188 if(vecWeitgths.isZero()) {
189 vecMuP = matP.colwise().mean();
190 vecMuX = matX.colwise().mean();
191 matDot = matP.transpose() * matX;
192 matDot = matDot / matP.rows();
194 vecW = vecWeitgths / vecWeitgths.sum();
195 vecMuP = vecW.transpose() * matP;
196 vecMuX = vecW.transpose() * matX;
198 MatrixXf matXWeighted = matX;
199 for(
int i = 0; i < (vecW.size()); ++i) {
200 matXWeighted.row(i) = matXWeighted.row(i) * vecW(i);
202 matDot = matP.transpose() * (matXWeighted);
206 matSigmaPX = matDot - (vecMuP * vecMuX.transpose());
207 matAij = matSigmaPX - matSigmaPX.transpose();
208 vecDelta(0) = matAij(1,2); vecDelta(1) = matAij(2,0); vecDelta(2) = matAij(0,1);
209 fTrace = matSigmaPX.trace();
211 matQ.block(0,1,1,3) = vecDelta.transpose();
212 matQ.block(1,0,3,1) = vecDelta;
213 matQ.block(1,1,3,3) = matSigmaPX + matSigmaPX.transpose() - fTrace * MatrixXf::Identity(3,3);
216 SelfAdjointEigenSolver<MatrixXf> es(matQ);
217 Vector4f vecEigVec = es.eigenvectors().col(matQ.cols()-1);
220 Quaternionf quatRot(vecEigVec(0),vecEigVec(1),vecEigVec(2),vecEigVec(3));
222 matRot = quatRot.matrix();
226 MatrixXf matDevX = matX.rowwise() - vecMuX.transpose();
227 MatrixXf matDevP = matP.rowwise() - vecMuP.transpose();
228 matDevX = matDevX.cwiseProduct(matDevX);
229 matDevP = matDevP.cwiseProduct(matDevP);
231 if(!vecWeitgths.isZero()) {
232 for(
int i = 0; i < (vecW.size()); ++i) {
233 matDevX.row(i) = matDevX.row(i) * vecW(i);
234 matDevP.row(i) = matDevP.row(i) * vecW(i);
238 fScale = std::sqrt(matDevX.sum() / matDevP.sum());
243 vecTrans = vecMuX - fScale * matRot * vecMuP;
246 matTrans.block<3,3>(0,0) = matRot;
247 matTrans.block<3,1>(0,3) = vecTrans;
248 matTrans(3,3) = 1.0f;
249 matTrans.block<1,3>(3,0) = MatrixXf::Zero(1,3);
256 const MatrixXf& matPointCloud,
259 MatrixXf& matTakePoint,
263 int iNP = matPointCloud.rows();
264 MatrixXf matP = matPointCloud;
265 MatrixXf matYk(matPointCloud.rows(),matPointCloud.cols());
276 if(!mneSurfacePoints->mne_find_closest_on_surface(matP, iNP, matYk, vecNearest, vecDist)) {
277 qWarning() <<
"[RTPROCESSINGLIB::icp] mne_find_closest_on_surface was not sucessfull.";
281 for(
int i = 0; i < vecDist.size(); ++i) {
282 if(std::fabs(vecDist(i)) < fMaxDist) {
283 vecTake.conservativeResize(vecTake.size()+1);
284 vecTake(vecTake.size()-1) = i;
285 matTakePoint.conservativeResize(matTakePoint.rows()+1,3);
286 matTakePoint.row(matTakePoint.rows()-1) = matPointCloud.row(i);
292 qInfo() <<
"[RTPROCESSINGLIB::discardOutliers] " << iDiscarded <<
"digitizers discarded.";