10 #include <Utils/cc2sm.h>
11 #include <Utils/sm2cc.h>
13 #include "PclUtils/PCLModules.h"
24 #include <QMainWindow>
32 tr(
"Correspondence Matching"),
33 tr(
"Correspondence Matching"),
34 tr(
"Correspondence Matching from clouds"),
35 ":/toolbar/PclAlgorithms/icons/correspondence_grouping.png")),
37 m_sceneCloud(nullptr),
38 m_useVoxelGrid(false),
43 m_modelSearchRadius(0.02f),
44 m_sceneSearchRadius(0.03f),
45 m_shotDescriptorRadius(0.03f),
46 m_normalKSearch(10.0f),
47 m_consensusResolution(0.01f),
48 m_gcMinClusterSize(20.0f),
50 m_houghBinSize(0.01f),
51 m_houghThreshold(5.0f) {}
61 if (have_cloud != 1)
return -11;
115 if (!cloud1 && !cloud2) {
122 assert(cloud1 != cloud2);
138 typedef PointT PointType;
139 typedef NormalT NormalType;
140 typedef pcl::ReferenceFrame RFType;
141 typedef pcl::SHOT352 DescriptorType;
143 std::vector<std::vector<ccGLMatrixd>> transMatVecs;
144 std::vector<std::vector<Eigen::Matrix4f,
145 Eigen::aligned_allocator<Eigen::Matrix4f>>>
147 std::vector<std::vector<pcl::Correspondences>> clusteredCorrs;
148 std::vector<std::vector<pcl::PointCloud<PointType>::ConstPtr>> instancesVec;
149 std::vector<std::vector<bool>> hypothesesMaskVec;
151 PointCloudT::Ptr sceneKeypoints(
new PointCloudT());
152 pcl::PointCloud<NormalType>::Ptr sceneNormals(
153 new pcl::PointCloud<NormalType>());
154 pcl::PointCloud<DescriptorType>::Ptr sceneDescriptors(
155 new pcl::PointCloud<DescriptorType>());
156 std::vector<pcl::CorrespondencesPtr> modelSceneCorrs;
157 std::vector<pcl::PointCloud<DescriptorType>::Ptr> modelsDescriptors;
158 std::vector<pcl::PointCloud<NormalType>::Ptr> modelsWithNormal;
159 std::vector<PointCloudT::Ptr> modelsKeypoints;
160 std::vector<PointCloudT::Ptr> modelClouds;
163 PointCloudT::Ptr scene = cc2smReader(
m_sceneCloud).getXYZ2();
167 PointCloudT::Ptr tempCloud(
new PointCloudT);
168 if (!PCLModules::VoxelGridFilter<PointType>(
182 PointCloudT::Ptr modelCloud = cc2smReader(
m_modelClouds[i]).getXYZ2();
183 if (modelCloud->width * modelCloud->height != 0) {
184 modelClouds.push_back(modelCloud);
185 pcl::PointCloud<NormalType>::Ptr model_normals(
186 new pcl::PointCloud<NormalType>());
187 if (PCLModules::ComputeNormals<PointType, NormalType>(
190 modelsWithNormal.push_back(model_normals);
194 if (!PCLModules::ComputeNormals<PointType, NormalType>(
200 if (!PCLModules::GetUniformSampling<PointType>(scene, sceneKeypoints,
204 CVLog::Print(tr(
"Scene total points: %1; Selected Keypoints: %2")
206 .arg(sceneKeypoints->size()));
207 for (
size_t i = 0; i < modelClouds.size(); ++i) {
208 PointCloudT::Ptr model_keypoints(
new PointCloudT());
209 if (!PCLModules::GetUniformSampling<PointType>(
213 modelsKeypoints.push_back(model_keypoints);
214 CVLog::Print(tr(
"Model %1 total points: %2; Selected Keypoints: %3")
216 .arg(modelClouds[i]->
size())
217 .arg(model_keypoints->size()));
221 if (!PCLModules::EstimateShot<PointType, NormalType, DescriptorType>(
222 scene, sceneKeypoints, sceneNormals, sceneDescriptors,
226 for (
size_t i = 0; i < modelClouds.size(); ++i) {
227 pcl::PointCloud<DescriptorType>::Ptr model_descriptors(
228 new pcl::PointCloud<DescriptorType>());
229 if (!PCLModules::EstimateShot<PointType, NormalType, DescriptorType>(
230 modelClouds[i], modelsKeypoints[i], modelsWithNormal[i],
235 modelsDescriptors.push_back(model_descriptors);
239 pcl::KdTreeFLANN<DescriptorType> match_search;
240 for (
size_t j = 0; j < modelClouds.size(); ++j) {
242 match_search.setInputCloud(modelsDescriptors[j]);
247 for (
size_t i = 0; i < sceneDescriptors->size(); ++i) {
248 std::vector<int> neigh_indices(1);
249 std::vector<float> neigh_sqr_dists(1);
250 if (!std::isfinite(sceneDescriptors->at(i)
255 int found_neighs = match_search.nearestKSearch(
256 sceneDescriptors->at(i), 1, neigh_indices, neigh_sqr_dists);
257 if (found_neighs == 1 &&
263 pcl::Correspondence corr(neigh_indices[0],
static_cast<int>(i),
265 model_scene_corrs->push_back(corr);
268 CVLog::Print(tr(
"Correspondences found for model %1 : %2")
270 .arg(model_scene_corrs->size()));
271 modelSceneCorrs.push_back(model_scene_corrs);
275 for (
size_t j = 0; j < modelClouds.size(); ++j) {
276 std::vector<Eigen::Matrix4f, Eigen::aligned_allocator<Eigen::Matrix4f>>
278 std::vector<pcl::Correspondences> clustered_corrs;
280 pcl::CorrespondencesPtr model_scene_corrs = modelSceneCorrs[j];
281 PointCloudT::Ptr model_keypoints = modelsKeypoints[j];
282 PointCloudT::Ptr model = modelClouds[j];
283 pcl::PointCloud<NormalType>::Ptr model_normals = modelsWithNormal[j];
286 if (!PCLModules::EstimateGeometricConsistencyGrouping<PointType,
288 model_keypoints, sceneKeypoints, model_scene_corrs,
297 pcl::PointCloud<RFType>::Ptr model_rf(
298 new pcl::PointCloud<RFType>());
299 pcl::PointCloud<RFType>::Ptr scene_rf(
300 new pcl::PointCloud<RFType>());
302 if (!PCLModules::EstimateLocalReferenceFrame<PointType, NormalType,
304 model, model_keypoints, model_normals, model_rf,
309 if (!PCLModules::EstimateLocalReferenceFrame<PointType, NormalType,
311 scene, sceneKeypoints, sceneNormals, scene_rf,
317 if (!PCLModules::EstimateHough3DGrouping<PointType, PointType,
319 model_keypoints, sceneKeypoints, model_rf, scene_rf,
320 model_scene_corrs, transformMatrix, clustered_corrs,
326 rotoTranslationsVec.push_back(transformMatrix);
327 clusteredCorrs.push_back(clustered_corrs);
331 for (
size_t j = 0; j < rotoTranslationsVec.size(); ++j) {
332 if (rotoTranslationsVec[j].
size() <= 0) {
333 CVLog::Print(tr(
"No instances found in Model %1 ").arg(j + 1));
339 .arg(rotoTranslationsVec[j].
size()));
344 std::vector<pcl::PointCloud<PointType>::ConstPtr> instances;
346 for (
size_t i = 0; i < rotoTranslationsVec[j].size(); ++i) {
347 pcl::PointCloud<PointType>::Ptr rotated_model(
348 new pcl::PointCloud<PointType>());
349 pcl::transformPointCloud(*modelClouds[j], *rotated_model,
350 rotoTranslationsVec[j][i]);
351 instances.push_back(rotated_model);
353 instancesVec.push_back(instances);
361 std::vector<pcl::PointCloud<PointType>::ConstPtr>
362 registered_instances;
366 for (
size_t i = 0; i < rotoTranslationsVec[j].size(); ++i) {
367 pcl::PointCloud<PointType>::Ptr registered(
368 new pcl::PointCloud<PointType>);
369 if (PCLModules::ICPRegistration<PointType, PointType>(
370 scene, instances[i], registered,
380 registered_instances.push_back(registered);
389 tr(
"--- Hypotheses bugs and do not support! ---------"));
419 for (
size_t i = 0; i < rotoTranslationsVec[j].size(); ++i) {
420 hypotheses_mask.push_back(
true);
424 hypothesesMaskVec.push_back(hypotheses_mask);
429 new ccHObject(tr(
"correspondence-grouping-cluster(s)"));
432 for (
int j = 0; j < static_cast<int>(instancesVec.size()); ++j) {
433 for (
int i = 0; i < static_cast<int>(instancesVec[j].
size()); ++i) {
435 if (hypothesesMaskVec[j][i]) {
436 PCLCloud out_cloud_sm;
437 TO_PCL_CLOUD(*instancesVec[j][i], out_cloud_sm);
438 if (out_cloud_sm.height * out_cloud_sm.width == 0) {
443 ccPointCloud* out_cloud_cc = pcl2cc::Convert(out_cloud_sm);
455 out_cloud_cc->
showSF(
false);
458 QString outName = tr(
"%1-correspondence-%2-%3")
462 out_cloud_cc->
setName(outName);
503 return tr(
"Cannot match anything by this model !");
506 "Wrong Parameters. One or more parameters cannot be "
510 "Correspondence Matching does not returned any point. Try "
511 "relaxing your parameters");
Base abstract class for each implemented PCL filter.
int isFirstSelectedCcPointCloud()
Returns 1 if the first selected object is a ccPointCloud.
void newEntity(ccHObject *)
Signal emitted when a new entity is created by the filter.
ecvMainAppInterface * m_app
Associated application interface.
virtual QString getErrorMessage(int errorCode)
Returns the error message corresponding to a given error code.
static bool Print(const char *format,...)
Prints out a formatted message in console.
CANUPO plugin's training dialog.
void saveParamsToPersistentSettings()
Saves parameters to persistent settings.
bool isGCActivated() const
void refreshCloudComboBox()
ccPointCloud * getModelCloudByIndex(int index)
float getModelSearchRadius() const
Returns the Model Search Radius.
float getShotDescriptorRadius() const
Returns the Shot Descriptor Radius.
float getHoughBinSize() const
float getVoxelGridLeafSize() const
float getHoughLRFRadius() const
float getNormalKSearch() const
Returns the normal KSearch.
ccPointCloud * getEvaluationCloud()
Get evaluation point cloud.
int getMaxThreadCount() const
Returns the max number of threads to use.
float getGcMinClusterSize() const
bool getScales(std::vector< float > &scales) const
Returns input scales.
float getSceneSearchRadius() const
Returns the Scene Search Radius.
float getHoughThreshold() const
float getGcConsensusSetResolution() const
bool getVerificationFlag() const
float m_shotDescriptorRadius
ccPointCloud * m_sceneCloud
virtual int compute()
Performs the actual filter job.
std::vector< ccPointCloud * > m_modelClouds
float m_consensusResolution
virtual QString getErrorMessage(int errorCode)
Returns the error message corresponding to a given error code.
virtual ~CorrespondenceMatching()
float m_sceneSearchRadius
void applyTransformation(ccHObject *entity, const ccGLMatrixd &mat)
float m_modelSearchRadius
virtual void getParametersFromDialog()
Collects parameters from the filter dialog (if openDialog is successful)
virtual int openInputDialog()
virtual int checkParameters()
CorrespondenceMatchingDialog * m_dialog
virtual int checkSelected()
Checks if current selection is compliant with the filter.
std::vector< float > m_scales
virtual void setVisible(bool state)
Sets entity visibility.
virtual void showColors(bool state)
Sets colors visibility.
virtual void showSF(bool state)
Sets active scalarfield visibility.
virtual void setGLTransformation(const ccGLMatrix &trans)
Associates entity with a GL transformation (rotation + translation)
T * data()
Returns a pointer to internal data.
Float version of ccGLMatrixTpl.
Double version of ccGLMatrixTpl.
Hierarchical CLOUDVIEWER Object.
void applyGLTransformation_recursive(const ccGLMatrix *trans=nullptr)
Applies the active OpenGL transformation to the entity (recursive)
unsigned getChildrenNumber() const
Returns the number of children.
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
ccHObject * getParent() const
Returns parent object.
virtual QString getName() const
Returns object name.
virtual void setName(const QString &name)
Sets object name.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
bool setRGBColor(ColorCompType r, ColorCompType g, ColorCompType b)
Set a unique color for the whole cloud (shortcut)
virtual void setGlobalScale(double scale)
virtual void setGlobalShift(double x, double y, double z)
Sets shift applied to original coordinates (information storage only)
virtual const CCVector3d & getGlobalShift() const
Returns the shift applied to original coordinates.
virtual double getGlobalScale() const
Returns the scale applied to original coordinates.
static Rgb Random(bool lightOnly=true)
Generates a random color.
virtual void dispToConsole(QString message, ConsoleMessageLevel level=STD_CONSOLE_MESSAGE)=0
std::vector< Pair > Correspondences