PCL 计算3DSC并可视化【2024最新版】

264 篇文章 ¥19.90 ¥99.00
本文介绍了PCL库中3D形状上下文(3DSC)的计算原理和应用,包括算法概述、原理详解及代码实现,强调3DSC在3D点云中的作用,以及如何通过LRF解决方向歧义问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

本文由CSDN点云侠原创,原文链接,首发于:2021年2月7日。博客长期更新,本文最近一次更新时间为:2024年10月10日,代码在PCL1.14.1测试通过。抄袭狗把自己当个狗!!!

一、算法原理

1、原理概述

pcl::ShapeContext3DEstimation
3D形状上下文描述符的约定是:

  • 如果不能估计查询点的最近邻居,则特性描述符将设置为NaN(不是数字),RF设置为0
  • 对于一个没有有限三维坐标的点,估计三维形状上下文描述符是不可能的。因此,在x、y或z上包含NaN数据的任何点都将其边界特征属性设置为NaN。
<think>我们被要求使用PCL计算3D Shape Context (3DSC)特征实现可视化。根据引用[3]和[4],3DSC是一种局部特征描述子,通过将点的局部邻域映射到球坐标系划分网格来统计点分布。 步骤: 1. 读取点云 2. 估计法线(因为3DSC需要局部坐标系,以法线为参考) 3. 计算3DSC特征 4. 可视化特征 注意:PCL3DSC特征描述子的类为`pcl::ShapeContext3DEstimation`。 代码框架: ```cpp #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/features/normal_3d.h> #include <pcl/features/3dsc.h> // 注意:3DSC在PCL中对应的头文件 #include <pcl/visualization/pcl_plotter.h> // 用于绘制特征直方图 int main() { // 1. 读取点云 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::io::loadPCDFile("input.pcd", *cloud); // 2. 计算法线 pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimation; normal_estimation.setInputCloud(cloud); pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>()); normal_estimation.setSearchMethod(tree); pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>); normal_estimation.setRadiusSearch(0.03); // 设置法线估计半径 normal_estimation.compute(*normals); // 3. 创建3DSC估计器 pcl::ShapeContext3DEstimation<pcl::PointXYZ, pcl::Normal, pcl::ShapeContext1980> sc3d; sc3d.setInputCloud(cloud); sc3d.setInputNormals(normals); sc3d.setSearchMethod(tree); sc3d.setRadiusSearch(0.05); // 设置搜索半径,用于确定邻域 // 4. 计算特征 pcl::PointCloud<pcl::ShapeContext1980>::Ptr descriptors(new pcl::PointCloud<pcl::ShapeContext1980>()); sc3d.compute(*descriptors); // 5. 可视化:可以输出某个点的描述子绘制直方图 // 例如,输出第一个点的描述子 std::cout << "Descriptor for point 0: " << std::endl; for (size_t i = 0; i < descriptors->at(0).descriptor.size(); ++i) { std::cout << descriptors->at(0).descriptor[i] << " "; if ((i+1) % 10 == 0) std::cout << std::endl; } std::cout << std::endl; // 使用PCLPlotter绘制直方图 pcl::visualization::PCLPlotter plotter; plotter.addFeatureHistogram(*descriptors, 1980); // 1980是描述子的长度(3DSC1980) plotter.plot(); return 0; } ``` 注意: - 3DSC描述子在PCL中实现为`pcl::ShapeContext1980`,因为描述子长度为1980(默认划分方式:径向12段,方位角11段,俯仰角15段,共12*11*15=1980个区间)[^3]。 - 设置搜索半径时,需要根据点云的密度调整,通常设置为点云平均间距的几倍。 - 法线估计的半径也需要根据点云密度调整。 可视化:这里使用PCLPlotter绘制特征直方图。另外,也可以考虑使用其他方式可视化,例如将描述子值映射到颜色显示在点云上,但这需要将高维描述子降维(如PCA)后映射到RGB颜色。 另一种可视化方法:将描述子中值最大的几个维度作为颜色分量(例如取前三个维度归一化后作为RGB): ```cpp pcl::PointCloud<pcl::PointXYZRGB>::Ptr colored_cloud(new pcl::PointCloud<pcl::PointXYZRGB>); colored_cloud->resize(descriptors->size()); for (size_t i=0; i<descriptors->size(); ++i) { pcl::PointXYZRGB pt; pt.x = cloud->at(i).x; pt.y = cloud->at(i).y; pt.z = cloud->at(i).z; // 取描述子的前三个维度(注意:这里需要归一化,因为描述子每个维度的值可能范围不同) float r = descriptors->at(i).descriptor[0]; float g = descriptors->at(i).descriptor[1]; float b = descriptors->at(i).descriptor[2]; // 归一化到0~255(这里简单处理,实际可能需要根据整个描述子集进行归一化) float max_val = *std::max_element(descriptors->at(i).descriptor.begin(), descriptors->at(i).descriptor.end()); r = 255 * (r / max_val); g = 255 * (g / max_val); b = 255 * (b / max_val); pt.r = static_cast<uint8_t>(r); pt.g = static_cast<uint8_t>(g); pt.b = static_cast<uint8_t>(b); colored_cloud->at(i) = pt; } // 保存或显示 pcl::io::savePCDFile("colored_by_3dsc.pcd", *colored_cloud); ``` 然后可以用PCL可视化工具查看上色的点云。 注意:这种方法只能显示描述子的前三个维度,可能不能完全代表描述子的全部信息,但可以直观地看到不同区域描述子的差异。 引用说明: [^1]: 3DSC算法计算点云描述子。 [^3]: PCL 计算3DSC可视化。 [^4]: PCL 计算3DSC可视化。 相关问题: 1. 3DSC特征描述子的参数(如径向、方位角、俯仰角的划分)如何调整? 2. 除了3DSC,PCL还支持哪些局部特征描述子? 3. 如何评估3DSC特征在点云匹配中的性能? 4. 3DSC特征描述子的长度是多少?如何解释其直方图? 5. 在计算3DSC时,如果点云没有法线信息,有哪些替代方法?</think>### PCL 计算 3D Shape Context (3DSC) 特征可视化方法 #### 一、3DSC 算法原理概述 3D Shape Context (3DSC) 是一种基于球坐标系的局部特征描述子,通过将点云局部邻域划分为球坐标系网格统计点分布特征来生成描述向量[^3][^4]。其核心计算步骤: 1. **建立局部坐标系** 以目标点 $p$ 为中心,以其法向量 $n$ 为 Z 轴(北极方向)建立局部参考系 2. **球坐标系划分** 将空间划分为三个维度的网格: - 径向距离 $r$(从中心向外) - 方位角 $\theta$(水平方向) - 俯仰角 $\phi$(垂直方向) 3. **特征统计** 计算每个网格单元内的加权点数,形成特征直方图(默认维度为 $12 \times 11 \times 15 = 1980$ 维)[^3] #### 二、PCL 实现步骤与代码 ##### 1. 环境配置 ```cpp #include <pcl/io/pcd_io.h> #include <pcl/features/normal_3d.h> #include <pcl/features/3dsc.h> // 3DSC特征计算 #include <pcl/visualization/pcl_plotter.h> // 特征可视化 #include <pcl/visualization/cloud_viewer.h> ``` ##### 2. 完整计算流程 ```cpp // 1. 读取点云 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::io::loadPCDFile("input.pcd", *cloud); // 2. 计算法线(3DSC依赖法线方向) pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne; pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>); pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>()); ne.setInputCloud(cloud); ne.setSearchMethod(tree); ne.setRadiusSearch(0.03); // 法线估计半径 ne.compute(*normals); // 3. 计算3DSC特征 pcl::ShapeContext3DEstimation<pcl::PointXYZ, pcl::Normal, pcl::ShapeContext1980> sc; sc.setInputCloud(cloud); sc.setInputNormals(normals); sc.setSearchMethod(tree); sc.setRadiusSearch(0.05); // 特征计算半径 pcl::PointCloud<pcl::ShapeContext1980>::Ptr descriptors(new pcl::PointCloud<pcl::ShapeContext1980>()); sc.compute(*descriptors); ``` #### 三、特征可视化方法 ##### 方法1:直方图可视化PCLPlotter) ```cpp // 选择目标点(示例取索引0的点) int target_index = 0; // 创建直方图绘制器 pcl::visualization::PCLPlotter plotter; plotter.addFeatureHistogram<pcl::ShapeContext1980>(*descriptors, 1980, target_index, "3DSC Descriptor"); // 设置显示范围 plotter.setYRange(0, *std::max_element(descriptors->at(target_index).descriptor.begin(), descriptors->at(target_index).descriptor.end()) * 1.2); plotter.plot(); // 显示直方图 ``` ##### 方法2:点云着色可视化 ```cpp pcl::PointCloud<pcl::PointXYZRGB>::Ptr colored_cloud(new pcl::PointCloud<pcl::PointXYZRGB>); colored_cloud->resize(cloud->size()); // 将描述子值映射到颜色 for (size_t i = 0; i < cloud->size(); ++i) { // 取描述子前3个维度作为RGB分量 float r = descriptors->at(i).descriptor[0]; float g = descriptors->at(i).descriptor[1]; float b = descriptors->at(i).descriptor[2]; // 归一化到[0,255] float max_val = std::max({r, g, b}); r = 255 * r / max_val; g = 255 * g / max_val; b = 255 * b / max_val; pcl::PointXYZRGB pt; pt.x = cloud->at(i).x; pt.y = cloud->at(i).y; pt.z = cloud->at(i).z; pt.r = static_cast<uint8_t>(r); pt.g = static_cast<uint8_t>(g); pt.b = static_cast<uint8_t>(b); colored_cloud->at(i) = pt; } // 可视化着色点云 pcl::visualization::CloudViewer viewer("3DSC Feature Visualization"); viewer.showCloud(colored_cloud); while (!viewer.wasStopped()) {} // 保持显示 ``` #### 四、关键参数说明 | 参数 | 类型 | 默认值 | 作用 | |------|------|--------|------| | `setRadiusSearch()` | float | 需指定 | 特征计算邻域半径[^3] | | `setMinimalRadius()` | float | 0.1 | 最小径向距离 | | `setPointDensityRadius()` | float | 0.2 | 点密度估计半径 | | `setRadialBins()` | int | 5 | 径向划分数 | | `setAzimuthBins()` | int | 6 | 方位角划分数 | | `setElevationBins()` | int | 11 | 俯仰角划分数 | **调整示例**: ```cpp sc.setRadialBins(6); // 增加径向划分 sc.setAzimuthBins(12); // 增加方位角划分 sc.setElevationBins(10); // 减少俯仰角划分 ``` #### 五、应用场景 1. **点云配准**:通过匹配3DSC特征实现精确配准 2. **物体识别**:比较目标物体与场景的3DSC特征 3. **形状检索**:在数据库中检索相似形状物体 4. **特征分析**:研究局部几何结构特性[^4]
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点云侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值