8

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

在此处输入图像描述 在此处输入图像描述

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

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

4

3 回答 3

5

您可以利用骨架的拓扑结构。一个循环不会有洞,所以我们可以用它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”图片为例。前两个图像是原始版本和检测周期的填充版本。在第二个版本中,我打破了循环并且没有填充,因此两个图像是相同的。

在此处输入图像描述

于 2013-04-10T15:37:01.607 回答
4

首先,让我们用 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 加载图像而不是生成图像会更好。无论如何,我们现在有一些工作要做: 上B

现在,真正的部分:

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 个孔

于 2013-05-17T11:01:03.723 回答
3

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

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

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

于 2013-04-10T14:30:59.497 回答