程序示例精选
C++ PCL三维点云物体目标识别
如需安装运行环境或远程调试,可点击 博主头像进入个人主页查看博主联系方式,由专业技术人员远程协助!
前言
这篇博客针对《C++ PCL三维点云物体目标识别》编写代码,代码整洁,规则,易读。 学习与应用推荐首选。运行结果
文章目录
一、所需工具软件二、使用步骤
1. 主要代码
2. 运行结果
三、在线协助
一、所需工具软件
1. VS2019, C++2. C++
二、使用步骤
代码如下(示例):
void
parseCommandLine(int argc, char *argv[])
{
//Show help
if (pcl::console::find_switch(argc, argv, "-h"))
{
showHelp(argv[0]);
exit(0);
}
//Model & scene filenames
std::vector<int> filenames;
filenames = pcl::console::parse_file_extension_argument(argc, argv, ".pcd");
if (filenames.size() != 2)
{
std::cout << "Filenames missing.\n";
showHelp(argv[0]);
exit(-1);
}
model_filename_ = argv[filenames[0]];
scene_filename_ = argv[filenames[1]];
//Program behavior
if (pcl::console::find_switch(argc, argv, "-k"))//可视化构造对应点时用到的关键点
{
show_keypoints_ = true;
}
if (pcl::console::find_switch(argc, argv, "-c"))//可视化支持实例假设的对应点对
{
show_correspondences_ = true;
}
if (pcl::console::find_switch(argc, argv, "-r"))//计算点云的分辨率和多样性
{
use_cloud_resolution_ = true;
}
std::string used_algorithm;
if (pcl::console::parse_argument(argc, argv, "--algorithm", used_algorithm) != -1)
{
if (used_algorithm.compare("Hough") == 0)
{
use_hough_ = true;
}
else if (used_algorithm.compare("GC") == 0)
{
use_hough_ = false;
}
else
{
std::cout << "Wrong algorithm name.\n";
showHelp(argv[0]);
exit(-1);
}
}
//General parameters
pcl::console::parse_argument(argc, argv, "--model_ss", model_ss_);
pcl::console::parse_argument(argc, argv, "--scene_ss", scene_ss_);
pcl::console::parse_argument(argc, argv, "--rf_rad", rf_rad_);
pcl::console::parse_argument(argc, argv, "--descr_rad", descr_rad_);
pcl::console::parse_argument(argc, argv, "--cg_size", cg_size_);
pcl::console::parse_argument(argc, argv, "--cg_thresh", cg_thresh_);
}
int
main(int argc, char *argv[])
{
parseCommandLine(argc, argv);
pcl::PointCloud<PointType>::Ptr model(new pcl::PointCloud<PointType>()); //模型点云
pcl::PointCloud<PointType>::Ptr model_keypoints(new pcl::PointCloud<PointType>()); //模型角点
pcl::PointCloud<PointType>::Ptr scene(new pcl::PointCloud<PointType>()); //目标点云
pcl::PointCloud<PointType>::Ptr scene_keypoints(new pcl::PointCloud<PointType>()); //目标角点
pcl::PointCloud<NormalType>::Ptr model_normals(new pcl::PointCloud<NormalType>()); //法线
pcl::PointCloud<NormalType>::Ptr scene_normals(new pcl::PointCloud<NormalType>()); //
pcl::PointCloud<DescriptorType>::Ptr model_descriptors(new pcl::PointCloud<DescriptorType>()); //描述子
pcl::PointCloud<DescriptorType>::Ptr scene_descriptors(new pcl::PointCloud<DescriptorType>());
//
// Load clouds
//
if (pcl::io::loadPCDFile(model_filename_, *model) < 0)
{
std::cout << "Error loading model cloud." << std::endl;
showHelp(argv[0]);
return (-1);
}
if (pcl::io::loadPCDFile(scene_filename_, *scene) < 0)
{
std::cout << "Error loading scene cloud." << std::endl;
showHelp(argv[0]);
return (-1);
}
//
// Set up resolution invariance
//
if (use_cloud_resolution_)
{
float resolution = static_cast<float> (computeCloudResolution(model));
if (resolution != 0.0f)
{
model_ss_ *= resolution;
scene_ss_ *= resolution;
rf_rad_ *= resolution;
descr_rad_ *= resolution;
cg_size_ *= resolution;
}
std::cout << "Model resolution: " << resolution << std::endl;
std::cout << "Model sampling size: " << model_ss_ << std::endl;
std::cout << "Scene sampling size: " << scene_ss_ << std::endl;
std::cout << "LRF support radius: " << rf_rad_ << std::endl;
std::cout << "SHOT descriptor radius: " << descr_rad_ << std::endl;
std::cout << "Clustering bin size: " << cg_size_ << std::endl << std::endl;
}
std::cout << "Model total points: " << model->size() << "; Selected Keypoints: " << model_keypoints->size() << std::endl;
uniform_sampling.setInputCloud(scene);
uniform_sampling.setRadiusSearch(scene_ss_);
//uniform_sampling.compute (sampled_indices);
//pcl::copyPointCloud (*scene, sampled_indices.points, *scene_keypoints);
uniform_sampling.filter(*scene_keypoints);
std::cout << "Scene total points: " << scene->size() << "; Selected Keypoints: " << scene_keypoints->size() << std::endl;
//
// Compute Descriptor for keypoints:为关键点计算描述子
//
pcl::SHOTEstimationOMP<PointType, NormalType, DescriptorType> descr_est;
descr_est.setNumberOfThreads(4);
descr_est.setRadiusSearch(descr_rad_); //设置搜索半径
descr_est.setInputCloud(model_keypoints); //模型点云的关键点
descr_est.setInputNormals(model_normals); //模型点云的法线
descr_est.setSearchSurface(model); //模型点云
descr_est.compute(*model_descriptors); //计算描述子
descr_est.setInputCloud(scene_keypoints);
descr_est.setInputNormals(scene_normals);
descr_est.setSearchSurface(scene);
descr_est.compute(*scene_descriptors);
//
// Find Model-Scene Correspondences with KdTree:使用Kdtree找出 Model-Scene 匹配点
//
pcl::CorrespondencesPtr model_scene_corrs(new pcl::Correspondences());
pcl::KdTreeFLANN<DescriptorType> match_search; //设置配准方式
match_search.setInputCloud(model_descriptors);//模型点云的描述子
// Clustering
pcl::Hough3DGrouping<PointType, PointType, RFType, RFType> clusterer;
clusterer.setHoughBinSize(cg_size_); //hough空间的采样间隔:0.01
clusterer.setHoughThreshold(cg_thresh_); //在hough空间确定是否有实例存在的最少票数阈值:5
clusterer.setUseInterpolation(true); //设置是否对投票在hough空间进行插值计算
clusterer.setUseDistanceWeight(false); //设置在投票时是否将对应点之间的距离作为权重参与计算
clusterer.setInputCloud(model_keypoints); //设置模型点云的关键点
clusterer.setInputRf(model_rf); //设置模型对应的局部坐标系
clusterer.setSceneCloud(scene_keypoints);
clusterer.setSceneRf(scene_rf);
clusterer.setModelSceneCorrespondences(model_scene_corrs);//设置模型与场景的对应点的集合
//clusterer.cluster (clustered_corrs);
clusterer.recognize(rototranslations, clustered_corrs); //结果包含变换矩阵和对应点聚类结果
}
else // Using GeometricConsistency:使用几何一致性性质
{
pcl::GeometricConsistencyGrouping<PointType, PointType> gc_clusterer;
gc_clusterer.setGCSize(cg_size_); //设置几何一致性的大小
gc_clusterer.setGCThreshold(cg_thresh_); //阈值
gc_clusterer.setInputCloud(model_keypoints);
gc_clusterer.setSceneCloud(scene_keypoints);
gc_clusterer.setModelSceneCorrespondences(model_scene_corrs);
//gc_clusterer.cluster (clustered_corrs);
gc_clusterer.recognize(rototranslations, clustered_corrs);
}
//
// Output results:找出输入模型是否在场景中出现
//
std::cout << "Model instances found: " << rototranslations.size() << std::endl;
for (size_t i = 0; i < rototranslations.size(); ++i)
{
std::cout << "\n Instance " << i + 1 << ":" << std::endl;
std::cout << " Correspondences belonging to this instance: " << clustered_corrs[i].size() << std::endl;
//打印处相对于输入模型的旋转矩阵与平移矩阵
Eigen::Matrix3f rotation = rototranslations[i].block<3, 3>(0, 0);
Eigen::Vector3f translation = rototranslations[i].block<3, 1>(0, 3);
printf("\n");
printf(" | %6.3f %6.3f %6.3f | \n", rotation(0, 0), rotation(0, 1), rotation(0, 2));
printf(" R = | %6.3f %6.3f %6.3f | \n", rotation(1, 0), rotation(1, 1), rotation(1, 2));
printf(" | %6.3f %6.3f %6.3f | \n", rotation(2, 0), rotation(2, 1), rotation(2, 2));
printf("\n");
printf(" t = < %0.3f, %0.3f, %0.3f >\n", translation(0), translation(1), translation(2));
}
//
// Visualization
//
pcl::visualization::PCLVisualizer viewer("点云库PCL学习教程第二版-基于对应点聚类的3D模型识别");
viewer.addPointCloud(scene, "scene_cloud");//可视化场景点云
viewer.setBackgroundColor(0, 0, 0);
pcl::PointCloud<PointType>::Ptr off_scene_model(new pcl::PointCloud<PointType>());
pcl::PointCloud<PointType>::Ptr off_scene_model_keypoints(new pcl::PointCloud<PointType>());
if (show_correspondences_ || show_keypoints_)//可视化配准点
{
//We are translating the model so that it doesn't end in the middle of the scene representation
//对输入的模型进行旋转与平移,使其在可视化界面的中间位置
pcl::transformPointCloud(*model, *off_scene_model, Eigen::Vector3f(0, 0, 0), Eigen::Quaternionf(1, 0, 0, 0));
pcl::transformPointCloud(*model_keypoints, *off_scene_model_keypoints, Eigen::Vector3f(-1, 0, 0), Eigen::Quaternionf(1, 0, 0, 0));
pcl::visualization::PointCloudColorHandlerCustom<PointType> off_scene_model_color_handler(off_scene_model, 0, 255, 0);
viewer.addPointCloud(off_scene_model, off_scene_model_color_handler, "off_scene_model");
}
if (show_keypoints_)//可视化关键点:蓝色
{
pcl::visualization::PointCloudColorHandlerCustom<PointType> scene_keypoints_color_handler(scene_keypoints, 0, 0, 255);
viewer.addPointCloud(scene_keypoints, scene_keypoints_color_handler, "scene_keypoints");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "scene_keypoints");
pcl::visualization::PointCloudColorHandlerCustom<PointType> off_scene_model_keypoints_color_handler(off_scene_model_keypoints, 0, 0, 255);
viewer.addPointCloud(off_scene_model_keypoints, off_scene_model_keypoints_color_handler, "off_scene_model_keypoints");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "off_scene_model_keypoints");
}
for (size_t i = 0; i < rototranslations.size(); ++i)
{
pcl::PointCloud<PointType>::Ptr rotated_model(new pcl::PointCloud<PointType>());
pcl::transformPointCloud(*model, *rotated_model, rototranslations[i]);//把model转化为rotated_model
std::stringstream ss_cloud;
ss_cloud << "instance" << i;
pcl::visualization::PointCloudColorHandlerCustom<PointType> rotated_model_color_handler(rotated_model, 255, 0, 0);
viewer.addPointCloud(rotated_model, rotated_model_color_handler, ss_cloud.str());
// We are drawing a line for each pair of clustered correspondences found between the model and the scene
viewer.addLine<PointType, PointType>(model_point, scene_point, 0, 255, 0, ss_line.str());
}
}
}
while (!viewer.wasStopped())
{
viewer.spinOnce();
}
return (0);
}
运行结果
三、在线协助:
如需安装运行环境或远程调试,可点击博主头像,进入个人主页查看博主联系方式,由专业技术人员远程协助!
1)远程安装运行环境,代码调试
2)Visual Studio, Qt, C++, Python编程语言入门指导
3)界面美化
4)软件制作
博主个人主页:https://developer.aliyun.com/profile/expert/rfnzgp3sk3ahc
博主所有文章点这里:https://developer.aliyun.com/profile/expert/rfnzgp3sk3ahc
博主联系方式点这里:https://developer.aliyun.com/profile/expert/rfnzgp3sk3ahc