【问题标题】:Aligning a point cloud on a grid在网格上对齐点云
【发布时间】:2014-07-27 13:23:50
【问题描述】:

我必须测量两朵云对应点的 Z 距离。 我打算遍历一个云并使用另一云的相同 X 和 Y 计算 Z 坐标之间的距离。 不幸的是,它不起作用,因为在第二个云中的这些 X-Y 坐标上从来没有一个点。我目前的解决方法是在第二个云中搜索第一个云的 X-Y 的最近点。它可以工作,但速度很慢。

有没有办法使用 PCL 在定义的网格上对齐 X 和 Y 坐标点?这样我希望 X-Y 坐标匹配得更好。

编辑 好的,这里有一些图片和更多解释。

顶视图

侧视图

有一个马鞍和马背的扫描图。两者都是独立制作的,但在 Z 轴上对齐 - 两者的 Z 轴是平行的。 我想创建一个图层模型,它正好适合马鞍(不仅仅是一个矩形垫)。

所以给定层的厚度,我想遍历鞍点并找到马背上对应点的 Z 距离。由于 Y 坐标是浮动的,因此马身上几乎没有一个点与马鞍上的 XY 相同。

我想。如果我可以将所有点与给定密度的网格对齐,那么马上面的每个 XY 鞍点都会有一个对应的 XY 点。

【问题讨论】:

  • 你有什么样的数据?什么是对应点:深度图中相同像素位置的点?或最近的邻居(非唯一)?还是点对最小化距离的平方和?
  • @Simson:我添加了一些信息和图片。我希望现在更清楚了。谢谢你的提问!

标签: point-cloud-library


【解决方案1】:

我不确定这是否是您的意思,但也许您所说的“网格”可能就是image plane?因此,您可以使用深度图/深度图像,而不是使用 3D 点云,只需比较相同图像坐标处的两个深度图的值。这将假定记录已经对齐。

如果您只有点云数据,则必须在平面上执行投影(为此,您必须了解相机的内在函数)。

另一个选项可能是使用注册方法(例如ICP)对齐云。然后你也可以get the (sum of) distance(s)获取云的对应点。

【讨论】:

  • 不幸的是,原来的云没有对齐。它们在数据准备的中间步骤中对齐,方法是找到被认为是水平的平面(例如地板)并转换云,使 z 与该平面正交。此外,云是旋转的。云中的图像不会发生变化。在任何转换之后,它都与最初捕获的一样。我找不到使用 at() 方法获取任何其他视角图像的方法。所有关于注册/对齐的 PCL 示例都处理全景图像。我无法将它们应用于我的需求。
  • “云中的图像没有转换。经过任何转换后,它都是最初捕获的。”是什么意思。 ?通过at(x,y) 获得一个点仅适用于有组织的点云。如果云不是从同一角度记录的,我认为这对您没有帮助。我不明白您对 PCL 注册实施的问题。为什么不能像文档中那样使用它:pointclouds.org/documentation/tutorials/…(当然你必须调整 icp 参数)。
  • 对不起,我想不通,这个例子应该如何解决我对齐两个不同对象的两朵云的问题? “......演示使用迭代最近点......它可以确定一个PointCloud是否只是另一个PointCloud的刚性变换”我的点云是不同的对象,而不仅仅是从另一个角度捕获的相同对象。
  • 好吧ICP 通常只是试图最小化任何两个点云之间的距离。显然,如果云是相同的,这种方法效果最好,但也应该使用适当的参数和良好的初始对齐来处理不同的云(如果我理解你的用例,这应该是可能的)。只找到局部最小值可能是个问题,但我认为它值得一试,因为 PCL 的实现很容易使用。
  • +1 感谢您向我介绍 ICP 并分享您的想法!不过,我认为我自己的答案更适合,所以我选择了它。
【解决方案2】:

我已经实现了概念验证并想分享它。不过,我希望有一个“正确”的解决方案——可能是一个 PCL API 函数。

bool alignToGrid( pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud, QMap<QString, float > & grid, int density )
{
    pcl::PointXYZRGBNormal p1;
    p1.r=0;
    p1.g=0;
    p1.b=255;
    QMap<QString, QList<float> > tmpGridMap;
    for( std::vector<pcl::PointXYZRGBNormal, Eigen::aligned_allocator<pcl::PointXYZRGBNormal> >::iterator it1 = cloud->points.begin();
         it1 != cloud->points.end(); it1++ )
    {
        p1.x = it1->x;
        p1.y = it1->y;
        p1.z = it1->z;
        int gridx = p1.x*density;
        int gridy = p1.y*density;
        QString pos = QString("%1x%2").arg(gridx).arg(gridy);
        tmpGridMap[pos].append(p1.z);
    }

    for (QMap<QString, QList<float> >::iterator it =  tmpGridMap.begin(); it!=tmpGridMap.end(); ++it)
    {
        float meanZ=0;

        foreach( float f, it.value() )
        {
            meanZ+=f;
        }
        meanZ /= it.value().size();


        grid[it.key()] = meanZ;
    }
    return true;
}

想法是遍历云并仅留下/创建点,XY 坐标位于定义的网格上。 Kinect 云的 Density 1000 结果大约为 1000。 1 毫米网格。 网格点周围的所有点都用于构建 Z 平均值。 云保持不变。输出是 xy 位置到 Z 的映射。XY 位置存储在字符串中(我知道很奇怪)作为 x。使用这张地图很容易在其他网格对齐的云中找到对应的 XY 点。

现在我可以使用任何密度绘制云图。在图像中,例如1 毫米和 1 厘米。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-20
  • 2017-10-04
  • 1970-01-01
  • 1970-01-01
  • 2020-07-09
  • 1970-01-01
相关资源
最近更新 更多