如何找到中轴的关节和端点
How to find the joints and endpoints of medial axis
我能够使用
获得中轴
image = Image.open('path/to/img.png')
image = (np.array(image) / 255).astype(np.uint8)
medial = skeletonize(image)
medial_x, medial_y = np.where(medial == 1)
但是我如何使用 python 找到中轴的端点和关节,因为我从 medial_x, medial_y = np.where(medial == 1)
获得的坐标没有按照我可以轻松获得端点或关节的方式排序?
原剪影附在下方
我把骨架看成一个图,并构造它的邻接矩阵。使用邻接矩阵,您可以非常轻松地找到端点。图中具有一个邻居的节点是端点,而具有两个以上邻居的节点就是您所说的“关节”。我喜欢称它们为十字路口。
我创建邻接矩阵的方法是,如果从节点 i 到节点 j 的欧几里德距离小于 2,则我用零启动一个 NxN 数组并将数组中的 [i, j] 值设置为 1,这意味着它们是相邻像素在图像中。
# create an adjacency matrix
xx, yy = np.where(skeleton)
n = len(xx)
dist_mat = ((xx[:, None]-xx[None, :])**2 + (yy[:, None]-yy[None, :])**2)
adj_mat = (dist_mat <= 2).astype(int)
# joints will have more than 2 neighbors and endpoints
# will have only one.
ends = np.where(adj_mat.sum(1)==1)[0]
intersections = np.where(adj_mat.sum(1)>2)[0]
最后,变量 'ends' 将保存端点的索引,这样端点 k 在图像中的 [x, y]
位置将是 [xx[ends[k]], yy[ends[k]]]
。交叉路口也是如此。
我使用 wand 完成此操作 - 它源自 ImageMagick。它有一个 skeletonise
方法和 “Hit and Miss Morphology” 用于查找特定形状,例如线端或连接点。
Anthony Thyssen here 进行了精彩的讨论,但如果我可以总结一下,您在寻找线端时正在寻找以下形状:
寻找路口时的这个:
黑色方块意味着图像在该位置必须是黑色的,并且在代码的内核中表示为零。白色方块意味着图像在那个位置必须是白色的,并且在代码中表示为内核中的那些。空白方块意味着我们“不关心”那个位置是什么,在代码中表示为破折号(减号)。
代码如下所示:
#!/usr/bin/env python3
import numpy as np
from wand.image import Image
# Use 'wand' to:
# 1 skeletonize
# 2 find line-ends using Top-Hat Morphology
# 3 find line-junctions using Top-Hat Morphology
with Image(filename='Q4J0l.png') as img:
# Skeletonize
img.morphology(method='thinning',
kernel='skeleton',
iterations=-1)
img.save(filename='DEBUG-skeleton.png')
# Find line-ends using Top-Hat Morphology
# There are two kernels here, separated by a semi-colon
# Each is rotated through 90 degress to form all 4 orientations
# The first 3x3 kernel is the one tinted red in the diagram above.
# The second 3x3 kernel is the one tinted green in the diagram above
lineEnds = """
3>:
0,0,-
0,1,1
0,0,-;
3>:
0,0,0
0,1,0
0,0,1
"""
# Clone the original image as we are about to destroy it
with img.clone() as endsImage:
endsImage.morphology(method='hit_and_miss', kernel=lineEnds)
endsImage.save(filename='DEBUG-ends.png')
# Find line-junctions using Top-Hat Morphology
# There are three kernels here, separated by a semi-colon
# Each is rotated through 90 degress to form all 4 orientations
# The first 3x3 kernel is the one tinted yellow in the diagram above
# The second 3x3 kernel is the one tinted magenta in the diagram above
# The third 3x3 kernel is the one tinted cyan in the diagram above
lineJunctions = """
3>:
1,-,1
-,1,-
-,1,-;
3>:
-,1,-
-,1,1
1,-,-;
3>:
1,-,-
-,1,-
1,-,1
"""
# Clone the original image as we are about to destroy it
with img.clone() as junctionsImage:
junctionsImage.morphology(method='hit_and_miss', kernel=lineJunctions)
junctionsImage.save(filename='DEBUG-junctions.png')
DEBUG-images如下:
调试骨架
DEBUG-lineends
调试连接点
使用 ImageMagick:
在终端中实际上要简单得多
magick Q4J0l.png -morphology Thinning:-1 Skeleton skeleton.png
magick skeleton.png -morphology HMT lineends ends.png
magick skeleton.png -morphology HMT linejunctions junctions.png
或者您可以在一个命令中生成所有 3 个图像:
magick Q4J0l.png \
-morphology Thinning:-1 Skeleton -write S.png \
\( +clone -morphology HMT lineends -write E.png +delete \) \
-morphology HMT linejunctions J.png
我能够使用
获得中轴image = Image.open('path/to/img.png')
image = (np.array(image) / 255).astype(np.uint8)
medial = skeletonize(image)
medial_x, medial_y = np.where(medial == 1)
但是我如何使用 python 找到中轴的端点和关节,因为我从 medial_x, medial_y = np.where(medial == 1)
获得的坐标没有按照我可以轻松获得端点或关节的方式排序?
原剪影附在下方
我把骨架看成一个图,并构造它的邻接矩阵。使用邻接矩阵,您可以非常轻松地找到端点。图中具有一个邻居的节点是端点,而具有两个以上邻居的节点就是您所说的“关节”。我喜欢称它们为十字路口。 我创建邻接矩阵的方法是,如果从节点 i 到节点 j 的欧几里德距离小于 2,则我用零启动一个 NxN 数组并将数组中的 [i, j] 值设置为 1,这意味着它们是相邻像素在图像中。
# create an adjacency matrix
xx, yy = np.where(skeleton)
n = len(xx)
dist_mat = ((xx[:, None]-xx[None, :])**2 + (yy[:, None]-yy[None, :])**2)
adj_mat = (dist_mat <= 2).astype(int)
# joints will have more than 2 neighbors and endpoints
# will have only one.
ends = np.where(adj_mat.sum(1)==1)[0]
intersections = np.where(adj_mat.sum(1)>2)[0]
最后,变量 'ends' 将保存端点的索引,这样端点 k 在图像中的 [x, y]
位置将是 [xx[ends[k]], yy[ends[k]]]
。交叉路口也是如此。
我使用 wand 完成此操作 - 它源自 ImageMagick。它有一个 skeletonise
方法和 “Hit and Miss Morphology” 用于查找特定形状,例如线端或连接点。
Anthony Thyssen here 进行了精彩的讨论,但如果我可以总结一下,您在寻找线端时正在寻找以下形状:
寻找路口时的这个:
黑色方块意味着图像在该位置必须是黑色的,并且在代码的内核中表示为零。白色方块意味着图像在那个位置必须是白色的,并且在代码中表示为内核中的那些。空白方块意味着我们“不关心”那个位置是什么,在代码中表示为破折号(减号)。
代码如下所示:
#!/usr/bin/env python3
import numpy as np
from wand.image import Image
# Use 'wand' to:
# 1 skeletonize
# 2 find line-ends using Top-Hat Morphology
# 3 find line-junctions using Top-Hat Morphology
with Image(filename='Q4J0l.png') as img:
# Skeletonize
img.morphology(method='thinning',
kernel='skeleton',
iterations=-1)
img.save(filename='DEBUG-skeleton.png')
# Find line-ends using Top-Hat Morphology
# There are two kernels here, separated by a semi-colon
# Each is rotated through 90 degress to form all 4 orientations
# The first 3x3 kernel is the one tinted red in the diagram above.
# The second 3x3 kernel is the one tinted green in the diagram above
lineEnds = """
3>:
0,0,-
0,1,1
0,0,-;
3>:
0,0,0
0,1,0
0,0,1
"""
# Clone the original image as we are about to destroy it
with img.clone() as endsImage:
endsImage.morphology(method='hit_and_miss', kernel=lineEnds)
endsImage.save(filename='DEBUG-ends.png')
# Find line-junctions using Top-Hat Morphology
# There are three kernels here, separated by a semi-colon
# Each is rotated through 90 degress to form all 4 orientations
# The first 3x3 kernel is the one tinted yellow in the diagram above
# The second 3x3 kernel is the one tinted magenta in the diagram above
# The third 3x3 kernel is the one tinted cyan in the diagram above
lineJunctions = """
3>:
1,-,1
-,1,-
-,1,-;
3>:
-,1,-
-,1,1
1,-,-;
3>:
1,-,-
-,1,-
1,-,1
"""
# Clone the original image as we are about to destroy it
with img.clone() as junctionsImage:
junctionsImage.morphology(method='hit_and_miss', kernel=lineJunctions)
junctionsImage.save(filename='DEBUG-junctions.png')
DEBUG-images如下:
调试骨架
DEBUG-lineends
调试连接点
使用 ImageMagick:
在终端中实际上要简单得多magick Q4J0l.png -morphology Thinning:-1 Skeleton skeleton.png
magick skeleton.png -morphology HMT lineends ends.png
magick skeleton.png -morphology HMT linejunctions junctions.png
或者您可以在一个命令中生成所有 3 个图像:
magick Q4J0l.png \
-morphology Thinning:-1 Skeleton -write S.png \
\( +clone -morphology HMT lineends -write E.png +delete \) \
-morphology HMT linejunctions J.png