区域生长算法与图像分割

1. 区域生长

  区域生长是一种串行区域分割的图像分割方法。区域生长是指从某个像素出发,按照一定的准则,逐步加入符合相似性判据的邻近像素,当满足生长停止条件,区域生长终止。其中相似性判据可以是像素灰度值、颜色、纹理特征等图像信息。(另一种区域生长是先将图像分割成很多的一致性较强,如区域内像素灰度值相同的小区域,再按一定的规则将小区域融合成大区域,达到分割图像的目的)

2. 算法步骤 

  区域生长算法一般分为三个步骤:

  1. 确定生长种子点
  2. 规定生长准则
  3. 确定生长停止条件

  区域生长实现的步骤如下:

  1. 对图像顺序扫描,找到第1个还没有归属的像素, 设该像素为(x0, y0);

  2. 以(x0, y0)为中心, 考虑(x0, y0)的4邻域或者8邻域像素(x, y)如果(x0, y0)满足生长准则, 将(x, y)与(x0, y0)合并(在同一区域内), 同时将(x, y)压入堆栈;

  3. 从堆栈中取出一个像素, 把它当作(x0, y0)返回到步骤2;

  4. 当堆栈为空时,返回到步骤1;

  5. 重复步骤1 - 4直到图像中的每个点都有归属时。生长结束。

3.  常用生长准则 

  颜色距离相似度:欧式距离计算,用于计算两个像素点之间的颜色相似度,从而判断它们是否应该属于同一区域。对于当前区域中的每个像素点,如果其与邻近像素点的颜色相似度大于某个阈值,则将该邻近像素点加入当前区域。在灰度图像中常计算两个点的像素值之差或是计算已划分的区域的平均值与领域点的像素之差。

4.  算法过程理解

 

  假设现在我们生长区域为生长点的8邻域。规定生长准则为选取的种子点的像素值与遍历的点的像素值之差小于等于1,则划分为同一区域。下图中红色的为划分为了同一区域,加粗的红色数字为选取的种子点。

 5.  python实现

  4邻域的区域生长算法图片分割,生长准则为种子点与遍历点像素值之差小于某个阈值。自己拍的一个照片,效果如下:

                            

    python代码如下:

import cv2
import numpy as np

class RegionalGrowth:
    def __init__(self,imgPath):
        self.imgPath=imgPath

    def zh_cn(self,string):
        return string.encode("gbk").decode('UTF-8', errors='ignore')

    def showImg(self):
        #显示图片
        img=cv2.imread(self.imgPath)
        print(type(img.shape))
        window_name = self.zh_cn('图')
        cv2.namedWindow(window_name, 0)  # 为窗口定义名字
        cv2.resizeWindow(window_name, 736, 416)  # 设置窗口显示的大小:W、H
        cv2.imshow(window_name, img)  # 显示窗口的名字, 所要显示的图片
        cv2.waitKey(0)  # 等待参数为毫秒,参数为 0表示 无限等待
        cv2.destroyAllWindows()

def showGrayImg(self): # 显示图片 img = cv2.imread(self.imgPath) grayImg = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) # 灰度图Gray=0.299*R+0.587*G+0.114*B window_name ='CT' cv2.namedWindow(window_name, 0) # 为窗口定义名字 cv2.resizeWindow(window_name, 736, 416) # 设置窗口显示的大小:W、H cv2.imshow(window_name, grayImg ) # 显示窗口的名字, 所要显示的图片 cv2.imwrite(r'./images/ctgray.jpg',grayImg) cv2.waitKey(0) # 等待参数为毫秒,参数为 0表示 无限等待 cv2.destroyAllWindows() return grayImg def meanDiff(self,grayImg,seedMark): #计算同一区域的平均值与邻域的像素点之差 areaGrayImg=np.multiply(grayImg,seedMark)#同位置元素相乘 # areaSum=np.sum(areaGrayImg) # count=np.count_nonzero(areaGrayImg == 0) # meanArea=areaSum/count #或者直接使用np.mean meanArea=np.mean(areaGrayImg) return meanArea def regional_growth (self,grayImg,seeds,threshold=15,kind=0):#种子点与遍历点像素值之差小于某个阈值归并为同一区域 # 每次区域生长的时候的种子像素之间的八个邻接点 # connects = [(-1, -1), (0, -1), (1, -1), (1, 0), (1, 1),(0, 1), (-1, 1), (-1, 0)] connects = [ (0, -1), (1, 0), (0, 1), (-1, 0)]#4邻域 height, weight = grayImg.shape #得到图片像素的高与宽 seedMark = np.zeros(grayImg.shape)#初始化全为0,用来标记同一个区域 print(seedMark) seedList = [] for seed in seeds: seedList.append(seed) #选取种子开始生长,直到没有可以生长的种子 while(len(seedList)>0): #出栈一个种子 currentPoint=seedList.pop() #并将生长点对应seedMark点赋值1 seedMark[currentPoint[0],currentPoint[1]]=1 # 以种子点为中心,八邻域的像素进行比较 for i in range(4):#0~7 tmpX = currentPoint[0] + connects[i][0] tmpY = currentPoint[1] + connects[i][1] # 判断是否为图像外的点,若是则跳过。 如果种子点是图像的边界点,邻域点就会落在图像外 if tmpX < 0 or tmpY < 0 or tmpX >= height or tmpY >= weight: continue # 判断邻域点和种子点的差值 if seedMark[tmpX, tmpY] == 0: #如果邻域点还未划分过 if kind==0: grayDiff = abs(int(grayImg[tmpX][tmpY])-int(grayImg[currentPoint[0]][currentPoint[1]])) if kind==1: grayDiff=abs(int(grayImg[tmpX][tmpY])-int(self.meanDiff(grayImg,seedMark))) #算区域内的平均值与领域点的差 # 归类 # 并作为下一个种子点放入seedList if grayDiff <= threshold: seedMark[tmpX, tmpY] = 1 seedList.append((tmpX, tmpY)) return seedMark if __name__ == '__main__': imgpath='./images/blue.jpg' rg=RegionalGrowth(imgpath) grayImg=rg.showGrayImg() seeds = [(973,996)]#初始种子 seedMarkBinary=rg.regional_growth(grayImg,seeds,2,0)#0表示使用种子点与邻域点比较,1表示选用区域平均值与邻域点比较 window_name = 'segment' cv2.namedWindow(window_name, 0) # 为窗口定义名字 cv2.resizeWindow(window_name, 736, 416) # 设置窗口显示的大小:W、H cv2.imshow(window_name, seedMarkBinary)#其中0 – 表示黑色, 1 – 表示白色 cv2.waitKey(0) cv2.destroyAllWindows()

6.   总结

  基于颜色相似度的区域生长可以应用于许多图像分割场景,例如医学图像分割、自然图像分割等。除了前面介绍的相似度生长准则,还有基于区域内灰度分布统计、基于区域形状等。另外,除了区域生长算法,还有OTSU算法、最大熵算法、自适应阈值法等都是基于阈值的分割算法。区域生长算法是一种计算量大,耗时长的算法。本文针对此图,也对区域的平均值与邻域点的差作为是否合并的尝试,通过调试不同的阈值,也未能达到好的效果,可能不同图片效果不同。

 

 参考资料:

https://huaweicloud.csdn.net/63807fcadacf622b8df891cc.html

https://blog.csdn.net/sinat_31608641/article/details/103228291

https://blog.csdn.net/weixin_43271137/article/details/130055631

https://blog.csdn.net/qq_42727880/article/details/108073661

若存在不足之处或错误之处,欢迎指正或评论!

posted @ 2023-05-07 23:07  wancy  阅读(2407)  评论(0编辑  收藏  举报