图像分割 - 区域生长
目录
1. 介绍
2. 代码详解
3. 代码
1. 介绍
分割的目的是将图像分为多个区域
常见的图像分割技术主要建立在以下两个关键特性上:一是图像区域间的灰度不连续性(如Canny边缘检测等方法),二是同一区域内部的灰度一致性(如阈值法和区域生长法等)。
区域生长主要建立在统一区域内像素灰度特性的一致性基础之上,并遵循预先定义的增长准则逐步发展出更大的区域范围。具体来说, 该方法的核心在于将预设的像素点作为种子, 通过与周围像素进行比较分析, 满足灰度相似性条件(即灰度值差异较小)的新像素加入新的种子集合中, 从而扩展区域范围。
区域生长的步骤为:
1. 先定义一组种子
2. 识别每个种子周围的八个相邻像素区域,并对这些区域进行亮度评估;若发现有亮度接近的新区域,则将其划分作独立的新种子
3. 循环这个过程,直到种子全部遍历完
2. 代码详解
这里不同的地方在于传入的种子是一副图像。
对给定的图像执行二值化转换后,我们确定该二值化的图像数据输入到seeds变量中。接着利用np.where函数筛选出seeds中大于零的元素坐标,并将这些坐标存储于seed_list变量中作为最终的种子列表输出。

循环停止的条件是种子列表里面没有种子。
将每一个种子取出,然后将对应的位置作为区域分割的结果 dst[x,y] = 255 。
根据之前定义的connects 周围8个点的相对位置偏差,找到周围的 8邻域

如果 8邻域不在图像上的话,就跳过这次判断
在图像处理中进行操作时,请先对灰度值进行对比检查;同时需确定该区域是否已被处理过以避免无限循环。
假设存在两个相邻点AB,在A被选为初始种子的情况下(即称为源点),B位于A的领域范围内满足相似性条件,则会将B点加入到种子列表中进行后续处理(即标记为待扩展单元)。在检查B点时(即判断其领域),由于已经确定了其领域中的源点A已经完成扩展操作(即成为区域生长后的区域),因此该源点不会再次被选作新的待扩展单元。
如果都满足的话,保存到种子列表里面

3. 代码
import cv2
import numpy as np
# 区域生长算法
def regional_growth(image, seeds, thresh=5): # 这里的seeds是一副图像
height, weight = image.shape[0], image.shape[1] # 图像的 height和 width
dst= np.zeros(image.shape, dtype=np.uint8) # 处理的结果
seed_list = [] # 种子列表
x,y = np.where(seeds > 0) # 找到种子seeds里面的种子
for i in range(len(x)):
seed_list.append((x[i],y[i]))
connects = [(-1, -1), (0, -1), (1, -1), (1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0)] # 8 邻域
while len(seed_list) > 0: # 判断种子受否剩余
point = seed_list.pop(0) # 取出第一个
x, y = point[0],point[1]
dst[x, y] = 255 # 将对应位置的点标记为 255
for i in range(8): # 对种子周围的 8个点一次进行相似性判断
connects_tmp = connects[i] # 8 邻域
x_tmp= x+ connects_tmp[0]
y_tmp= y+ connects_tmp[1]
if (x_tmp < 0) or (y_tmp < 0) or (x_tmp >= height) or (y_tmp >= weight): # 是否超出限定阈值
continue
gray_diff = np.abs(int(image[x, y]) - int(image[x_tmp, y_tmp])) # 判断相似性
if (gray_diff <= thresh) and (dst[x_tmp, y_tmp] == 0): # 相似的话储存为新的种子
dst[x_tmp,y_tmp] = 255
seed_list.append((x_tmp,y_tmp))
return dst
# 区域生长 主程序
img = cv2.imread("./img.tif", flags=0)
_, img_bin = cv2.threshold(img, 254, 255, cv2.THRESH_BINARY) # 阈值处理产生种子区域
dst = regional_growth(img, img_bin)
cv2.imshow('img', np.hstack((img,dst)))
cv2.waitKey()
cv2.destroyAllWindows()
处理结果:

这里阈值产生的种子图像为:

