法线

小技巧

我们的网络研讨会 Getting your point cloud ready for your application (为您的应用准备好点云)部分涵盖了法线的相关内容。

介绍

本文介绍了表面法线,如何在Zivid SDK中通过点云计算它们,以及为什么法线是一项有价值的功能。最后,文章还提供了一个带有代码示例的教程。

表面法线是几何曲面的一个重要属性。它表示了垂直于点云中特定点平面的切面的单位向量。由于它是一个向量,因此表面法线包含了三个用于描述3D坐标向量元素(x、y、z),每个元素的范围为-1至1。平面的所有表面法线都是平行的,而球体的表面法线指向所有可能的方向。

法线描述了表面的方向,而法线的变化率描述了表面的曲率。

法线API

跳转到源码

源码

std::cout << "Computing normals and copying them to CPU memory" << std::endl;
const auto normals = pointCloud.copyData<Zivid::NormalXYZ>();
跳转到源码

源码

Console.WriteLine("Computing normals and copying them to CPU memory");
var normals = pointCloud.CopyNormalsXYZ();
跳转到源码

源码

print("Computing normals and copying them to CPU memory")
normals = point_cloud.copy_data("normals")

法线API将计算点云中每个点的法线,并将法线从GPU内存复制到CPU内存。其结果是一个法向量矩阵,每条法线对应输入点云的每个点。法线的大小和输入点云的大小相等。

备注

Zivid SDK中法线API的处理速度非常快,因为其计算是在GPU中并行完成的,而此时点云数据仍在GPU内存中。使用第三方库计算法线可能更耗时:因为CPU计算通常要慢得多,而GPU计算则需要多出一次数据复制过程。查看 点云捕获过程 了解更多信息。

如果您已经有一个缓冲区,那么您可以使用包含模板参数 NormalXYZcopyData ,直接将数据从GPU内存复制到目标缓冲区。

小技巧

  • 使用Zivid SDK中的法线,降采样和转换API可以获得更好的表现,因为GPU执行所有这些计算时, 点云数据仍在GPU内存中时。

  • 为了获得最好的性能,您可以先对点云进行降采样,然后计算法线。

  • 当请求复制法线时,法线将在点云上进行计算。您可以在转换点云后计算法线,使得法线与点云在同一坐标系中。

  • 转换法线需要先转换点云,然后从转换后的点云计算法线。不能只变换法线。

应用中的法线

基于各种原因,不同的应用可能需要从点云计算法线。法线描述了表面的方向,法线的变化率描述了表面的曲率。

使用法线的应用包括基于CAD和基于表面的匹配、边缘检测和基于法线差异的分割算法。网格算法和过滤算法也可以通过法线来移除点云伪像或异常值。例如,几乎垂直于从相机原点到某个点的线的法线可以被判断为伪像并被过滤掉。

使用PCL计算法线并可视化

本教程展示了如何从Zivid点云计算法线,将点云和法线转换为PCL格式,并在3D中将它们可视化为法线贴图。

首先,我们连接到相机并捕获点云。

跳转到源码

源码

std::cout << "Connecting to camera" << std::endl;
auto camera = zivid.connectCamera();

std::cout << "Configuring settings" << std::endl;
Zivid::Settings settings;
for(const auto aperture : { 9.57, 4.76, 2.59 })
{
    std::cout << "Adding acquisition with aperture = " << aperture << std::endl;
    const auto acquisitionSettings = Zivid::Settings::Acquisition{
        Zivid::Settings::Acquisition::Aperture{ aperture },
    };
    settings.acquisitions().emplaceBack(acquisitionSettings);
}

std::cout << "Capturing frame (HDR)" << std::endl;
const auto frame = camera.capture(settings);
const auto pointCloud = frame.pointCloud();

然后计算点云的法线。

跳转到源码

源码

std::cout << "Computing point cloud normals" << std::endl;
const auto normals = pointCloud.copyData<Zivid::NormalXYZ>();

我们再将点云和法线转换为PCL格式。

跳转到源码

源码

std::cout << "Creating PCL point cloud structure" << std::endl;
const auto data = pointCloud.copyData<Zivid::PointXYZColorRGBA>();
const auto pointCloudPCL = convertToPCLPointCloud(data);
std::cout << "Creating PCL normals structure suited for visualization" << std::endl;
const auto pointCloudWithNormalsPCL = convertToPCLVisualizationNormals(data, normals);

最后,我们在3D中可视化点云和法线。

跳转到源码

源码

std::cout << "Visualizing normals" << std::endl;
visualizePointCloudAndNormalsPCL(pointCloudPCL.makeShared(), pointCloudWithNormalsPCL.makeShared());

版本历史

SDK

变更

2.8.0

Zivid Studio新增了法线图显示功能

2.5.0

添加了法线API。