我目前正在使用 Python3 中的
skspatial
包。我目前有两个功能:
skspatial.objects.Cylinder.best_fit
尝试将点最好地拟合到圆柱体中skspatial.objects
对象“扩展” Cuboid
,但实际上只是一个边界框。我的问题如下:有没有办法确定这两种形状中哪一个更好地包含散点?对于同一组分散点,它们都返回有效的
cylinder
或 Cuboid
对象,但只有其中一个实际上更适合点。
如果这个问题很重要,散点仅代表它们实际所在形状的表面,因此物体“内部”没有点。
我决定用我在上面评论中给出的解释来测试我自己的指标。
方法如下:假设我们知道任一形状(圆柱体或长方体)是目标(从技术上讲,所有形状都可以在给定其中心坐标的 3D 空间中进行点反射/镜像),那么我们可以确定百分比不在任一形状表面上的点:
定义错误计数器变量
errors = 0
。
确定形状的中心。
对于圆柱体,它将是
Point(cylinder.point + cylinder.vector * 0.5)
。对于长方体,它将是从 (x_min, y_min, z_min)
点到 (x_max, y_max, z_max)
点的线的中间。在 skspatial
中,这将由 Line.from_points(p_min, p_max).to_point(0.5)
完成。
point
,从之前计算的中心点到各个点画一条线:point_center_line = Line.from_points(center, point)
point_center_line
与圆柱体或长方体形状相交时返回的两个交点。由于我们的形状是“空心”的,并且线穿过形状的中心,因此总会有 2 个交点 a
和 b
:a, b = shape.intersect_line(point_center_line)
a
和 b
构造一条线。这条线的长度为2 * (length_of_point_center_line +- delta)
。 delta
是从 a 或 b(以较近者为准)到个体 point
的直线长度。 +-
是因为该点要么仍在形状本身内,要么就在形状外部。我们现在可以检查
delta
是否在指定的容差范围内:
delta = abs(length_of_point_center_line - length_of_a_b_line / 2)
if delta > tolerance:
errors += 1
errors / number_of_points
这将为点云(实际上来自圆柱体形状的物体)提供在我的用例中的以下输出:
Fitting error for Cuboid.best_fit: 0.951777280636341
Fitting error for Cylinder.best_fit: 0.0019885657469550086
由于长方体完全拟合圆柱点云,因此圆柱点实际上位于长方体表面上的点只有少数。然而,对于圆柱体,大多数点都在表面的公差范围内,只有 0.19% 的点在该公差范围之外。
有了这个,我可以简单地检查返回值并采用百分比较低的函数。