目录
一、概述
1.1原理
1.2实现步骤
1.3应用场景
二、代码实现
2.1关键函数
2.1.1 法线计算
2.1.2 3DSC特征计算
2.1.3 可视化3DSC直方图
2.2完整代码
三、实现效果
PCL点云算法汇总及实战案例汇总的目录地址链接:
PCL点云算法与项目实战案例汇总(长期更新)
一、概述
3D形状上下文(3D Shape Context, 3DSC)是三维点云描述子的一种,它通过将一个点的局部邻域信息映射到球坐标系,并将空间区域划分为多个区域来描述点的局部几何结构。通过计算每个区域内的点数,可以得到描述点局部形状的特征向量。3DSC可以用于点云配准、匹配、物体识别等任务。
1.1原理
3DSC通过以下步骤计算点云描述子:
- 对每个点,建立以该点为中心的局部坐标系,并将其邻域内的点投影到球坐标系中。
- 将球坐标系分割为不同的体积单元,统计每个体积单元内的点数,生成描述子。
- 形状上下文描述子的关键参数包括:
- 最小半径Rmin:用于定义搜索球面内的最小球半径。
- 搜索半径Rmax:用于定义计算特征时考虑的最大邻域范围。
- 点密度半径:用于估算点的局部密度。
1.2实现步骤
- 读取点云数据并计算点云法线。
- 利用3D形状上下文方法计算3DSC描述子。
- 可视化计算的3DSC直方图。
1.3应用场景
- 点云配准:通过比较不同点云的3DSC描述子,可以进行点云配准。
- 物体识别:在3D物体识别中,3DSC描述子用于描述物体表面的局部几何特征。
- 形状匹配:在点云数据中的局部形状匹配任务中,3DSC可以有效地提取局部特征。
二、代码实现
2.1关键函数
2.1.1 法线计算
void computeNormals(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals)
{
pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> ne;
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
ne.setNumberOfThreads(10); // 使用10线程加速计算
ne.setInputCloud(cloud); // 输入点云
ne.setSearchMethod(tree); // 搜索方法
ne.setKSearch(10); // 设置近邻点数量
ne.compute(*normals); // 计算法线
}
2.1.2 3DSC特征计算
void compute3DSCDescriptors(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals, pcl::PointCloud<pcl::ShapeContext1980>::Ptr descriptors)
{
pcl::ShapeContext3DEstimation<pcl::PointXYZ, pcl::Normal, pcl::ShapeContext1980> sc;
sc.setInputCloud(cloud); // 输入点云
sc.setInputNormals(normals); // 输入法线
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
sc.setSearchMethod(tree); // 设置搜索方法
sc.setMinimalRadius(0.02); // 设置最小半径
sc.setRadiusSearch(0.03); // 设置搜索半径
sc.setPointDensityRadius(0.02); // 设置点密度半径
sc.compute(*descriptors); // 计算3DSC描述子
}
2.1.3 可视化3DSC直方图
void visualize3DSC(pcl::PointCloud<pcl::ShapeContext1980>::Ptr descriptors)
{
pcl::visualization::PCLPlotter plotter("3DSC Descriptor Plot");
plotter.setTitle("3D Shape Context Descriptors");
plotter.setShowLegend(true);
plotter.addFeatureHistogram(*descriptors, "shape_context", 5); // 选取第五个点的特征可视化
plotter.setWindowSize(800, 600); // 设置窗口大小
plotter.plot();
}
2.2完整代码
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d_omp.h>
#include <pcl/features/3dsc.h> // 3D形状描述子
#include <pcl/search/kdtree.h>
#include <pcl/visualization/pcl_plotter.h> // 直方图的可视化
using namespace std;
// 法线计算
void computeNormals(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals)
{
pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> ne;
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
ne.setNumberOfThreads(10); // 使用10线程加速计算
ne.setInputCloud(cloud); // 输入点云
ne.setSearchMethod(tree); // 搜索方法
ne.setKSearch(10); // 设置近邻点数量
ne.compute(*normals); // 计算法线
}
// 计算3DSC描述子
void compute3DSCDescriptors(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals, pcl::PointCloud<pcl::ShapeContext1980>::Ptr descriptors)
{
pcl::ShapeContext3DEstimation<pcl::PointXYZ, pcl::Normal, pcl::ShapeContext1980> sc;
sc.setInputCloud(cloud); // 输入点云
sc.setInputNormals(normals); // 输入法线
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
sc.setSearchMethod(tree); // 设置搜索方法
sc.setMinimalRadius(0.02); // 设置最小半径
sc.setRadiusSearch(0.03); // 设置搜索半径
sc.setPointDensityRadius(0.02); // 设置点密度半径
sc.compute(*descriptors); // 计算3DSC描述子
}
// 直方图可视化
void visualize3DSC(pcl::PointCloud<pcl::ShapeContext1980>::Ptr descriptors)
{
pcl::visualization::PCLPlotter plotter("3DSC Descriptor Plot");
plotter.setTitle("3D Shape Context Descriptors");
plotter.setShowLegend(true);
plotter.addFeatureHistogram(*descriptors, "shape_context", 5); // 选取第五个点的特征可视化
plotter.setWindowSize(800, 600); // 设置窗口大小
plotter.plot();
}
int main(int argc, char** argv)
{
// 1. 加载点云数据
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
if (pcl::io::loadPCDFile<pcl::PointXYZ>("person2.pcd", *cloud) == -1)
{
PCL_ERROR("Could not read file\n");
return -1;
}
// 2. 计算法线
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>());
computeNormals(cloud, normals);
cout << "法线计算完毕!" << endl;
// 3. 计算3DSC描述子
pcl::PointCloud<pcl::ShapeContext1980>::Ptr descriptors(new pcl::PointCloud<pcl::ShapeContext1980>());
compute3DSCDescriptors(cloud, normals, descriptors);
cout << "3DSC特征描述子计算完毕!" << endl;
// 4. 可视化3DSC直方图
visualize3DSC(descriptors);
return 0;
}