简体   繁体   English

如何计算2D矢量形状的中轴?

[英]How do I calculate the medial axis for a 2D vector shape?

I have a 2D shape stored as a path element in an SVG. 我有一个2D形状存储为SVG中的路径元素。 The shapes consist of Bezier curves and line segments. 形状由贝塞尔曲线和线段组成。

I also have a set of equally space points along the shape that I am generating using arc length parameterization. 我还在使用弧长参数化生成的形状上有一组相同的空间点。

How can I use either the SVG or these points to determine the medial axis of the shape? 如何使用SVG或这些点来确定形状的中轴?

I am using Python, but any sort of pseudocode or algorithm advice would be much appreciated. 我正在使用Python,但是非常感谢任何类型的伪代码或算法建议。


The following is an example of the types of shapes I am dealing with, and the red dots are my sampled points along the curve. 以下是我正在处理的形状类型的示例,红点是沿着曲线的采样点。

例

A tad late but here goes: 有点晚了但是这里有:

Medial and Scale Axis TransformScale Axis TransformMedial Axis Transform2-Prong3-Prong

The pictures above shows: (I've converted the OP's image to SVG with an online tool hence the ragged boundary that is an artifact of the red dots) 1. Superimposed Medial and Scale Axis Transform ( MAT and SAT ). 上面的图片显示:(我已经使用在线工具将OP的图像转换为SVG,因此参差不齐的边界是红点的伪影)1。叠加的内侧和尺度轴变换( MATSAT )。 2. Scale Axis Transform only. 2.仅缩放轴变换。 3. Medial Axis Transform only. 3.仅内侧轴变换。 4. One of many 2-prongs (see below). 4.许多2个插脚之一 (见下文)。 5. The single 3-prong in the SAT (there are many in the MAT ). 5. SAT中的单个三爪MAT中有很多)。

To find the Medial Axis (MA) or Medial Axis Transform (MAT) (purple curves in above image) the following algorithm can be used (based on a paper by Choi, Choi, Moon and Wee - see a demo implementation here that also handles intersecting shapes and shapes with holes). 为了找到以下算法可以用来中轴(MA)中轴变换(MAT)(以上图片紫色曲线)(基于一由财,财,月球和嫣-看到一个演示实现这里 ,也负责处理相交的形状和形状有孔)。 Other algorithms also exist. 还存在其他算法。

The algorithm is much harder to implement than finding a binary image (eg bitmap) skeleton (aka grassfire or discrete transform) but has several advantages (such as being analytic). 该算法比找到二进制图像(例如位图)骨架(又名草火或离散变换)更难实现,但具有几个优点(例如分析)。 To simplify things, the discussion below only handles the case of simple (non-intersecting) shapes without holes. 为简化起见,下面的讨论仅处理没有孔的简单(非交叉)形状的情况。

Some definitions 一些定义

  • Curve - A parametric bezier curve with parameter t ∈ [0,1]. 曲线 -与参数t∈[0,1]甲参数贝塞尔曲线。 In other words, a typical curve as used in vector graphics. 换句话说,是矢量图形中使用的典型曲线。
  • Shape (Ω) - (Definition taken directly from the paper) - "the closure of a connected bounded open subset in ℝ² bounded by a finite number of mutually disjoint simple closed curves ." 形状(Ω) - (直接取自论文) - “由有限数量的相互不相交的简单闭合曲线限制的ℝ²中连通有界开放子集的闭包。” For the purposes of this answer it can be further assumed that the shape has no holes. 出于本答案的目的,可以进一步假设该形状没有孔。 In simple terms it is the area enclosed by the boundary given by a number of curves - the filled gray part in the image above. 简单来说,它是由许多曲线给出的边界所包围的区域 - 上图中填充的灰色部分。
  • Boundary - The boundary of the shape . 边界 - 形状的边界。 In other words, an indexed sequence of curves such that the starting point of any curve at t =0 corresponds to the previous curve's endpoint at t =1. 换句话说,索引的曲线序列使得t = 0处的任何曲线的起点对应于t = 1处的前一曲线的终点。 The boundary is assumed positively oriented (ie by walking along the boundary in an anti-clockwise direction the shape will always be to your left). 假定边界是正向的(即通过沿逆时针方向沿边界行走,形状总是在你的左边)。
  • Boundary point - Any point on the shape boundary fully identified by an index identifying the curve and a t curve paramter. 边界点 - 形状边界上的任何点由标识曲线的索引和t 曲线参数完全标识。
  • Maximal disk - Disks within the shape not occluded by any other disk also within the shape. 最大磁盘 - 形状内的磁盘未被形状内的任何其他磁盘遮挡。 Every maximal disk can be identified by 1 or more (usually 2) boundary point s and its center point. 每个最大磁盘可以由1个或多个(通常为2个) 边界点 s及其中心点标识。
  • n-prong - A maximal disk touching the shape boundary tangentially at n points. n-prong - 在n个点处切向接触形状边界的最大圆盘
  • Branch point - An n-prong maximal disk center with n >= 3. In other words a point on the MA that forms a vertex in the MA planar tree. 分支点 - n> = 3的n-prong 最大磁盘中心 。换句话说, MA上的一个点,它在MA平面树中形成一个顶点。
  • Medial Axis (MA) - The union of the centers of all n-prongs . Medial Axis(MA) - 所有n-prongs中心的联合。
  • Medial Axis Transform (MAT) - The union of all n-prongs . Medial Axis Transform(MAT) - 所有n-prongs的结合 In other words, the radius of the maximal disks are included in the definition. 换句话说, 最大磁盘的半径包含在定义中。
  • Contact point (cp) - A boundary point linked to a unique maximal disk that has already been found. 接触点(cp) - 链接到已找到的唯一最大磁盘的 边界点
  • Sharp corner - A boundary point , usually at curve parameter t = 0 or t = 1, that is not differentiable (not smooth) and that forms an interior angle < 180°. 尖角 - 边界点 ,通常在曲线参数t = 0或t = 1时,不可微分(不平滑)并且形成内角<180°。
  • Dull corner - Same as a sharp corner except the angle > 180°. 钝角 - 除角度> 180°外与锐角相同。
  • Cp graph - A graph (not necessarily planar) with vertices being contact point s thus also containing information regarding all found maximal disk s and in turn the entire MAT . Cp图 - 顶点为接触点 s的图形(不一定是平面的)因此也包含有关所有找到的最大磁盘 s以及整个MAT的信息 Each vertex ( cp ) in the graph has the following edges: 图中的每个顶点( cp )都具有以下边:
    • next - The first contact point found from the current one by walking anti-clockwise around the boundary . next - 通过逆时针绕边界行走,从当前接触点找到的第一个接触点
    • prev - The first contact point found from the current one by walking clockwise around the boundary . prev - 从当前的一个接触点顺时针绕边界走。
    • next-around - The first contact point found by going around the maximal disk in an anti-clockwise direction. next-around - 通过沿逆时针方向绕最大磁盘找到的第一个接触点
    • prev-around - The first contact point found by going around the maximal disk in a clockwise direction. prev-around - 沿顺时针方向绕最大磁盘找到的第一个接触点 We can view each of the above as an operator (.) on a contact point returning another contact point by following an edge, eg if a is a contact point , then a . 我们可以通过跟随边缘返回另一个接触点接触点上的上述每个操作符(。),例如,如果a接触点 ,则a next is another contact point . 接下来是另一个联络点

Some notes 一些笔记

  • The Medial Axis Transform forms an unrooted planar tree with tree leaves at every 1-prong center (including sharp corner s); 中间轴变换形成一个无根的平面树,在每个1爪中心(包括尖角 s)有树叶; if the shape has holes then the MAT is a planar graph. 如果形状有孔,则MAT是平面图。
  • You can remove noise on the shape boundary by applying a Scale Axis Transform (SAT) (red curves in above image) to the MAT . 您可以通过将缩放轴变换(SAT) (上图中的红色曲线)应用于MAT来消除形状边界上的噪声。 The demo implements such a transform, based on this research. 基于这项研究,该演示实现了这种转换。 However, the demo improves the algorithm by ensuring the SAT is a subset of the MAT and guarantees topology preservation. 但是,该演示通过确保SATMAT的子集并保证拓扑保留来改进算法。

Algorithm overview 算法概述

  1. Find all 1-prongs ; 找到所有1-prongs ; they are exactly the Medial Axis tree leaves. 它们正好是Medial Axis树叶。 These are the sharp corners and the 1-prongs touching a boundary point with maximum local inward curvature. 这些是尖角1尖接触边界点,具有最大局部向内弯曲。 Add the contact point s of the 1-prongs to the cp-graph . 1-prongs接触点 s添加到cp-graph Note that since 1-prong s have one contact point only, the edges next-around and prev-around will just return the found contact point again. 请注意,由于1-prong只有一个接触点 ,因此旁边的边缘和prev-around将再次返回找到的接触点
  2. For a representative set of boundary point s (such as those red dots given by the OP), calculate their maximal disk s. 对于一组有代表性的边界点 s(例如OP给出的那些红点),计算它们的最大磁盘 s。 They will generally be 2-prongs . 它们通常是2个插脚 (See 'finding a 2-prong' below). (参见下面'找到一个2叉')。 Add their contact point s to the cp-graph by connecting the appropriate edges. 通过连接适当的边将其接触点 s添加到cp图中 Note that in this case, since we found 2-prongs , if next-around (or prev-around ) is followed twice one will be back at the same contact point . 请注意,在这种情况下,由于我们找到了2个插脚 ,如果接下来两次(或上下左右 ),则会返回同一个接触点
  3. Finally find the n-prongs for n >= 3. Starting from each contact point : 最后找到n> = 3的n-prongs 。从每个接触点开始

    1. traverse the cp-graph by starting with a contact point (say cp1 ) and applying cp1 . 通过从接触点 (比如cp1 )开始并应用cp1来遍历cp图 next . 接下来 next-around repeatedly until you are back at cp1 . 下身边 ,直到你又回到CP1。
    2. If either 1 or 2 iterations of the above occured move to the next contact point on the boundary (using next ). 如果上述发生的1或2次迭代移动到边界上的下一个接触点 (使用下一个 )。 If, however, 3 or more iterations were required, it can be proved that a 3-prong branch point exists and should be inserted with contact point s on each boundary piece between cp1 and cp1 . 但是,如果需要3次或更多次迭代,则可以证明存在3叉 分支点 ,并且应该在cp1cp1之间的每个边界块上插入接触点 s。 next . 接下来

      In that case, insert the 3-prong (see below on how to find these) and go back to step 1, again starting from cp1 . 在这种情况下,插入3针 (参见下面有关如何找到这些)并返回步骤1,再次从cp1开始。

    3. Repeat step 1 and 2 until all 3-prongs have been found. 重复步骤1和2,直到找到所有3个插脚
  4. The structure of the MAT has now been found implicitly. 现在已经隐含地发现了MAT的结构。 To extract the MAT one needs to traverse the cp-graph . 要提取MAT,需要遍历cp图 Choose any contact point (call it cp1 ) as the root (for simplicity let's assume it to be linked to a 2-prong ), and apply next (call it cp2 ). 选择任何一个联系点 (称之为cp1 )作为根(为简单起见,我们假设它被链接到一个2-prong ),然后应用next (称之为cp2 )。 A line can now be drawn from cp1 's linked maximal disk center to that of cp2 . 现在可以从cp1的链接最大磁盘中心绘制一条线到cp2的线 This line is an approximation of a subset of the MA . 该线是MA的子集的近似值。 A much better approximation is obtained via interpolation between the points since we know the boundary tangents at the contact points . 由于我们知道接触点处的边界切线,因此通过点之间的插值获得了更好的近似。 Let the two line endpoints be the endpoints of a quadratic bezier curve. 设两条线端点为二次贝塞尔曲线的端点。 Since the orientation of the MA at the two maximal disk centers are known exactly (via the average of the 2 boundary tangents) we have the derivatives of the quadratic beziers at the endpoints too and we can construct a best approximation qudratic bezier curve between the points. 由于MA在两个最大圆盘中心的方向是精确已知的(通过2个边界切线的平均值),我们在端点处也有二次贝塞尔曲线的导数,我们可以在这些点之间构造最佳逼近的四次贝塞尔曲线。 If cp2 is linked to a 3-prong it implies that the planar tree formed by the MA bifurcates (ie branches ot forks) and we need to follow both MA edges (by using, for example, a stack or recursion). 如果cp2链接到3-prong,则意味着由MA形成的平面树分叉(即分支或叉子),并且我们需要跟随两个MA边缘(通过使用例如堆栈或递归)。 If, on the other hand, cp2 is linked to a 1-prong a leaf of the MA has been reached and the traversal stops for that edge. 另一方面,如果cp2链接到1-prong ,则已到达MA的叶子并且该遍历的遍历停止。 In fact, since the MA forms a planar tree the traversal algorithm is essentialy the same as that of any other tree data structure. 实际上,由于MA形成平面树,遍历算法基本上与任何其他树数据结构的算法相同。

Finding a 2-prong 寻找一个2叉

  1. I will summarize here but the paper by Choi et al. 我将在这里总结,但Choi等人的论文。 explains this part quite clearly and is easy to follow. 这个部分非常清楚地解释并易于理解。

    Choose a point on the boundary that will be the first contact point of our 2-prong and call it bp1 . 选择边界上的一个点,它将是我们的2-prong的第一个接触点 ,并将其命名为bp1 Draw an inward normal ray form the boundary point (ie the first 'prong' of the 2-prong to be found). 边界点 (即要找到的2叉的第一个“尖头”)绘制向内法线。 Now iterate: 现在迭代:

    1. Select a point, p1 , (at a distance d1 from bp1 along this ray) with d1 large enough such that a circle (drawn tangentially at bp1 with center on the ray) will cut the boundary in at least one more point. 选择一个点p1 (沿着该光线距离bp1的距离d1 ), d1足够大,使得一个圆(沿着光线中心切向绘制bp1 )将在至少一个点上切割边界
    2. Find the closest boundary point to p1 , call it bp2 . 找到最接近p1的 边界点 ,称之为bp2 Finally, find the point on the ray equidistant from bp1 and bp2 and call it p2 . 最后,从bp1bp2找到等距光线上的点,并将其称为p2
    3. Go back to step 2 with p2 the new p1 . 返回步骤2,使用p2p1
    4. Repeat steps 2 and 3 until the distance from p1 to the two boundary point s are equal to within some tolerance. 重复步骤2和3,直到从p1到两个边界点 s的距离等于某个公差范围内。 The 2-prong has now been found with bp1 and bp2 its two contact point s and p1 its center. 现在发现2-prong的 bp1bp2是两个接触点 s, p1是其中心。

Finding a 3-prong 寻找一个三叉

Here we deviate a bit from the paper by constructing a circumcircle as opposed to using a potential function. 在这里,我们通过构造一个外接圆而不是使用势函数来偏离论文。

  1. Select the boundary point 's ( cp1 's) linked maximal disk center as an initial guess to the 3-prong center to be found. 选择边界点cp1 )链接的最大磁盘中心作为要找到的3-prong中心的初始猜测。 Call it p . 叫它p
  2. Find the 3 closest points to p seperately to each of the 3+ boundary piece s. 找到3个最接近p点的点到3 + 边界块中的每一个。
  3. Construct the circumcircle of those points and use its center as the new point p . 构造这些点的外接圆并使用其中心作为新点p
  4. Repeat steps 2 and 3 until the distance to the 3 boundary pieces from p is equal to within some tolerance. 重复步骤2和3,直到距p的3个边界块的距离等于某个公差范围内。
  5. Mark the 3 boundary points thus found as contact points of the 3-prong. 将这样找到的3个边界点标记为3叉的接触点 The point p is the center of the 3-prong . p3叉的中心。

Please feel free to ask if anything is unclear. 请随时询问是否有任何不清楚的地方。

you can see the code from skimage (scikit-image). 你可以看到skimage(scikit-image)的代码。 you will find the code for skeletonization and also for medial-axis (skimage.morphology.medial_axis) 你会找到骨架化的代码,也可以找到medial-axis的代码(skimage.morphology.medial_axis)

The source are available at this address : https://github.com/scikit-image/scikit-image/blob/v0.12.2/skimage/morphology/_skeletonize.py#L103 来源可在以下地址获得: https//github.com/scikit-image/scikit-image/blob/v0.12.2/skimage/morphology/_skeletonize.py#L103

This algorithm computes the medial axis transform of an image as the ridges of its distance transform. 该算法计算图像的中轴变换作为其距离变换的脊。

The different steps of the algorithm are as follows 算法的不同步骤如下

A lookup table is used, that assigns 0 or 1 to each configuration of
   the 3x3 binary square, whether the central pixel should be removed
   or kept. 

We want a point to be removed if it has more than one neighbor
   and if removing it does not change the number of connected components.


The distance transform to the background is computed, as well as
   the cornerness of the pixel.

The foreground (value of 1) points are ordered by
   the distance transform, then the cornerness.

A cython function is called to reduce the image to its skeleton. It
   processes pixels in the order determined at the previous step, and
   removes or maintains a pixel according to the lookup table. 

Because
   of the ordering, it is possible to process all pixels in only one
   pass.

I hope it will help you 我希望它会对你有所帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使Keras使用2D形状工作? - How do I make Keras work using a 2D shape? 如何将二维 Python 列表转换为二维 C++ 向量? - How do I convert a 2d Python list to a 2d C++ vector? 如何找到中轴的关节和端点 - How to find the joints and endpoints of medial axis 如何快速创建一个numpy或pandas二维数组,其中两个轴都在一个范围内,值是一个产品? - How do I quickly create a numpy or pandas 2D array with both axis in a range and the values a product? 如何获取代表轮廓形状的向量的坐标,该轮廓形状存储为 2D numpy 像素数组? - How do I get the coordinates of the vectors that represent a contour shape which I have stores as a 2D numpy array of pixels? 如何使用 numpy 计算二维数组的“最大掩码” - How to I calculate a “maximum mask” for a 2d array with numpy 如何提高用medial_axis制作的骨架的质量 - how to improve quality of skeleton made with medial_axis 如何进行 matshow 或 imshow,但将轴值显示为 bin 边界(即,就像在 2d 频率/密度图上一样) - How to do a matshow or imshow, but display the axis values as bin boundaries (i.e as you would on a 2d frequency/density plot) 如何使二维形状的numpy数组 - How to make numpy array with 2D shape Python - 如何对 2D 形状进行重采样? - Python - How to resample a 2D shape?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM