【问题标题】:How can I find the alpha shape (concave hull) of a 2d point cloud?如何找到二维点云的 alpha 形状(凹壳)?
【发布时间】:2011-10-13 13:52:27
【问题描述】:

我正在寻找一种在二维中计算 alpha 形状的实现。我正在运行 ubuntu。我更喜欢这个任务的命令行实用程序,但也可以使用 python 库。

在 Google 中,我发现了许多计算 alpha 形状的实现。但他们都没有输出我想要的。作为输入,我有一个二维点列表(例如,文本文件中每行一对浮点数)。作为输出,我想要另一个二维点列表具有相同的比例

我已经尝试安装 cgal 的最新 python 绑定,但是这些已经有一段时间不支持并且不再在 Ubuntu 11.04 上编译(我也在 Ubuntu 10.04 上尝试过,但没有运气)。 Clustr,由 Aaron Straup Cope 在 flickr 开发的项目也无法在 Ubuntu 11.04 上编译(可能是因为它也与旧的 CGAL 库相关联)。

我还尝试了来自贝尔实验室的 Ken Clarkson 的 this implementation。它几乎输出了我想要的,输出似乎是另一个比例,它把浮点数变成了整数。

我还尝试了dionysus 的python 绑定。这些已编译,但是当我将点列表提供给函数fill_alpha2D_complex(points, f) 时,输出不是我所期望的。它不是二维点的列表,而是似乎是“持久性图”,我不知道这是什么意思。

有人知道这个问题的简单解决方案吗?

更新:我想打印出与 alpha 形状相关联的点,它处于不再连接的边缘。我认为这意味着“给我与最小 alpha 值相关的点,以便连接形状。”

更新我现在知道了如何从Ken Clarkson's implementation 和(或多或少)从dionysus implementation 获得我想要的东西。 Clarkson 的实现是正确的,它只输出点的索引而不是点本身(与酒神相同的故事),我需要正确设置一些可选标志。我写的包装如下。这个解决方案是理想的,因为它产生了一个既连接又不包含孔的 alpha 形状。 Alpha 是自动设置的。另一方面,狄俄尼索斯不会自动发现这个阿尔法值。另外,Clarkson 的实现可以设置为输出形状的 ps 图像(使用 -afps 标志)。要让克拉克森的代码与非古代版本的 GCC 一起编译,您需要按照here 列出的步骤进行操作。以下代码可用作库或独立包装器:

#!/usr/bin/python -O

import sys, os
import subprocess
import tempfile

hull_path = "./hull.exe"

def get_alpha_shape(points):
    # Write points to tempfile
    tmpfile = tempfile.NamedTemporaryFile(delete=False)
    for point in points:
        tmpfile.write("%0.7f %0.7f\n" % point)
    tmpfile.close()

    # Run hull
    command = "%s -A -m1000000 -oN < %s" % (hull_path, tmpfile.name)
    print >> sys.stderr, "Running command: %s" % command
    retcode = subprocess.call(command, shell=True)
    if retcode != 0:
        print >> sys.stderr, "Warning: bad retcode returned by hull.  Retcode value:" % retcode
    os.remove(tmpfile.name)

    # Parse results
    results_file = open("hout-alf")
    results_file.next() # skip header
    results_indices = [[int(i) for i in line.rstrip().split()] for line in results_file]
#    print "results length = %d" % len(results_indices)
    results_file.close()
    os.remove(results_file.name)

    return [(points[i], points[j]) for i,j in results_indices]

if __name__ == "__main__":
    points = [tuple([float(i) for i in line.rstrip().split()]) for line in sys.stdin]
    for point_i, point_j in get_alpha_shape(points):
        sys.stdout.write("%0.7f,%0.7f\t%0.7f,%0.7f\n" % (point_i[0], point_i[1], point_j[0], point_j[1]))
    sys.exit(0)

【问题讨论】:

  • 一个简单的点列表不能描述一个阿尔法形状,因为它甚至不一定是连接的。
  • 我只想要一个漂亮的点云边界。但如果这个描述不够准确,请参阅我在问题中的更新。
  • 连接的 alpha 形状可能仍然不是很好,即包含孔。
  • 好吧,我更喜欢“漂亮”的形状,但我不精通计算几何的术语,所以我不知道如何描述什么是“漂亮的形状”。但我觉得它具有直观的属性,例如连接,不包含孔等。我也愿意尝试不同的 alpha 值,直到我得到一个“不错”的值。

标签: python linux ubuntu geometry computational-geometry


【解决方案1】:
import alphashape
import numpy as np
from descartes import PolygonPatch
import matplotlib.pyplot as plt

n = 1000
points = np.random.rand(n, 2)

# Define alpha parameter
alpha= 20

# Generate the alpha shape
alpha_shape = alphashape.alphashape(points, alpha)

# Initialize plot
fig, ax = plt.subplots()

# Plot input points
ax.scatter(*zip(*points))

# Plot alpha shape
ax.add_patch(PolygonPatch(alpha_shape, alpha=.5, fc='blue', ec='red'))


pnts = [x for x in alpha_shape.boundary.coords]
plt.scatter(*zip(*pnts),marker='s')



plt.show()

【讨论】:

    【解决方案2】:

    我在 dionysus 文档中找到了this,它可能会为您提供 alpha 形状:

    complex = Filtration()
    fill_alpha2D_complex(points, complex)
    alphashape = [s for s in complex if s.data[0] <= .5]
    

    那我相信你需要做这样的事情:

    for simplex in alphashape:
        print [v for v in simplex.vertices]
    

    【讨论】:

    • 打印出一长串元组。大多数元组有一个成员,有些有两个或三个。尽管我最初的输入包含大约一千个点,但这些元组大约有五千个。相反,我期待一个二维点列表,其成员数少于输入。
    • 经过狄俄尼索斯作者的一番解释,我断定这个答案是对的。每个元组中的整数是点的索引。具有两个成员的元组是边,具有三个成员的元组是三角形。 “.5”是 alpha 的值。有一种方法可以确定 alpha 的最小值,以便连接生成的形状。如果我有时间,我会将这段代码放在问题中。
    • 好的,我发布了。最后,出于我在上面的解决方案(我已添加到问题中)中概述的原因,我选择了“船体”而不是酒神。
    • 优秀的问题和研究。感谢那。我从酒神路线中获得了顶点索引列表。现在我有了它们,我如何找到 alpha 以便我可以从这些点形成一个凹多边形?你说有一种方法可以计算出 alpha ——你能详细说明一下吗?
    • 我试过了,但出现错误:NameError: name 'fill_alpha2D_complex' is not defined
    猜你喜欢
    • 2019-08-01
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    • 2018-04-30
    • 1970-01-01
    • 2021-01-24
    • 2015-11-03
    • 1970-01-01
    相关资源
    最近更新 更多