PCL中NNDR特征匹配代码
时间: 2023-07-10 08:13:30 浏览: 183
特征匹配源码
在PCL中,NNDR特征匹配可以使用`pcl::registration::CorrespondenceEstimation`类和`pcl::registration::CorrespondenceRejectorOneToOne`类实现。下面是一个示例代码,用于在两个点云中匹配SURF特征:
```cpp
#include <pcl/registration/correspondence_estimation.h>
#include <pcl/registration/correspondence_rejection_one_to_one.h>
#include <pcl/features/normal_3d.h>
#include <pcl/features/shot_omp.h>
#include <pcl/features/board.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
typedef pcl::PointXYZ PointT;
typedef pcl::Normal NormalT;
typedef pcl::SHOT352 DescriptorT;
int main(int argc, char **argv)
{
// 加载两个点云
pcl::PointCloud<PointT>::Ptr cloud1(new pcl::PointCloud<PointT>);
pcl::PointCloud<PointT>::Ptr cloud2(new pcl::PointCloud<PointT>);
pcl::io::loadPCDFile<PointT>("cloud1.pcd", *cloud1);
pcl::io::loadPCDFile<PointT>("cloud2.pcd", *cloud2);
// 计算法线
pcl::PointCloud<NormalT>::Ptr normals1(new pcl::PointCloud<NormalT>);
pcl::PointCloud<NormalT>::Ptr normals2(new pcl::PointCloud<NormalT>);
pcl::NormalEstimation<PointT, NormalT> normalEstimator;
normalEstimator.setInputCloud(cloud1);
normalEstimator.setRadiusSearch(0.01);
normalEstimator.compute(*normals1);
normalEstimator.setInputCloud(cloud2);
normalEstimator.compute(*normals2);
// 计算SHOT特征
pcl::PointCloud<DescriptorT>::Ptr features1(new pcl::PointCloud<DescriptorT>);
pcl::PointCloud<DescriptorT>::Ptr features2(new pcl::PointCloud<DescriptorT>);
pcl::SHOTEstimationOMP<PointT, NormalT, DescriptorT> shotEstimator;
shotEstimator.setInputCloud(cloud1);
shotEstimator.setInputNormals(normals1);
shotEstimator.setRadiusSearch(0.01);
shotEstimator.compute(*features1);
shotEstimator.setInputCloud(cloud2);
shotEstimator.setInputNormals(normals2);
shotEstimator.compute(*features2);
// 特征匹配
pcl::registration::CorrespondenceEstimation<DescriptorT, DescriptorT> correspondenceEstimator;
correspondenceEstimator.setInputSource(features1);
correspondenceEstimator.setInputTarget(features2);
pcl::CorrespondencesPtr correspondences(new pcl::Correspondences);
correspondenceEstimator.determineCorrespondences(*correspondences);
// NNDR匹配
pcl::registration::CorrespondenceRejectorOneToOne correspondenceRejector;
correspondenceRejector.setInputCorrespondences(correspondences);
correspondenceRejector.setThreshold(0.8); // 设置NNDR阈值
pcl::CorrespondencesPtr filteredCorrespondences(new pcl::Correspondences);
correspondenceRejector.getCorrespondences(*filteredCorrespondences);
// 可视化匹配结果
pcl::visualization::PCLVisualizer viewer("Correspondences");
viewer.addPointCloud(cloud1, "cloud1");
viewer.addPointCloud(cloud2, "cloud2");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "cloud1");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "cloud2");
for (int i = 0; i < filteredCorrespondences->size(); i++) {
int index1 = filteredCorrespondences->at(i).index_query;
int index2 = filteredCorrespondences->at(i).index_match;
std::stringstream ss;
ss << "correspondence_" << i;
viewer.addCorrespondence<PointT>(cloud1, cloud2, index1, index2, ss.str());
}
viewer.spin();
return 0;
}
```
该代码中,我们首先加载了两个点云,然后计算了它们的法线和SHOT特征。接着,使用`CorrespondenceEstimation`类对两个点云的特征进行匹配,并得到了一组初始的匹配对。然后,使用`CorrespondenceRejectorOneToOne`类对这些匹配对进行NNDR匹配,并得到了一组筛选后的匹配对。最后,我们可以使用PCL可视化工具对匹配结果进行可视化。
需要注意的是,在进行NNDR匹配时,需要根据实际应用场景来调整阈值的取值。如果阈值过大,会导致匹配成功的对数较少;如果阈值过小,会导致误匹配的对数较多。
阅读全文