如何找到二维点云的alpha形状(凹壳)?

时间:2011-07-26 16:19:05

标签: python linux ubuntu geometry computational-geometry

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

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

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

我还在贝尔实验室的肯克拉克森试过this implementation。它输出几乎我想要的东西,输出似乎是另一个规模,它将浮动变成整数。

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

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

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

更新我现在从Ken Clarkson's implementation找到了如何从dionysus implementation和(或多或少我想要的)得到我想要的东西。 Clarkson的实现是做正确的事情,它只是输出点的索引而不是点本身(与dionysus相同的故事),我需要得到一些可选的标记。我写的包装器如下。这种解决方案是理想的,因为它产生的α形状既连接又不包含孔。 Alpha自动设置。另一方面,狄俄尼索斯并没有自动发现这种α值。另外,Clarkson的实现可以设置为输出形状的ps图像(带-afps标志)。要使用非古代版本的GCC编译Clarkson的代码,您需要按照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)

2 个答案:

答案 0 :(得分:3)

我在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]

答案 1 :(得分: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()