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

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 update
def 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是连通区域阈值大小。

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值