最佳 PCL 模板对齐设置
Optimal PCL Template Alignment setup
我有 2 个点云(以毫米为单位),一个是从 stl 对象采样的"网格"(99999 点),第二个是从 3D cam 拍摄的这个对象的点云(约 30841 点)。我正在使用此 PCL 教程的代码进行模板匹配:http://pointclouds.org/documentation/tutorials/template_alignment.php。之后,我使用 PCL ICP 代码进行最终对齐。但我仍然从模板对齐中得到相当糟糕的初步猜测。(例如,没有轮换,半场比赛,...)
我尝试从以下位置更改设置:
normal_radius_(0.02f)
feature_radius_(0.02f)
min_sample_distance_(0.05f)
max_correspondence_distance_(0.01f * 0.01f)
nr_iterations_(50)
对此:
normal_radius_(2.0f)
feature_radius_(2.0f)
min_sample_distance_(0.5f)
max_correspondence_distance_(1.0f * 1.0f)
nr_iterations_(1000)
有人可以给我一些提示如何改进此代码吗?谢谢!
与分辨率相关的参数也应根据点云的分辨率进行设置。 与对象大小相关的参数也应根据对象的大小进行设置。
一些例子:
normal_radius: 4-8 * <resolution>
要计算良好的法线,下垫表面必须有足够的点来表示稳定的表面。如果你的单位是mm
,那么你选择的半径是2mm
,这太小了。-
feature_radius: 1-2 * <normal_radius>
计算特征与法线相同。 max_correspondence_distance:
将此值设置为1mm*1mm
,这意味着对应关系只能1mm
分开才能归类为对应关系。 在这里,使用与对象大小相关的值很重要。您应该问自己,"我的对象和参照之间的最大允许距离是多少,以便我的对象仍然是匹配的?如果你正在比较面孔,你应该使用一些centimeter
,例如1cm-5cm
,因为脸相当小。但是,假设您想比较建筑物等大型物体。 在那里,您可以使用最多1m
的值。min_sample_distance:
这里几乎与max_correspondence_distance
相同。您应该问自己,"一个样本与另一个样本的距离应该有多远?值越小,获得的样本就越多。同样,选择一个是对象大小的一小部分的值,但也要考虑到它不应小于云的分辨率。您将其设置为0.5mm
,这太小了。nr_iterations:
通常不是那么重要,但100-500
之间的值是合理的。
normal_radius_:
- 根据云的密度进行选择(您希望它足够大以捕获环境中的足够点 - 如果它太小,法线将是嘈杂的,直到完全垃圾或无法计算)
- 考虑云的平滑度(您希望它足够小,以便将本地环境近似为平面是正确的 - 如果它太大,法线将过于平滑并忽略小细节)
min_sample_distance_:
- 主要是计算方面。采样距离越大,它的工作速度就越快。
- 如果它太大,则会失去对齐的准确性。
feature_radius_:
- 您需要考虑在多大程度上具有判别结构/形状
- 以人脸为例,我成功地将特征半径定为模型大小的 1/10。
max_correspondence_distance_:
- 取决于您的起始条件 - 2 个相应的点可以有多远。使用一些启发式方法提供初始猜测可以帮助您减少此参数,并提高性能和结果。
- 请注意,这是平方距离
在你的例子中(同一对象的两个云),如果你的云有法线,就可以在不使用SampleConsensusInitialAlign的情况下实现一个很好的初步猜测。只需对齐两个云的平均法线即可。您可以将以下方法应用于两个云,以将它们置于"规范化"位置和方向:
void ToOrigin(pcl::PointCloud<pcl::PointXYZINormal>::Ptr cloud, Eigen::Affine3f & transformation, Eigen::Vector3f up, float resolution)
{
// Calc Origin
pcl::PointXYZINormal origin;
auto size = cloud->points.size();
for (auto pointItr = cloud->begin(); pointItr != cloud->end(); pointItr++)
{
origin.getArray3fMap() += pointItr->getArray3fMap() / size;
origin.getNormalVector3fMap() += pointItr->getNormalVector3fMap();
}
origin.getNormalVector3fMap().normalize();
// Calc Transformation
auto proj = origin.getNormalVector3fMap().dot(up) * origin.getNormalVector3fMap();
// the direction that will be rotated to y_axis
// (the part of "up" that is perpendicular to the cloud normal)
auto y_direction = (up - proj).normalized();
// the direction that will be rotated to z_axis
auto z_direction = origin.getNormalVector3fMap();
// the point that will be shifted to origin (0,0,0)
auto center = origin.getArray3fMap();
pcl::getTransformationFromTwoUnitVectorsAndOrigin(y_direction, z_direction, center, transformation);
// Transform
pcl::PointCloud<pcl::PointXYZINormal> cloud_tmp;
pcl::transformPointCloudWithNormals(*cloud, cloud_tmp, transformation);
pcl::copyPointCloud(cloud_tmp, *cloud);
}
相关文章:
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- 如何创建一个QTableWidgetItem,用长文本右对齐,左边有省略号
- 我可以检测和更改 gcc/g++ 中结构的当前数据对齐设置吗?
- 64位机器上的C++内存对齐
- 为什么我可以将变量存储在不是其最小对齐方式的倍数的地址?
- 使 std::vector 分配对齐内存的现代方法
- C++ cout 将双精度对齐到精度 2 并正确对齐
- 在 64 位边界上对齐C++结构数组?
- 使用 g++7 构建的代码在访问未对齐的内存时崩溃
- 在 capnp FlatArrayMessageReader 的对齐内存缓冲区中接收 zmq 消息
- 是否值得对齐变量?
- 初始化派生结构的基部分/意外打包派生结构字段以对齐基结构的间隙
- 对齐和对齐的实际用例C++关键字
- 如何减少代码的运行时间以对齐文本?
- 指向包含对齐 C 结构C++类的 C 指针的对齐问题
- Linux C++ 中的页面对齐内存分配
- C++ 类层次结构中的"对齐"是什么意思?
- 最佳 PCL 模板对齐设置
- 如何以与平台无关的方式设置对齐
- 如何正确设置文件对齐