CGAL中凹多边形的直骨架
Straight Skeleton from concave polygon in CGAL
我有一张图像,我从中提取轮廓并将其变成多边形,使用下面的代码见下图:
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 将所有多边形报告为 not-simple,但据我所知它们应该很简单。它们在任何地方都不相交,也没有任何重复点。
由于 CGAL 确信多边形是 not-simple,函数 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
那么,我是不是弄错了,多边形确实是 not-simple。如果是这样,我怎么还能骨架化?或者是其他地方的错误,我做错了什么?
编辑
根据要求多边形文件: 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,not-being 简单的问题已经解决。第一个点和最后一个点在每个多边形中都是重复的。
遗憾的是创建的骨骼非常变形:
骷髅
骷髅放大
使用的代码:
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() 限制为仅一个多边形,它也会变形。
最终编辑
直骨架失败了,因为我是按顺时针顺序创建顶点的多边形。在创建多边形之前颠倒点的顺序解决了最后一个问题。
尝试使用 create_interior_straight_skeleton() 时,确保多边形:
- 很简单 -> 没有相交线段或重复点
- 其顶点按逆时针顺序定义。
如果多边形不简单,您将收到这样的错误。
如果顶点不是逆时针顺序,你的直骨架看起来像恶魔产卵并且是不正确的。
感谢@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)
#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 将所有多边形报告为 not-simple,但据我所知它们应该很简单。它们在任何地方都不相交,也没有任何重复点。
由于 CGAL 确信多边形是 not-simple,函数 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
那么,我是不是弄错了,多边形确实是 not-simple。如果是这样,我怎么还能骨架化?或者是其他地方的错误,我做错了什么?
编辑
根据要求多边形文件: 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,not-being 简单的问题已经解决。第一个点和最后一个点在每个多边形中都是重复的。
遗憾的是创建的骨骼非常变形:
骷髅
使用的代码:
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() 限制为仅一个多边形,它也会变形。
最终编辑
直骨架失败了,因为我是按顺时针顺序创建顶点的多边形。在创建多边形之前颠倒点的顺序解决了最后一个问题。
尝试使用 create_interior_straight_skeleton() 时,确保多边形:
- 很简单 -> 没有相交线段或重复点
- 其顶点按逆时针顺序定义。
如果多边形不简单,您将收到这样的错误。
如果顶点不是逆时针顺序,你的直骨架看起来像恶魔产卵并且是不正确的。
感谢@Sloriot 的帮助!