pcl基于对应分组的三维物体识别简化版
·
前言
本文针对csdn中,对于pcl库中基于对应分组的三维物体识别的代码过于冗长的现象,如https://blog.csdn.net/lizhengze1117/article/details/103230261这篇文章的代码真的长。本文对其代码中花里胡哨的部分进行删减。提示:以下是本篇文章正文内容,下面案例可供参考
一、pcl基于对应分组的三维物体识别
与识别有关的知识请参考https://www.yuque.com/huangzhongqing/pcl/hpgc39#E10g9
该链接是某大佬写的pcl的教程代码虽然写得很长,但理论讲的还不错。
二、使用步骤
1.环境
vs2019+pcl1.11.1
2.代码
代码如下(:
// 对象识别.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <sstream>
#include <fstream>
#include<pcl\point_types.h>
#include<pcl\point_cloud.h>
#include <pcl/features/shot_omp.h>
#include<pcl\io\pcd_io.h>
#include <pcl/features/normal_3d_omp.h>
#include<pcl\visualization\pcl_visualizer.h>
#include <pcl/filters/uniform_sampling.h>//均匀采样 滤波
#include <pcl/recognition/cg/geometric_consistency.h> //几何一致性
#include <pcl/common/transforms.h>//点云转换 转换矩阵
using namespace std;
int main()
{
/*模型、场景、局部特征描述子的数据结构*/
pcl::PointCloud<pcl::PointXYZ>::Ptr model(new pcl::PointCloud<pcl::PointXYZ>()); //模型点云,模型的格式为PointXYZ
pcl::PointCloud<pcl::PointXYZ>::Ptr model_keypoints(new pcl::PointCloud<pcl::PointXYZ>()); //降采样后的
pcl::PointCloud<pcl::PointXYZRGBA>::Ptr scene(new pcl::PointCloud<pcl::PointXYZRGBA>()); //目标点云,场景的格式为PointXYZRGBA,也不知道那篇文章为什么将其和模型定义为相同格式,可能又想炫技?
pcl::PointCloud<pcl::PointXYZRGBA>::Ptr scene_keypoints(new pcl::PointCloud<pcl::PointXYZRGBA>()); //关键点
pcl::PointCloud<pcl::Normal>::Ptr model_normals(new pcl::PointCloud<pcl::Normal>()); //法线
pcl::PointCloud<pcl::Normal>::Ptr scene_normals(new pcl::PointCloud<pcl::Normal>()); //
pcl::PointCloud<pcl::SHOT352>::Ptr model_descriptors(new pcl::PointCloud<pcl::SHOT352>()); //描述子
pcl::PointCloud<pcl::SHOT352>::Ptr scene_descriptors(new pcl::PointCloud<pcl::SHOT352>());
/*模型、场景、局部特征描述子的数据结构*/
/* pcd文件输入输出*/
pcl::io::loadPCDFile("E:\\2345Downloads\\MVision-master\\MVision-master\\PCL_APP\\Recognition\\milk.pcd", *model);
pcl::io::loadPCDFile("E:\\2345Downloads\\MVision-master\\MVision-master\\PCL_APP\\Recognition\\milk_cartoon_all_small_clorox.pcd", *scene);
/* pcd文件输入输出*/
/* 法线估计*/
pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> norm_est;
pcl::NormalEstimationOMP<pcl::PointXYZRGBA, pcl::Normal> norm_sen;
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree1(new pcl::search::KdTree<pcl::PointXYZ>());
pcl::search::KdTree<pcl::PointXYZRGBA>::Ptr tree2(new pcl::search::KdTree<pcl::PointXYZRGBA>());
norm_est.setSearchMethod(tree1);//设置搜索模式为kdtree,原文想炫技非用多线程
norm_est.setKSearch(10); //设置k邻域搜索阈值为10个点
norm_est.setInputCloud(model); //设置输入模型点云
norm_est.compute(*model_normals);//计算点云法线
norm_sen.setSearchMethod(tree2); //设置搜索模式为kdtree,原文想炫技非用多线程
norm_sen.setKSearch(10); //设置k邻域搜索阈值为10个
norm_sen.setInputCloud(scene);
norm_sen.compute(*scene_normals);
/* 法线估计*/
/*降采样*/
pcl::UniformSampling<pcl::PointXYZ> uniform_sampling1;//下采样滤波模型
uniform_sampling1.setInputCloud(model);//模型点云
uniform_sampling1.setRadiusSearch(0.01);//模型点云搜索半径
uniform_sampling1.filter(*model_keypoints);//下采样得到的关键点
pcl::UniformSampling<pcl::PointXYZRGBA> uniform_sampling2;//下采样滤波模型
uniform_sampling2.setInputCloud(scene);//场景点云
uniform_sampling2.setRadiusSearch(0.03);//场景点云搜索半径
uniform_sampling2.filter(*scene_keypoints);//下采样得到的关键点,降得几乎看不出轮廓
/*降采样*/
/* 局部特征描述子*/
pcl::SHOTEstimationOMP<pcl::PointXYZ, pcl::Normal, pcl::SHOT352> descr_est1;//shot描述子
descr_est1.setRadiusSearch(0.02);
descr_est1.setInputCloud(model_keypoints);
descr_est1.setInputNormals(model_normals);
descr_est1.setSearchSurface(model);
descr_est1.compute(*model_descriptors);//模型点云描述子
pcl::SHOTEstimationOMP<pcl::PointXYZRGBA, pcl::Normal, pcl::SHOT352> descr_est2;//shot描述子
descr_est2.setRadiusSearch(0.04);//你上面都降采样到0.03了,这里在设置为0.02怎么可能找得到点
descr_est2.setInputCloud(scene_keypoints);
descr_est2.setInputNormals(scene_normals);
descr_est2.setSearchSurface(scene);
descr_est2.compute(*scene_descriptors);//场景点云描述子
/*局部特征描述子*/
/*匹配局部特征描述子,我也不知道为什么要匹配这个*/
pcl::CorrespondencesPtr model_scene_corrs(new pcl::Correspondences());//最佳匹配点对组
pcl::KdTreeFLANN<pcl::SHOT352> match_search;//匹配搜索
match_search.setInputCloud(model_descriptors);//模型点云描述子
// 在 场景点云中 为 模型点云的每一个关键点 匹配一个 描述子最相似的 点
for (size_t i = 0; i < scene_descriptors->size(); ++i)//遍历场景点云
{
std::vector<int> neigh_indices(1);//索引
std::vector<float> neigh_sqr_dists(1);//描述子距离
if (!pcl_isfinite(scene_descriptors->at(i).descriptor[0])) //跳过NAN点
{
continue;
}
int found_neighs = match_search.nearestKSearch(scene_descriptors->at(i), 1, neigh_indices, neigh_sqr_dists);
if (found_neighs == 1 && neigh_sqr_dists[0] < 0.25f) //在模型点云中 找 距离 场景点云点i shot描述子距离 <0.25 的点 ,很神奇,不清楚0.25怎么来的
{
pcl::Correspondence corr(neigh_indices[0], static_cast<int> (i), neigh_sqr_dists[0]);
// neigh_indices[0] 为模型点云中 和 场景点云 点 scene_descriptors->at (i) 最佳的匹配 距离为 neigh_sqr_dists[0]
model_scene_corrs->push_back(corr);
}
}
/*匹配局部特征描述子,我也不知道为什么要匹配这个*/
std::vector<Eigen::Matrix4f, Eigen::aligned_allocator<Eigen::Matrix4f> > rototranslations;//变换矩阵 旋转矩阵与平移矩阵
// 对eigen中的固定大小的类使用STL容器的时候,如果直接使用就会出错 需要使用 Eigen::aligned_allocator 对齐技术
std::vector<pcl::Correspondences> clustered_corrs;//匹配点 相互连线的索引
pcl::GeometricConsistencyGrouping<pcl::PointXYZ, pcl::PointXYZRGBA> gc_clusterer;
gc_clusterer.setGCSize(0.01);//设置几何一致性的大小
gc_clusterer.setGCThreshold(5.0);//阀值
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);
/* 可视化*/
pcl::visualization::PCLVisualizer viewer("111");
viewer.addPointCloud(scene, "scene_cloud");//添加场景点云
pcl::PointCloud<pcl::PointXYZ>::Ptr off_scene_model(new pcl::PointCloud<pcl::PointXYZ>());// 模型点云 变换后的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr off_scene_model_keypoints(new pcl::PointCloud<pcl::PointXYZ>());//关键点
for (size_t i = 0; i < rototranslations.size(); ++i)//对于 模型在场景中 匹配的 点云
{
pcl::PointCloud<pcl::PointXYZ>::Ptr rotated_model(new pcl::PointCloud<pcl::PointXYZ>());//按匹配变换矩阵 模型点云
pcl::transformPointCloud(*model, *rotated_model, rototranslations[i]);//将模型点云按匹配的变换矩阵旋转
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> rotated_model_color_handler(rotated_model, 255, 0, 0);
viewer.addPointCloud(rotated_model, rotated_model_color_handler);//添加模型按识别 变换矩阵变换后 显示
for (size_t j = 0; j < clustered_corrs[i].size(); ++j)
{
pcl::PointXYZ& model_point = model_keypoints->at(clustered_corrs[i][j].index_query);//模型点
pcl::PointXYZRGBA& scene_point = scene_keypoints->at(clustered_corrs[i][j].index_match);//场景点
// 显示点云匹配对中每一对匹配点对之间的连线
viewer.addLine<pcl::PointXYZ, pcl::PointXYZRGBA>(model_point, scene_point, 0, 255, 0);
}
}
while (!viewer.wasStopped())
{
viewer.spinOnce();
}
}
该处使用的url网络请求的数据。
效果图

本文作者水平有限,因此对原文的代码一知半解,又由于对原文代码删减过多,从而导致识别结果出现了很大的问题,如只有一条绿色的线、红色点云是横着的等问题,但原文代码过长,笔者也不知道到底哪里出了问题。
下附参考文章的链接 https://www.yuque.com/huangzhongqing/pcl/hpgc39#E10g9
更多推荐


所有评论(0)