CV1——二值图像分析之连通域

来源:互联网 发布:淘宝包店名字 编辑:程序博客网 时间:2024/06/17 07:35

最近选修了计算机视觉的有关课程,主要目的就是系统地学习一下计算机视觉的有关知识。之前涉及到了一些,但是主要是结合opencv的学习,功能上只会调库,而没有深入思考背后的原理及实现,这次算是补课了。

首先从最简单的二值图像分析开始,这里主要介绍了一个比较重要的知识点,就是如何寻找连通域并标记。

第一种方法就是递归算法,其实可以算作是一种深度搜索,先把原有的图像二值化为0与1,然后把所有1的部分置为-1,这样做的目的是为了区别之后标记类别所要用的1,然后开始遍历,对于像素值为-1的点,首先要进行标记,然后在其邻域进行递归搜索,这里不需要返回处理,因为当一个值周围在没有未标记的-1点,说明邻域已经寻找完毕,退出搜索。值得注意的是,这个算法之所以效率不高,原因是一旦搜索完了一片邻域之后,需要重新再来一遍重新寻找搜索的起始点。

第二种方法是以空间换时间,称为序贯算法,主要思路是,进行从左至右,从上至下的遍历,遍历过程中分情况讨论,其中当上方和左方标记不一致的时候,则需要一步更新等价表的操作,等价表其实就是记录一下哪些虽然标号不同,但是实际可以可以连在一起的相邻区域。

#encoding=utf-8import numpy as npclass FindConnectedDomain(object):    def __init__(self):        pass    def baseMethod(self,image):        dir = [[1,0],[-1,0],[0,1],[0,-1]] # 方向向量        m, n = image.shape        def dfs(x,y,mark):            image[x][y] = mark            for i in range(4):                nextx = x+dir[i][0]                nexty = y+dir[i][1]                if nextx < m and nextx >= 0 and nexty >= 0 and nexty < n and image[nextx][nexty] == -1: # 判断是否越界,邻域元素是否未被标记                    image[nextx][nexty] = mark                    dfs(nextx,nexty,mark)        for i in range(m): # 先处理图像为-1-0形式            for j in range(n):                if image[i][j] == 1:                    image[i][j] = -1        mark = 1        for i in range(m):            for j in range(n):                if image[i][j] == -1:                    dfs(i,j,mark) # 寻找起始点开始搜索                    mark += 1 # 搜索完毕,邻域标记自动加1    def sequenceMethod(self,image):        m, n = image.shape        mark = 0        equDic = {} # 等价表字典        for i in range(m):            for j in range(n):                if image[i][j] == 1:                    if i-1 >= 0 and j-1 >= 0:                        if image[i-1][j] != image[i][j-1] and image[i-1][j] != 0 and image[i][j-1] != 0: # 不同标记                            image[i][j] = image[i][j-1]                            equDic[image[i-1][j]] = image[i][j-1]                        if (image[i-1][j] != 0 and image[i-1][j] != 1) or (image[i][j-1] != 0 and image[i][j-1] != 1):# 至少存在一个有标记                            if image[i-1][j] != 0 and image[i-1][j] != 1:                                image[i][j] = image[i-1][j]                            else:                                image[i][j] = image[i][j-1]                        if image[i-1][j] == 0 and image[i][j-1] == 0:               # 没有标记                            mark += 1                            equDic[mark] = 0                            image[i][j] = mark                    else:                # 这里主要是考虑当所遍历的元素在边界的情况                        mark += 1                        equDic[mark] = 0                        image[i][j] = mark        newEquDic = {}        for key in sorted(equDic.keys()):            path = []            while equDic[key] != 0: # 在等价表中搜索相关区域序号,并把它赋给其余所以相连的区域,这里并不是最小                path.append(key)                key = equDic[key]            for item in path:                newEquDic[item] = key        for i in range(m):            for j in range(n):                if image[i][j] in newEquDic:                    image[i][j] = newEquDic[image[i][j]] # 更新图像        print equDic        print newEquDicif __name__ == "__main__":    finder = FindConnectedDomain()    image = np.array([[1,0,0,1,0,0],[0,1,1,1,1,1],[1,1,0,0,1,1],[0,0,1,0,0,1]])    print image    #finder.baseMethod(image)    finder.sequenceMethod(image)    print image


0 0
原创粉丝点击