【问题标题】:Straight Skeleton from concave polygon in CGALCGAL中凹多边形的直骨架
【发布时间】:2021-01-08 02:05:14
【问题描述】:

我有一张图像,我从中提取轮廓并将其转换为多边形,使用下面的代码见下图:

import os
from scipy import ndimage
from skimage import io, measure, img_as_bool, img_as_ubyte, filters
import skgeom as sg
from skgeom.draw import draw
from matplotlib import pyplot as plt

#Read in the image:
filename = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'traces.png')
traces = img_as_ubyte(io.imread(filename))

#Find contours in of the traces:
Alpha = traces[:,:,3]
bool = img_as_bool(Alpha)
filled = ndimage.binary_fill_holes(bool)
gaussian = filters.gaussian(filled)
countours = measure.find_contours(gaussian, 0.9)

#Display the image and plot all contours found as polygons:
fig, ax = plt.subplots(figsize=(32,16))

skels = []
for countour in countours:
    approximated_countour = measure.approximate_polygon(countour, 10)
    poly = sg.Polygon(approximated_countour)
    draw(poly)
    print(poly.is_simple())
    #skels.append(sg.skeleton.create_interior_straight_skeleton(poly)) #Causes error!

ax.axis('off')
ax.set_axis_off()
plt.show()

控制台中的输出:

False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False

我正在为 CGAL 使用一个名为 scikit-geometry 的 python 包装器。

CGAL 报告所有多边形都不简单,但据我所知,它们应该很简单。它们不会在任何地方相交,也没有任何重复点。

由于 CGAL 确信多边形不简单,函数 create_interior_straight_skeleton 会引发错误并停止。

错误:

RuntimeError: CGAL ERROR: precondition violation!
Expr: aOutContour.is_simple() || !"The input polygon is not simple."
File: D:\bld\scikit-geometry_1602638892768\_h_env\Library\include\CGAL/create_straight_skeleton_2.h
Line: 133

所以,我是不是弄错了,多边形确实不简单。如果是这样,我怎么还能骨骼化?或者是其他地方的错吗?我做错了什么?

编辑

根据要求提供多边形文件: Polygon Files

用于生成文件的代码:

import os
from scipy import ndimage
from skimage import io, measure, img_as_bool, img_as_ubyte, filters
import skgeom as sg

#Read in the image:
directory = os.path.dirname(os.path.abspath(__file__))
filename = os.path.join(directory, 'traces.png')
traces = img_as_ubyte(io.imread(filename))

#Find contours in of the traces:
Alpha = traces[:,:,3]
bool = img_as_bool(Alpha)
filled = ndimage.binary_fill_holes(bool)
gaussian = filters.gaussian(filled)
countours = measure.find_contours(gaussian, 0.9)

#Save the polygons to a text file:
for index, countour in enumerate(countours):
    approximated_countour = measure.approximate_polygon(countour, 10)
    poly = sg.Polygon(approximated_countour)

    file = open(os.path.join(directory, "polygons\poly_{}.txt".format(index)), "w")
    for vertice in poly.vertices:
        file.write("{}, {}\n".format(vertice.x(), vertice.y()))

编辑 2

感谢@sloriot,这个不简单的问题已经解决。第一个点和最后一个点在每个多边形中都是重复的。

可悲的是,创建的骨架非常变形: 骷髅 骨架放大

使用的代码:

import os
from scipy import ndimage
from skimage import io, measure, img_as_bool, img_as_ubyte, filters
import skgeom as sg
from skgeom.draw import draw
from matplotlib import pyplot as plt

#Read in the image:
filename = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'traces.png')
traces = img_as_ubyte(io.imread(filename))

#Find contours in of the traces:
Alpha = traces[:,:,3]
bool = img_as_bool(Alpha)
filled = ndimage.binary_fill_holes(bool)
gaussian = filters.gaussian(filled)
countours = measure.find_contours(gaussian, 0.9)

def draw_skeleton(polygon, skeleton, show_time=False):
    draw(polygon)

    for h in skeleton.halfedges:
        if h.is_bisector:
            p1 = h.vertex.point
            p2 = h.opposite.vertex.point
            plt.plot([p1.x(), p2.x()], [p1.y(), p2.y()], 'r-', lw=2)

    if show_time:
        for v in skeleton.vertices:
            plt.gcf().gca().add_artist(plt.Circle(
                (v.point.x(), v.point.y()),
                v.time, color='blue', fill=False))

#Display the image and plot all contours found as polygons:

for countour in countours:
    approximated_countour = measure.approximate_polygon(countour, 10)

    if ((approximated_countour[0] == approximated_countour[-1]).all()):
        approximated_countour = approximated_countour[:-1]

    poly = sg.Polygon(approximated_countour)
    print(poly.is_simple())
    skel = sg.skeleton.create_interior_straight_skeleton(poly)

    draw_skeleton(poly, skel, True)

plt.show()

代码和 python 库似乎不是问题,因为它可以正常工作here,并且当我尝试它时该代码也可以正常工作。同样,我的多边形是我担心的问题。请注意,如果我将 draw_skeleton() 限制为一个多边形,它也会变形。

最终编辑

直骨架失败了,因为我正在创建具有顺时针顺序顶点的多边形。在创建多边形之前反转点的顺序已解决了最后一个问题。

【问题讨论】:

  • 没有任何代码或数据,很难告诉你哪里出了问题。也许它只是输入多边形中的一个重复点?
  • @sloriot 添加了代码。检查了多边形本身,找不到任何重复的点。
  • 如果你给我多边形文件,我可以看看,但如果函数说它们不简单,它们可能并不简单。我是 CGAL 开发人员而不是 scipy 开发人员,所以包装器可能存在问题。
  • @sloriot 没想到包装纸会损坏。我会尽快将多边形文件添加到问题中。感谢您迄今为止的帮助!
  • 第一个点和最后一个点是相同的。尝试删除其中一个。

标签: python cgal


【解决方案1】:

尝试使用 create_interior_straight_skeleton() 时,请确保您使用多边形:

  • 很简单 -> 没有相交的线段或重复的点
  • 按逆时针顺序定义顶点。

如果多边形不是简单的,你会被这样的错误对待。

如果顶点不是按逆时针顺序排列的,那么你的直骨架看起来就像恶魔产卵并且是不正确的。

感谢@Sloriot 的帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-24
    • 2010-12-22
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 2011-01-28
    • 2020-05-24
    相关资源
    最近更新 更多