Engee 文档
Notebook

公差内紧密间隔点的平均

让我们展示如何减少图形上的点的数量,只留下那些与其他点不同的点。

初始数据

让我们使用文件中的函数 peaks.jl,这将创建一个光滑的表面,在[-3.3],[-3.3]范围内有几个突起。 让我们沿着Z轴添加一些噪声到数据中。 现在点云不再位于一个表面上,而是分散在它周围。

In [ ]:
Pkg.add(["Statistics", "GroupSlices"])
In [ ]:
gr( format=:png ) # Обратите внимание, теперь все графики, в рамках
                  # текущей рабочей сессии, будут выводиться в PNG

include( "$(@__DIR__)/peaks.jl" );

xy = rand(10000, 2) .* 6 .- 3; 
z = peaks.( xy[:,1], xy[:,2] ) .+ 0.5 .- rand(10000,1);
A = [xy z]

scatter( A[:,1], A[:,2], A[:,3], camera=(45, 20), ms=2, markerstrokewidth=0.1, leg=false )
Out[0]:
No description has been provided for this image

恢复光滑表面

在这个点云中,我们将寻找那些可以根据以下标准组合的点:

*点之间的距离不超过 tol.
*我们对Z轴不感兴趣,我们只比较X和Y。

In [ ]:
tol = 0.33;

为了识别相同的区域,我们通过将每个点的所有坐标舍入到整数来舍入原始数据集,首先乘以 1/tol.

In [ ]:
aA = round.( (1/tol) .* A[:,1:2], digits=0);

我们的矩阵现在由大量具有相同值的向量组组成。 我们如何将它们分组? 您可以将矢量相互零碎地进行比较,但以更短的方式进行比较。

可以使用函数执行此操作 groupslices 从图书馆 GroupSlices (如有必要,要设置它,请取消注释并执行以下单元格):

In [ ]:
#]add GroupSlices
In [ ]:
using GroupSlices
C = groupslices( aA, dims=1 );

功能 groupslices 对于矩阵的每行r,返回与r相同的第一个遇到行的索引*。

让我们平均每个子组中的点。

In [ ]:
using Statistics
avgA = [  mean( A[C .== c, :], dims=1) for c in unique( C ) ]
avgA = vcat( avgA... ); # Мы получили матрицу из матриц; осуществим вертикальную конкатенацию строчек

现在我们可以从平均点构建一个图形,并为自己指出,尽管数据集没有结构化,但我们已经摆脱了沿Z轴的可变性,保留了源数据的一般外观。

In [ ]:
scatter( A[:,1], A[:,2], A[:,3], camera=(45, 20), ms=2, markerstrokewidth=0.1, leg=false )
scatter!( avgA[:,1], avgA[:,2], avgA[:,3], color=:red, ms=3, legend=false )
Out[0]:
No description has been provided for this image

通过如下着色可以看到各个区域:

In [ ]:
scatter( A[:,1], A[:,2], A[:,3], camera=(45, 20), ms=2, markerstrokewidth=0.1, leg=false, zcolor=C./maximum(C), c=:prism )
scatter!( avgA[:,1], avgA[:,2], avgA[:,3], color=:white, ms=3, legend=false, camera=(0,90) )
Out[0]:
No description has been provided for this image

结论

我们通过选择一些独特的点来过滤掉噪声函数。 在选择它们时,我们依赖于沿X和Y轴的参考点之间的可接受的接近度。