在standard algorithm for connected component counting中,使用名为union-find的不相交集数据结构。
为什么使用这种数据结构?我编写的代码只是线性搜索图像,保留两个线性缓冲区,通过检查四个邻居(E,SE,S,SW)来存储每个连接像素的当前和下一个组件计数,如果是连接,更新连接映射以将较高组件与较低组件连接。 完成后,搜索所有未连接的组件并报告计数。
我无法理解为什么这种方法的效率低于使用union-find。
这是我的代码。输入文件已缩减为0
和1
s。程序输出由0
s。
def CompCount(fname):
fin = open(fname)
b,l = fin.readline().split()
b,l = int(b),int(l)+1
inbuf = '1'*l + fin.read()
prev = curr = [sys.maxint]*l
nextComp = 0
tree = dict()
for i in xrange(1, b+1):
curr = [sys.maxint]*l
for j in xrange(0, l-1):
curr[j] = sys.maxint
if inbuf[i*l+j] == '0':
p = [prev[j+n] for m,n in [(-l+1,1),(-l,0),(-l-1,-1)] if inbuf[i*l + j+m] == '0']
curr[j] = min([curr[j]] + p + [curr[j-1]])
if curr[j] == sys.maxint:
nextComp += 1
curr[j] = nextComp
tree[curr[j]] = 0
else:
if curr[j] < prev[j+1]: tree[prev[j+1]] = curr[j]
if curr[j] < prev[j]: tree[prev[j]] = curr[j]
if curr[j] < prev[j-1]: tree[prev[j-1]] = curr[j]
if curr[j] < curr[j-1]: tree[curr[j-1]] = curr[j]
prev = curr
return len([x for x in tree if tree[x]==0])
答案 0 :(得分:0)
我没有完全理解你的问题,你在写清楚并构建问题时,自己真正获益。
据我所知,您希望使用8邻域在0-1图像中进行连通分量标记。如果这是你的假设,结果邻域图是平面的是错误的。你在&#34;对角线&#34;有过境点。在这样的图像中构造K_ {3,3}或K_ {5}应该是容易的。
答案 1 :(得分:0)
您的算法存在缺陷。考虑这个例子:
11110
01010
10010
11101
你的算法说2个组件,而它只有1个。
为了测试,我使用了这个稍微修改过的代码版本。
import sys
def CompCount(image):
l = len(image[0])
b = len(image)
prev = curr = [sys.maxint]*(l+1)
nextComp = 0
tree = dict()
for i in xrange(b):
curr = [sys.maxint]*(l+1)
for j in xrange(l):
curr[j] = sys.maxint
if image[i][j] == '0':
p = [prev[j+n] for m,n in [(1,1),(-1,0),(-1,-1)] if 0<=i+m<b and 0<=j+n<l and image[i+m][j+n] == '0']
curr[j] = min([curr[j]] + p + [curr[j-1]])
if curr[j] == sys.maxint:
nextComp += 1
curr[j] = nextComp
tree[curr[j]] = 0
else:
if curr[j] < prev[j+1]: tree[prev[j+1]] = curr[j]
if curr[j] < prev[j]: tree[prev[j]] = curr[j]
if curr[j] < prev[j-1]: tree[prev[j-1]] = curr[j]
if curr[j] < curr[j-1]: tree[curr[j-1]] = curr[j]
prev = curr
return len([x for x in tree if tree[x]==0])
print CompCount(['11110', '01010', '10010', '11101'])
让我尝试用文字解释你的算法(用图形而不是网格)。
(您的tree
与我的roots
相同:请注意,您从不使用tree[]
元素的值,只是它们是否为0 ...这只是实现一套)
它就像union-find,除了它假设当你合并两个组件时,具有更高v []值的组件之前从未与另一个组件合并。在反例中,这是被利用的,因为中间列中的两个0已经与它们左边的0合并。
答案 2 :(得分:0)
我的变体:
首先,您的节点将分别位于其集合中,
o-o o-o o1-o3 o2 o3-o4
\ / |
o-o-o-o o2 o1-o3-o4
随着算法的进展和合并,它的输入相对减半。
在示例中,我正在检查某个图表中的组件。在将所有边缘合并到它们的最大可能设置之后,我留下3组,给出3个断开连接的组件。 (组件数是算法完成时能够获得的组数。)
可能的图表(对于上面的树):
o-o-o o4 o2
| |
o o3
|
o1