Commit ff3a18ae authored by Emmanuel Promayon's avatar Emmanuel Promayon

Merge branch 'feature/improved-ICP' into 'develop'

NEW feature: ICP parameter GUI + show algorithm information at the end

See merge request !125
parents bc64b886 30c2b6b7
......@@ -37,10 +37,11 @@
using namespace camitk;
// -------------------- constructor --------------------
ICPRegistration::ICPRegistration(camitk::ActionExtension* ext) : Action(ext) {
this->setName("ICP Registration");
this->setDescription(QString(tr("Iterative Closest Point algorithm bewteen two mesh.<br/>")) +
this->setDescription(QString(tr("Iterative Closest Point algorithm between two mesh.<br/>")) +
QString(tr("At least two mesh components must be selected :")) +
QString("<ul>") +
QString(tr("<li> The first one is the source mesh (the one to be registered) </li>")) +
......@@ -48,17 +49,33 @@ ICPRegistration::ICPRegistration(camitk::ActionExtension* ext) : Action(ext) {
QString("</ul>"));
this->setComponent("MeshComponent");
this->setFamily("Mesh Processing");
this->addTag(tr("registration"));
distanceMeasureType = RMS;
Property* numberOfIterationsProperty = new Property(tr("Number of iterations"), 20, tr("The number of iteration of the ICP algorithm."), "");
addParameter(numberOfIterationsProperty);
Property* distanceMesureTypeProperty = new Property(tr("Distance mesure type"), RMS, tr("The distance mesure type use by the ICP algorithm."), "");
this->addTag(tr("Registration"));
this->addTag(tr("CPI"));
addParameter(new Property(tr("Maximum Number Of Iterations"), 50, tr("The maximum number of iterations of the ICP algorithm."), ""));
addParameter(new Property(tr("Maximum Number Of Landmarks"), 200, tr("The maximum number of landmarks sampled in your dataset. If your dataset is dense, then you will typically not need all the points to compute the ICP transform. The default is 200."), ""));
Property* distanceMesureTypeProperty = new Property(tr("Distance Mesure Type"), RMS, tr("The distance mesure type used by the ICP algorithm. Specify the mean distance mode. The RMS mode is the square root of the average of the sum of squares of the closest point distances. The Absolute Value mode is the mean of the sum of absolute values of the closest point distances."), "");
distanceMesureTypeProperty->setEnumTypeName("DistanceMeasureType", this);
addParameter(distanceMesureTypeProperty);
Property* transformTypeProperty = new Property(tr("Transform Type"), Similarity, tr("The landmark transformation type used by the ICP agorithm. Set the number of degrees of freedom to constrain the solution to: Rigidbody (rotation and translation only), Similarity (rotation, translation and isotropic scaling) or Affine (collinearity is preserved, ratios of distances along a line are preserved."), "");
transformTypeProperty->setEnumTypeName("LandmarkTransformType", this);
addParameter(transformTypeProperty);
addParameter(new Property(tr("Match Centroid First"), false, tr("Starts the process by translating source centroid to target centroid."), ""));
addParameter(new Property(tr("Check Mean Distance"), false, tr("Force the algorithm to check the mean distance between two iterations. This is slower but generally more accurate."), ""));
Property* maxMeanDistanceProperty = new Property(tr("Maximum Mean Distance"), 0.01, tr("The maximum mean distance between two iterations. If the mean distance is lower than this, the convergence stops."), "");
maxMeanDistanceProperty->setAttribute("decimals", 5);
maxMeanDistanceProperty->setAttribute("minimum", 0);
maxMeanDistanceProperty->setAttribute("singleStep", 0.001);
addParameter(maxMeanDistanceProperty);
}
// -------------------- apply --------------------
camitk::Action::ApplyStatus ICPRegistration::apply() {
// set waiting cursor and status bar
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
......@@ -92,19 +109,32 @@ camitk::Action::ApplyStatus ICPRegistration::apply() {
vtkSmartPointer<vtkIterativeClosestPointTransform> icp = vtkSmartPointer<vtkIterativeClosestPointTransform>::New();
icp->SetSource(sourceMesh->getPointSet());
icp->SetTarget(targetMesh->getPointSet());
icp->GetLandmarkTransform()->SetModeToRigidBody();
icp->SetMaximumNumberOfIterations(property("Number of iterations").toInt());
switch (property("Distance mesure type").toInt()) {
case RMS :
icp->SetMeanDistanceModeToRMS();
break;
icp->SetMaximumNumberOfIterations(property("Maximum Number Of Iterations").toInt());
icp->SetMaximumNumberOfLandmarks(property("Maximum Number Of Landmarks").toInt());
switch (property("Distance Mesure Type").toInt()) {
case ABS :
icp->SetMeanDistanceModeToAbsoluteValue();
break;
case RMS :
default:
icp->SetMeanDistanceModeToRMS();
break;
}
switch(property("Transform Type").toInt()) {
case Rigidbody:
icp->GetLandmarkTransform()->SetModeToRigidBody();
break;
case Affine:
icp->GetLandmarkTransform()->SetModeToAffine();
break;
case Similarity:
default:
icp->GetLandmarkTransform()->SetModeToSimilarity();
break;
}
icp->SetStartByMatchingCentroids(property("Match Centroid First").toBool());
icp->SetCheckMeanDistance(property("Check Mean Distance").toBool());
icp->SetMaximumMeanDistance(property("Maximum Mean Distance").toDouble());
icp->AddObserver(vtkCommand::ProgressEvent, progressCallback);
icp->Modified();
icp->Update();
......@@ -121,6 +151,18 @@ camitk::Action::ApplyStatus ICPRegistration::apply() {
icpTransformFilter->AddObserver(vtkCommand::ProgressEvent, progressCallback);
icpTransformFilter->Update();
// get the algorithm output information
vtkSmartPointer<vtkMatrix4x4> registrationMatrix = icp->GetMatrix();
QStringList stringMatrix;
for (int i=0;i<4;i++) {
for (int j=0;j<4;j++) {
stringMatrix << QString::number(icp->GetMatrix()->GetElement(i,j));
}
}
int numberOfIterations = icp->GetNumberOfIterations();
double meanDistance = icp->GetMeanDistance();
CAMITK_TRACE("ICP algorithm information: " + QString::number(numberOfIterations) + " iterations, mean distance = " + QString::number(meanDistance) + ", transform: [" + stringMatrix.join(", ") + "]")
// create a new MeshComponent for the result
new MeshComponent(icpTransformFilter->GetOutput(), sourceMesh->getName() + "_registered_mesh");
......
......@@ -43,12 +43,21 @@ class ICPRegistration : public camitk::Action {
public:
/// \enum DistanceMeasureType specify the mean distance mode
enum DistanceMeasureType {
RMS,
ABS
};
RMS, ///< The RMS mode is the square root of the average of the sum of squares of the closest point distances
ABS ///< The Absolute Value mode is the mean of the sum of absolute values of the closest point distances.
};
Q_ENUMS(DistanceMeasureType)
/// \enum LandmarkTransformType Set the number of degrees of freedom to constrain the solution to.
enum LandmarkTransformType {
Rigidbody, ///< rotation and translation only.
Similarity, ///< rotation, translation and isotropic scaling.
Affine ///< collinearity is preserved, ratios of distances along a line are preserved
};
Q_ENUMS(LandmarkTransformType)
public:
/// the constructor
......@@ -57,18 +66,14 @@ public:
/// the destructor
virtual ~ICPRegistration() = default;
public slots :
/// method applied when the action is called
virtual ApplyStatus apply();
protected :
DistanceMeasureType distanceMeasureType;
};
Q_DECLARE_METATYPE(ICPRegistration::DistanceMeasureType)
Q_DECLARE_METATYPE(ICPRegistration::LandmarkTransformType)
#endif // ICP_REGISTRATION_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment