CloudCompare——计算点云的法向量【2025最新版】

本文详细介绍了如何计算和处理点云的法线,包括使用最小二乘拟合、最小生成树和快速 marching 算法。还展示了法线计算结果的可视化,以及如何通过 HSV 转换和 Dip & Dip direction SFs 来进一步分析点云数据。同时,提供了反转法线方向的方法,并探讨了不同方法对点云外观的影响。
该文章已生成可运行项目,

本文由CSDN点云侠原创,首发于:2022年8月25日。博客长期更新,本文最新更新时间为:2025年1月11日。对最新论文阅读进行整理,添加法向量实现原理。

1.实现原理

内容来自:论文截图。计算法向量的方法有几十种,这只是最常用的一种。
在这里插入图片描述

2.Computing normals on a cloud

  通过菜单栏的'Edit > Normals > Compute'找到该功能。
在这里插入图片描述
设置相关参数
在这里插入图片描述

  如果进行计算的实体对象是点云,那么需要设置以下几个参数:

  • local surface model:选择使用最小二乘拟合平面、二次曲面拟合或三角网。
  • Neighbors->Octree->radius:局部球体邻域的半径。如果设置的太小(即没有足够的点来计算局部模型),那么法线值将默认为(0,0,1)。如果设置的太大,计算的过程可能会很长,结果会很平滑。
  • Orientation:让用户指定一个简单的启发式来设置法线方向(最好是在表面之外)。
  • Orientation->Use preferred orientation :使用如下方式设置点云法线的朝向(+Z与Z轴正方向同向)
    在这里插入图片描述
  • Orientation->Use minimum Spanning Tree :使用最小代价生成树调整点云法线的朝向

注意:

  • 如果没有指定首选方向,或者结果仍然不一致,可能需要使用更高级的算法——‘Normals > Orient Normals > With Minimum Spanning Tree’,来确定法线的方向。
    在这里插入图片描述

  • 在任何情况下,都可能需要使用invert方法对法线字段进行全局反转。
    在这里插入图片描述

3.点云法线计算结果

  法线实体的外观变化取决于光线相对于法线的方向:

  • 对于点云来说,法线向后的点呈现黑色。
    在这里插入图片描述
      保存成txt格式,打开则可以看到在原来XYZ坐标后边多了法向量的值。
    在这里插入图片描述
      保存成pcd格式,使用PCL进行法向量可视化。
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>

using namespace std;

int
main(int argc, char** argv)
{
    pcl::PointCloud<pcl::PointNormal>::Ptr cloud(new pcl::PointCloud<pcl::PointNormal>);

    if (pcl::io::loadPCDFile<pcl::PointNormal>("bunny.pcd", *cloud) == -1)
    {
        PCL_ERROR("Could not read file\n");
    }
    //---------------------可视化(含法线)-----------------------------
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("CloudCompare-XYZNormal viewer"));
    viewer->setWindowName("CloudCompare-XYZNormal");
    viewer->addText("CloudCompare-PointNormal", 50, 50, 0, 1, 0, "v1_text");
    viewer->addPointCloud<pcl::PointNormal>(cloud, "CloudCompare-XYZNormal");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "CloudCompare-XYZNormal");
    viewer->addPointCloudNormals<pcl::PointNormal>(cloud, 20, 0.02, "normals");

    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }

    return 0;
}

在这里插入图片描述

4.反转法线方向(Normals > Invert)

  该工具用来反转所选实体的法线。可以通过Edit > Normals > Invert菜单访问。
法线实体的外观变化取决于光线相对于法线的方向:

  • 对于点云来说,法线向后的点呈现黑色。
  • 对于一个网格(使用默认材质),后向发光的三角形出现在浅蓝色(而前向发光的三角形是绿色)

反转点云的法线方向
在这里插入图片描述
使用PCL可视化
在这里插入图片描述

5. With Minimum Spanning Tree

  这个工具可以通过'Edit > Normals > Orient normals > with Minimum Spanning Tree'菜单访问。
这种方法试图以一致的方式重新定位云的所有法线。它从一个随机的点开始,然后从一个邻居传播到另一个。传播是在最小生成树的帮助下完成的。因此,用户必须指定每个节点上连接的邻居的最大数量(邻居越多,就越准确,但也需要更多的内存和更多的时间)。
使用最小代价生成树调整的结果
在这里插入图片描述

6.With Fast Marching

  这个工具可以通过Edit > Normals > Orient normals > with Fast Marching菜单访问。这种方法试图以一致的方式重新定位云的所有法线。它从一个随机的点开始,然后从一个邻居传播到另一个。传播是通过应用于网格的Fast Marching算法完成的。实际上,这个网格是点云的八叉树,被认为是一个给定的细分级别。因此,用户必须指定此细分级别。问题是找到正确的水平:如果体素分辨率太大(即低水平的细分),传播不是很准确。然而,如果体素分辨率太小(即高水平的细分),可能出现空体素,传播在一次扫描中完成是不可能。
注意:这种方法很快,效率极高。但是不推荐用。

7.HSV colors

  这个工具可以通过Edit > Normals > Convert to > HSV colors菜单访问。用来将点云的法线转换为HSV颜色字段。

H = dip direction, S = dip , V = 1

在这里插入图片描述

8.Dip and Dip direction SFs

  这个工具可以通过Edit > Normals > Convert to > Dip and dip direction SFs菜单访问。
将云的法线转换为两个标量字段:

  • 一个有倾角值
  • 另一个带倾角方向值

注意:角度是以度为单位的。
在这里插入图片描述

9.Clear

  这个工具可以通过Edit > Colors > Clear访问。从选定的实体中移除法线。

10.Computing normals on a mesh

在这里插入图片描述

  • per-vertex:连接到一个顶点的所有三角形的平均法线被分配到这个顶点-光滑的外观,没有保留尖锐的边
  • per triangle:三角形法线被分配到三角形-硬/镶嵌外观,但保留锋利的边缘
    在这里插入图片描述

11.相关链接

[1] PCL 计算点云法向量并显示
[2] PCL 之vtk计算点云模型的法向量

本文章已经生成可运行项目
计算表面法向量并确保其方向朝外时,需要结合几何原理和数据处理策略来完成。以下是一个完整的流程: ### 表面法向量计算 对于三角网格模型中的每个面片,可以通过该面片三个顶点坐标计算出一个垂直于该面片的法向量。假设三角形的三个顶点为 $ A(x_1, y_1, z_1) $、$ B(x_2, y_2, z_2) $ 和 $ C(x_3, y_3, z_3) $,可以构造两个边向量: $$ \vec{AB} = (x_2 - x_1, y_2 - y_1, z_2 - z_1) $$ $$ \vec{AC} = (x_3 - x_1, y_3 - y_1, z_3 - z_1) $$ 然后通过叉积得到该面片的法向量: $$ \vec{N} = \vec{AB} \times \vec{AC} $$ 最后将法向量单位化以方便后续光照等计算: $$ \hat{N} = \frac{\vec{N}}{|\vec{N}|} $$[^1] ### 确保法向量方向朝外 为了确保所有法向量的方向一致且朝向外侧,需要注意以下几点: 1. **统一方向性**:在三角网格中,通常使用右手法则判断法向量的方向。如果三角形的顶点顺序是顺时针排列(从外侧观察),则法向量会指向外部;反之则指向内部。因此,需要确保所有三角形的顶点顺序一致[^2]。 2. **检查封闭性**:模型必须是封闭的,否则无法确定法向量的正确方向。若存在孔洞或缺失的面片,应进行修复[^2]。 3. **基于点云法向量定向**:对于点云数据,可以利用协方差矩阵分析的方法来估计法向量。具体步骤包括: - 对于某一点,选取其 k 个最近邻点。 - 计算这些点的重心,并将数据去中心化。 - 构建协方差矩阵并求解特征向量,最小特征值对应的特征向量即为该点的法向量方向。 - 利用 Open3D 等库实现法向量的定向,使其调整为正确的方向[^4]。 4. **平滑处理**:对于相邻面片,可以通过插值计算平滑的法线,以实现更自然的光照效果[^1]。 ### 示例代码:计算三角网格法向量 以下是一个使用 Python 和 NumPy 的示例代码,用于计算三角网格的法向量并将其单位化: ```python import numpy as np def compute_face_normal(v1, v2, v3): # 计算两个边向量 edge1 = v2 - v1 edge2 = v3 - v1 # 叉积计算法向量 normal = np.cross(edge1, edge2) # 单位化法向量 normal_normalized = normal / np.linalg.norm(normal) return normal_normalized # 三角形顶点坐标 v1 = np.array([0, 0, 0]) v2 = np.array([1, 0, 0]) v3 = np.array([0, 1, 0]) normal = compute_face_normal(v1, v2, v3) print("Surface Normal:", normal) ``` ### 总结 通过上述方法,可以准确计算表面法向量并确保其方向一致地朝向外侧。无论是三角网格还是点云数据,都需要遵循几何原理和数据处理策略来保证结果的正确性。
评论 36
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点云侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值