如何使用 python 库在骨架图像中找到循环?

Posted

技术标签:

【中文标题】如何使用 python 库在骨架图像中找到循环?【英文标题】:How can i find cycles in a skeleton image with python libraries? 【发布时间】:2013-04-01 15:14:56 【问题描述】:

我有很多这样的骨架图像:

我怎样才能检测到一个循环,一个骨架中的循环? 是否有执行此操作的“特殊”功能,或者我应该将其实现为图形?

如果只有图形选项,python图形库NetworkX可以帮到我吗?

【问题讨论】:

使用 python 字典很容易实现一个简单的图形。这里是an example from the python docs。 NetworkX 似乎有点矫枉过正,尽管我从未使用过它。关于将图像转换为图形,我不知道一种简单的方法来做到这一点,尽管这似乎是一个有趣的问题。我使用opencv,它提供了很多用于处理图像的功能。您可能会在其中找到一些有用的部分。 【参考方案1】:

您可以利用骨架的拓扑结构。一个循环不会有漏洞,因此我们可以使用scipy.ndimage 查找任何漏洞并进行比较。这不是最快的方法,但它非常容易编码。

import scipy.misc, scipy.ndimage

# Read the image
img = scipy.misc.imread("Skel.png")

# Retain only the skeleton
img[img!=255] = 0
img = img.astype(bool)

# Fill the holes
img2 = scipy.ndimage.binary_fill_holes(img)

# Compare the two, an image without cycles will have no holes
print "Cycles in image: ", ~(img == img2).all()

# As a test break the cycles
img3 = img.copy()
img3[0:200, 0:200] = 0
img4 = scipy.ndimage.binary_fill_holes(img3)

# Compare the two, an image without cycles will have no holes
print "Cycles in image: ", ~(img3 == img4).all()

我以您的“B”图片为例。前两个图像是原始版本和检测周期的填充版本。在第二个版本中,我打破了循环,没有填充,因此两个图像是相同的。

【讨论】:

【参考方案2】:

首先,让我们用 PIL 构建字母 B 的图像:

import Image, ImageDraw, ImageFont
image = Image.new("RGBA", (600,150), (255,255,255))
draw = ImageDraw.Draw(image)
fontsize = 150
font = ImageFont.truetype("/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf", fontsize)
txt = 'B'
draw.text((30, 5), txt, (0,0,0), font=font)
img = image.resize((188,45), Image.ANTIALIAS)
print type(img)
plt.imshow(img)

您可能会找到更好的方法来做到这一点,尤其是使用字体路径。 ii 加载图像而不是生成图像会更好。无论如何,我们现在有一些工作要做:

现在,真正的部分:

import mahotas as mh
img = np.array(img)
im = img[:,0:50,0]
im = im < 128
skel = mh.thin(im)
noholes = mh.morph.close_holes(skel)
plt.subplot(311)
plt.imshow(im)
plt.subplot(312)
plt.imshow(skel)
plt.subplot(313)
cskel = np.logical_not(skel)
choles = np.logical_not(noholes)
holes = np.logical_and(cskel,noholes)
lab, n = mh.label(holes)
print 'B has %s holes'% str(n)
plt.imshow(lab)

我们在控制台(ipython)中有: B 有 2 个洞

【讨论】:

【参考方案3】:

将您的骨架图像转换为图形表示并非易事,而且我不知道有任何工具可以为您做到这一点。

在位图中执行此操作的一种方法是使用flood fill,就像 Photoshop 中的油漆桶一样。如果您开始对图像进行泛光填充,如果没有循环,整个背景将被填充。如果填充没有得到整个图像,那么您已经找到了一个循环。稳健地找到所有循环可能需要多次填充。

这可能执行起来很慢,但可能比将骨架追踪到图形数据结构的技术快得多。

【讨论】:

我认为这是一个很好的解决方案。我计算像素的骨架数和图像的总像素数并计算差异,如果 Floodfill 返回相同数量的像素,则没有循环,如果返回较少则有循环。 是的,基本上你需要标记骨骼的补充。这将返回被骨架循环切割的连接组件。如果组件的数量大于 1 说 N 你有 N-1 循环。这也可以看作是一种瘦骨架的形式。

以上是关于如何使用 python 库在骨架图像中找到循环?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用标准库在 python 中解析格式错误的 HTML

在 C++ 中计算图像骨架的最快方法

python数字图像处理(19):骨架提取与分水岭算法

如何使用python OpenCV在单通道图像中找到与特定值匹配的最大连通分量?

Python,OpenCV骨架化图像并显示(skeletonize)

如何使用 Leanback 库在 Android TV 中创建顶部导航栏