区域生长法:

通俗的讲就是利用初始种子点,通过邻域判断,获取更多的种子点,以达到生长的目的。

有点像是核聚变的链式反应,一个点找到更多的种子点,然后新的种子点再找到更多的,最后生长结束,种子点库也就清空了。

目前主要使用的是四领域和八领域:

四邻域 (左) 和八邻域 (右) 的示意图:

区域生长图像分割算法python 区域生长算法 python_图像处理

区域生长的流程图:

 

区域生长图像分割算法python 区域生长算法 python_区域生长图像分割算法python_02

  以下是部分代码(参考:结合python与遥感图像的区域生长算法实现 - 知乎):


class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def getX(self):
        return self.x

    def getY(self):
        return self.y

    def toString(self):
        return '[' + str(self.x) + ',' + str(self.y) + ']'

def selectConnects(p):
    if p != 0:
        connects = [Point(-1, -1), Point(0, -1), Point(1, -1), Point(1, 0), Point(1, 1),
                    Point(0, 1), Point(-1, 1), Point(-1, 0)]
    else:
        connects = [Point(0, -1), Point(1, 0), Point(0, 1), Point(-1, 0)]
    return connects 

def getGrayDiff(img, currentPoint, tmpPoint):
    return abs(int(img[currentPoint.x, currentPoint.y]) - int(img[tmpPoint.x, tmpPoint.y]))

def regionGrow(img, seeds, thresh, p=1):
    height, weight = img.shape
    seedMark = np.zeros(img.shape)
    seedList = []
    for seed in seeds:
        if seed is not None:
            seedList.append(seed)
    label1 = 255
    connects = selectConnects(p)
    while len(seedList) > 0:
        currentPoint = seedList.pop(0)
        seedMark[currentPoint.y, currentPoint.x] = label1
        for i in range(0, 8):
            tmpX = currentPoint.x + connects[i].x
            tmpY = currentPoint.y + connects[i].y

            if tmpX < 0 or tmpY < 0 or tmpX >= height or tmpY >= weight:
                continue
            grayDiff = getGrayDiff(img, Point(currentPoint.y, currentPoint.x), Point(tmpY, tmpX))
            if grayDiff < thresh and seedMark[tmpY, tmpX] == 0:
                seedMark[tmpY, tmpX] = label1
                seedList.append(Point(tmpX, tmpY))
    return seedMark

def on_EVENT_LBUTTONDOWN(event, x, y, flags, param):
    global num
    if event == cv2.EVENT_LBUTTONDOWN:
        if num < 5:
            num = num + 1
            seeds[num] = Point(x, y)
        else:
            print("已勾选五个点")


 结合以上代码和流程图进行分析:

这是一个灰度值图像的区域生长,通过鼠标左键选取五个种子点,在seeds这个数组中我们传入初始的种子点。假设我们从中拿出一个种子点,将其对应位置设置为白色,以这个种子点作为中心实行八邻域生长。判断周围点的灰度值与它的误差是否小于thresh,如果满足条件我们将这个点加入种子点列表,在种子点列表为空时结束循环。

总结:

写这篇文章的目的主要是记录学习内容,代码部分不知道是不是自己的操作问题,但就运行结果来讲原知乎上代码存在坐标颠倒的问题,坐标(x,y)的 x 与 y 应当对于数组 a[ i , j ] 的 j 和 i ,具体表现为选取左下的点,实际却是以右上对称点进行生长。在这里我进行了修改,所以部分代码显示为x,y部分却是y,x。

后续我会基于这个方法对一些医学图像进行一些切割,来获取深度学习的样本,这里做一些进度的记录和学习内容的笔记。如果有什么想法或是问题,欢迎一起讨论。