最佳 PCL 模板对齐设置
Optimal PCL Template Alignment setup
我有2个点云(以mm为单位),一个是"mesh"从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)
有人可以给我一些如何改进这段代码的提示吗?谢谢!
分辨率相关的参数也应根据点云的分辨率设置。
object-size-dependent 的参数也应该根据对象的大小进行设置。
一些示例:
normal_radius: 4-8 * <resolution>
要计算 good 法线,底层表面必须有足够的点来表示稳定的表面。如果您的单位是 mm
,那么您选择的半径 2mm
太小了。
feature_radius: 1-2 * <normal_radius>
计算 features 与 normals. 相同
max_correspondence_distance:
你把这个值设置为1mm*1mm
,也就是说,信件只能相隔1mm
才能归类为信件。在这里使用与对象大小相关的值很重要。你应该问问自己,"What's the maximum allowed distance between my object and reference such that my object is still a match?" 如果你在比较人脸,你应该使用一些 centimeter
,例如1cm-5cm
,因为脸比较小。但是假设你想比较像建筑物这样的大物体。在那里您可以使用最大 1m
. 的值
min_sample_distance:
这里几乎与 max_correspondence_distance
相同。你应该问问自己,"How much should a sample be distant from another sample?"。值越小,您获得的样本越多。同样,选择一个对象大小的一小部分的值,但也要考虑到它不应小于云的分辨率。您将其设置为 0.5mm
,这太小了。
nr_iterations:
通常不是那么重要,但 100-500
之间的值是合理的。
normal_radius_:
- 根据你的云密度选择(你希望它足够大以捕获环境中的足够点 - 如果它太小,法线会很嘈杂,向上完成垃圾或计算失败)
- 考虑云的平滑度(您希望它足够小,以便将局部环境近似为平面是正确的 - 如果它太大,法线会太平滑而忽略小细节)
min_sample_distance_:
- 主要是计算方面。采样距离越大,速度越快
- 如果它太大,就会降低对齐的准确性。
feature_radius_:
- 你需要考虑你在多大尺度上有辨别力structures/shapes
- 以人脸为例,我成功地使用了大约模型大小 1/10 的特征半径。
max_correspondence_distance_:
- 取决于你的起始条件——2个对应点能走多远。使用一些启发式方法提供初始猜测可以帮助您减少此参数,并提高性能和结果。
- 注意这是平方距离
在您的情况下(同一对象的两个云),如果您的云具有法线,则可以在根本不使用 SampleConsensusInitialAlignment 的情况下实现良好的初始猜测。简单地对齐两个云的平均法线。您可以对两朵云应用以下方法,将它们置于 "normalized" 位置和方向:
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);
}
我有2个点云(以mm为单位),一个是"mesh"从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)
有人可以给我一些如何改进这段代码的提示吗?谢谢!
分辨率相关的参数也应根据点云的分辨率设置。 object-size-dependent 的参数也应该根据对象的大小进行设置。
一些示例:
normal_radius: 4-8 * <resolution>
要计算 good 法线,底层表面必须有足够的点来表示稳定的表面。如果您的单位是mm
,那么您选择的半径2mm
太小了。feature_radius: 1-2 * <normal_radius>
计算 features 与 normals. 相同
max_correspondence_distance:
你把这个值设置为1mm*1mm
,也就是说,信件只能相隔1mm
才能归类为信件。在这里使用与对象大小相关的值很重要。你应该问问自己,"What's the maximum allowed distance between my object and reference such that my object is still a match?" 如果你在比较人脸,你应该使用一些centimeter
,例如1cm-5cm
,因为脸比较小。但是假设你想比较像建筑物这样的大物体。在那里您可以使用最大1m
. 的值
min_sample_distance:
这里几乎与max_correspondence_distance
相同。你应该问问自己,"How much should a sample be distant from another sample?"。值越小,您获得的样本越多。同样,选择一个对象大小的一小部分的值,但也要考虑到它不应小于云的分辨率。您将其设置为0.5mm
,这太小了。nr_iterations:
通常不是那么重要,但100-500
之间的值是合理的。
normal_radius_:
- 根据你的云密度选择(你希望它足够大以捕获环境中的足够点 - 如果它太小,法线会很嘈杂,向上完成垃圾或计算失败)
- 考虑云的平滑度(您希望它足够小,以便将局部环境近似为平面是正确的 - 如果它太大,法线会太平滑而忽略小细节)
min_sample_distance_:
- 主要是计算方面。采样距离越大,速度越快
- 如果它太大,就会降低对齐的准确性。
feature_radius_:
- 你需要考虑你在多大尺度上有辨别力structures/shapes
- 以人脸为例,我成功地使用了大约模型大小 1/10 的特征半径。
max_correspondence_distance_:
- 取决于你的起始条件——2个对应点能走多远。使用一些启发式方法提供初始猜测可以帮助您减少此参数,并提高性能和结果。
- 注意这是平方距离
在您的情况下(同一对象的两个云),如果您的云具有法线,则可以在根本不使用 SampleConsensusInitialAlignment 的情况下实现良好的初始猜测。简单地对齐两个云的平均法线。您可以对两朵云应用以下方法,将它们置于 "normalized" 位置和方向:
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);
}