我有很多这样的镂空图像:
我如何检测一个循环,一个骨架中的循环? 是否有“特殊”功能可以执行此操作,还是应将其实现为图形?
如果只有图形选项,python图形库NetworkX可以帮助我吗?
答案 0 :(得分: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最好加载图像而不是生成图像。无论如何,我们现在有一些工作要做:
现在,真实的部分:
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个洞
答案 1 :(得分:3)
将骨架图像转换为图形表示并非易事,我不知道有任何工具可以帮助您。
在位图中执行此操作的一种方法是使用flood fill,就像在photoshop中使用油漆桶一样。如果您开始填充图像,如果没有循环,整个背景将被填充。如果填充没有得到整个图像,那么你已经找到了一个循环。稳健地找到所有周期可能需要多次填充。
这可能会非常慢,但编码速度可能比将骨架跟踪到图形数据结构的技术要快得多。
答案 2 :(得分:3)
您可以利用骨架的拓扑。循环没有漏洞,因此我们可以使用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”图片作为例子。前两个图像是原始图像和填充版本,它检测周期。在第二个版本中,我打破了循环,没有任何东西被填满,因此两个图像是相同的。