欢迎光临
我们一直在努力

Wolfram Mathematica 三维点云进阶篇——点云分割

MMA点云进阶篇——点云分割篇


目录

MMA点云进阶篇——点云分割篇

前言

一、聚类方法介绍

二、Meanshift聚类介绍

1、算法步骤

三、案例实现

总结                 


前言

随着深度学习的兴起,各种复杂的分割方法如雨后春笋般兴起。但是不应忽视传统方法的基石作用,在某些情况,传统方法在分割上的效果往往好于基于深度学习方法,这已经被许多研究证明。借此点云分割,一起学习和掌握在MMA中使用各种聚类方法。

一、聚类方法介绍

主要介绍FindClusters函数的用法,在MMA中,FindClusters函数支持如下的方法:

  • 其中"KMeans" 和 "KMedoids" 需要显示指定划分的簇数;
  • "DBSCAN"、"JarvisPatrick"、"MeanShift"、"SpanningTree"、 "NeighborhoodContraction" 和 "GaussianMixture" 不用指定划分簇数,会自动寻找可划分的簇数;
  • "Agglomerate"、"Spectral" 和 "SpanningTree" 方法两种情况下都可以。
  • 对于后续的聚类案例,我会使用Meanshift举例。

    二、Meanshift聚类介绍

    The "MeanShift" method iteratively shifts data points toward higher-density regions

    Meanshift是一种基于密度的非参数聚类算法,上面这句话,说明了其核心思想,就是让每个数据点沿着密度增加的方向“漂移”,最终汇聚到密度分布的局部极大值点。而局部的极大值点就代表着簇中心,有多少个这样点,就有多少簇。

    1、算法步骤

  • 初始化:将每个数据点视为一个潜在的中心。

  • 迭代漂移:对于每个点 ,计算其邻域内所有点的加权平均位置 ,然后将点移动到该位置:

     

    其中 K 是核函数,通常采用高斯核。

  • 收敛判断:重复上述步骤,直到所有点的移动距离小于某个容差(即点不再显著变化)

  • 三、案例实现

    选择个一个开放的UAV-Lidar数据集(https://figshare.com/s/9823af091bb401eea612. 但是目前该连接似乎不好用了),该数据集来自纽卡斯尔大学农场内的树木。可视化如下:

    如果直接对三维点云应用聚类,结果十分糟糕,这是因为树冠与树干的特点截然不同,尤其是点云密度,因为该数据来自UAV,从树冠顶部到树干底部的点云密度逐渐减少。

    直接聚类代码

    (*filteredPoints代表已经处理后的点云*)
    clusters = FindClusters[filteredPoints,
    Method -> {"MeanShift", "NeighborhoodRadius" -> 0.2}];

    filteredPoints = Catenate[clusters];

    randomColors = RandomColor[Length[clusters]];(*创建颜色*)

    coloredClusters = MapThread[{#1, Point[#2]} &, {randomColors, clusters}];

    Graphics3D[{PointSize[0.01], coloredClusters}, Axes -> True,
    PlotLabel -> "Clusters by Color"]

    直接聚类结果:

    由于从上到下的点云密度不均匀,直接聚类不可行。考虑树木还具有垂直方向的整体性,即一个树干对应一个树冠。因此尝试对XOY平面应用Meanshift聚类,随后将聚类结果映射到三维点云。

    水平聚类代码

    pointsXY = filteredPoints[[All, {1, 2}]];

    (*Meanshift聚类*)
    clusters =
    FindClusters[pointsXY,
    Method -> {"MeanShift", "NeighborhoodRadius" -> 0.12}];

    Print["簇的数量: ", Length[clusters]];

    (*用 ListPlot 绘制*)
    If[clusters =!= {}, ListPlot[clusters, PlotStyle -> PointSize[0.01],
    AspectRatio -> Automatic,
    PlotLabel -> "DBSCAN Clusters (不同颜色代表不同簇)"],
    Print["没有找到任何簇(全部为噪声)"]]

    聚类结果映射

    这段代码中,最难的就是映射到三维。需要分开看在Table[]里面有一个 nf[#, {1, tolerance}] & /@ cluster,其含义是对于平面聚类后的结果cluster(pointsXY)在三维点云(filteredPoints)找到最近的一点。

    后面的 //Flatten[#,1] 其主要作用是展平列表,可以理解为去除一层括号。因为,在查找后,点会变成这样:{ {{x1,y1,z1}}, {{x2,y2,z2}} },三层括号,在后续可视化会出现问题,于是要去掉一层,其中 // 是后缀操作符,将左边的结果作为参数传递给右边的函数。

    这里还有一个Table[]用法,对于Table[……. , {cluster, clusters}]表示,遍历clusters的每一个元素,执行省略号里的规则,并将当前元素赋值给变量cluster。

    (*Nearest 函数在初始点云中映射*)
    nf = Nearest[pointsXY -> filteredPoints];

    (*容差*)
    tolerance = 10^-4;

    (*将二维簇映射到三维簇*)
    clusters3D = Table[[nf[#, {1, tolerance}] & /@ cluster] // Flatten[#, 1] &,
    {cluster, clusters}];

    (*移除可能为空的簇(如果某个簇全部未匹配)*)
    clusters3D = DeleteCases[clusters3D, {}];

    (*可视化*)
    randomColors = RandomColor[Length[clusters3D]];
    coloredClusters = MapThread[{#1, Point[#2]} &, {randomColors, clusters3D}];

    Graphics3D[{PointSize[0.01], coloredClusters}, Axes -> True,
    BoxRatios -> Automatic, PlotLabel -> "3D Clusters (from 2D)"]

    下面就是最终的可视化结果,可见分割效果有了明显提升。

                                 

    总结                 

    借此点云分割,介绍在MMA进行聚类的方法,并以Meanshift为例子,展示具体操作。后续还有更深入的实现,比如,通过一些监督学习的方法能够改进分割的精度,并在更复杂的场景下分割点云。


    以上就是本文全部内容,后面将继续探索MMA在三维点云领域的应用,为MMA的中文资料继续添砖加瓦。

    赞(0)
    未经允许不得转载:171主机测评 » Wolfram Mathematica 三维点云进阶篇——点云分割
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址