连通域染色,two-pass算法的并查集实现

来源:互联网 发布:阿里云免费套餐激活码 编辑:程序博客网 时间:2024/06/05 17:51

two-pass是一种找连通域的算法,只要对图做两次遍历,就能够对相同连通域内的点打上相同的label。

这里写图片描述

该图为4-邻域上的two-pass

第一遍:
对每个点打上min(labeln(x,y)),即其邻域中点的最小的label;如果发现邻域中出现了不同的label,把这些label放到并一个集合Si中去,即使得同一个连通域Ci的label在同一个集合,label(x,y)Si,(x,y)Ci
第二遍:
对每个点的label进行更新,更新为其对于其集合中最小的label,label(x,y)=min(Si),(x,y)Ci
two-pass就做完了。看看效果吧。
原图:
处理前
two-pass 加随机染色 去除小于100的连通块
处理后

集合的维护采用了并查集,让同一个连通域中的label的父亲都指向集合中最小的label,然后用并查集更新每个像素的label,这样就使得所有像素的label为集合中最小的label了。

python实现:

#find father and updatedef find_fa(x):    global count,fa,cc    fx = fa[x]    if fa[fx] == fx:#if father has no father, no more search        return fx    else:#update x's father        fa[x] = find_fa(fx)        return fa[x]def two_pass(img, mask=255, area=100):    #init merge and find set    global count,fa,cc    fa = range(img.shape[0]*img.shape[1]) #father node    cc = np.zeros(img.shape[0]*img.shape[1]) #count connected components area of fa[]    cc = cc+1    dx = [0,0,-1,1,-1,-1,1,1]    dy = [-1,1,0,0,-1,1,-1,1]    for i in range(img.shape[0]):        for j in range(img.shape[1]):            if img[i,j] == mask:                for dir in range(8):                    nx = dx[dir] + i                    ny = dy[dir] + j                    if nx >= 0 and nx < img.shape[0] and ny >= 0 and ny < img.shape[1] and img[nx,ny] == mask:                        a = i*img.shape[1]+j                        b = nx*img.shape[1]+ny                        pa = find_fa(a)#shorten chain                        pb = find_fa(b)#                        #merge father                        if pa<pb:                            fa[pb]=pa                            cc[pa]+=cc[pb]                            cc[pb]=0                        elif pa>pb:                            fa[pa]=pb                            cc[pb]+=cc[pa]                            cc[pa]=0    for i in range(img.shape[0]):        for j in range(img.shape[1]):            if img[i,j] == mask:                a = i*img.shape[1]+j                find_fa(a)    count = 0    colormap = np.zeros((img.shape[0],img.shape[1],3))#color hash table    for i in range(img.shape[0]):        for j in range(img.shape[1]):            if img[i,j] == mask:                a = i*img.shape[1]+j                pa = find_fa(a)                if cc[pa] >= 100: # connected components with area >= 100 pixels                    pa_i = pa / img.shape[1]                    pa_j = pa % img.shape[1]                    if np.max(colormap[pa_i,pa_j,:]) == 0:                        colormap[pa_i,pa_j,:] = np.random.randint(256,size=3)                        count += 1                    colormap[i,j,:] = colormap[pa_i,pa_j,:]    print count    return colormap

方法调用:
des = two_pass(src,255,100)
255是白色的意思,100是连通区域阈值大小。

原创粉丝点击