首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >最优PCL模板对齐设置

最优PCL模板对齐设置
EN

Stack Overflow用户
提问于 2019-04-25 14:29:50
回答 2查看 969关注 0票数 1

我得到两点云(以毫米为单位),一个是从标准物体(99999点)中取样的“网格”,第二个是由3D凸轮拍摄的物体的点云(约30841点)。我正在使用这个PCL教程的代码进行模板匹配:alignment.php。在此之后,我将使用PCL ICP代码进行最终校准。但是,从模板对齐的角度来看,我仍然得到了相当糟糕的初始猜测。(例如,不轮换,半赛,.)

我尝试从以下几个方面更改设置:

代码语言:javascript
运行
复制
normal_radius_(0.02f)
feature_radius_(0.02f)
min_sample_distance_(0.05f)
max_correspondence_distance_(0.01f * 0.01f)
nr_iterations_(50)

对此:

代码语言:javascript
运行
复制
normal_radius_(2.0f)
feature_radius_(2.0f)
min_sample_distance_(0.5f)
max_correspondence_distance_(1.0f * 1.0f)
nr_iterations_(1000)

有谁能给我一些改进代码的建议吗?谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-02 01:13:08

与分辨率有关的参数也应与点云的分辨率相关联。对象大小相关的Parameret也应该根据对象的大小来设置。

下面是一些例子:

  • normal_radius: 4-8 * <resolution> 为了计算好的法线,下垫面必须有足够的点来表示一个稳定的曲面。如果您的单元位于mm中,那么您就选择了2mm的半径,这太小了。
  • feature_radius: 1-2 * <normal_radius> 计算特性和法线也是如此。
  • max_correspondence_distance: --您将这个值设置为1mm*1mm,这意味着,通讯员只能是1mm,才能被归类为通信。在这里,使用与对象大小相关的值是很重要的。你应该扪心自问:“我的对象和引用之间的最大允许距离是多少,这样我的对象仍然是匹配的?”如果您正在比较faces,则应该使用一些centimeters,例如1cm-5cm,因为脸相当小。但是假设你想要比较像建筑物这样的大物体。在那里,您可以在1m之前使用值。
  • 这里的min_sample_distance:max_correspondence_distance几乎一样。你应该扪心自问:“一个样本离另一个样本有多远?”值越小,你得到的样本就越多。同样,选择一个值,它是对象大小的一小部分,但也要考虑它不应该小于云的分辨率。您将其设置为0.5mm,这太小了。
  • nr_iterations:通常不那么重要,但100-500之间的值是合理的。
票数 1
EN

Stack Overflow用户

发布于 2019-05-02 05:44:25

normal_radius_

  • 根据你的云的密度来选择(你希望它足够大来捕捉环境中的足够多的点-如果它太小,正常将是噪音,直到完成垃圾或无法计算)
  • 考虑到云的平滑性(你希望它足够小,这样就可以正确地将本地环境近似于一架飞机--如果它太大,正常情况就会太平滑,而忽略小细节)

min_sample_distance_

  • 主要是计算方面。取样距离越大,工作速度越快。
  • 如果它太大,你就会失去对齐的准确性。

feature_radius_

  • 你需要考虑你有多大的区分结构/形状。
  • 例如,我的特征半径约为模型大小的十分之一,我已经取得了成功。

max_correspondence_distance_

  • 取决于你的开始条件-两个对应的点能有多远。使用一些启发式提供一个初始猜测可以帮助您减少这个参数,并提高性能和结果。
  • 请注意,这是平方距离。

在您的例子中是(同一对象的两个云),如果您的云有法线,那么完全不用SampleConsensusInitialAlignment就可以实现一个很好的初始猜测。只需对齐两种云的平均法线。您可以将以下方法应用于两种云,以便将它们置于“规范化”位置和方向:

代码语言:javascript
运行
复制
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);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55851744

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档