区域生长是图像分割中的一种重要算法。它的基本思路是给定一个种子点,给定一个搜索范围,在这个所搜范围之内符合一定规则的点就是和种子点同一类别的点。依据这个思路,其基本步骤便是:
1、给定种子点,将种子点加入种子序列
2、将种子序列中的第一个元素弹出,搜索器范围(常用8邻域)符合规则的点,将该点加入种子序列。
3、循环1,2,所有做过种子点的元素便是和最开始的种子点同一类别的元素。
在这里:我们通常使用8邻域作为2D图像搜索范围,使用两个元素的欧氏距离为评估规则。
我这里写了3D元素的代码,有兴趣的同志可以改成2D的。(这里使用的是脑部MRI的数据,我们想做的是将脑组织提取出来,即将MRI影像中的颅骨等非脑部组织去掉,以便我们分割静脉)
import numpy as np
import cv2
import numpy as np
import SimpleITK as sitk
import numpy as np
import matplotlib.pyplot as plt
import math
def get_img_array(path):
ds_img = sitk.ReadImage(path)
image_arrays = sitk.GetArrayFromImage(ds_img)
image_arrays = (image_arrays - image_arrays.min()) / (image_arrays.max() - image_arrays.min())
image_arrays = image_arrays.astype(np.float32)
return image_arrays
def if_out_of_bounds(local,shape):
x,y,z=local
h,w,c=shape
h,w,c=h-1,w-1,c-1
if(x<0 or y<0 or z<0 or x>h or y>w or z>c):
return False
else:
return True
def area_grow(img,seed,t):
seed_list=[seed]
class_k=1
img_mark=np.zeros_like(img)
h,w,c=img.shape
while(len(seed_list)>0):
seed_tmp = seed_list[0]
seed_list.pop(0)
x,y,z=seed_tmp
img_mark[x,y,z] = class_k
for i in range(x-1,x+2):
for j in range(y-1,y+2):
for k in range(z-1,z+2):
if([x,y,z]!=[i,j,k]):
if(if_out_of_bounds([i,j,k],img.shape)):
pixes_n=img[i,j,k]
pixes_seed=img[x,y,z]
dist=abs((pixes_n-pixes_seed))
if(dist<t and img_mark[i,j,k]==0):
img_mark[i,j,k]=class_k
seed_list.append([i,j,k])
img[img_mark==0]=0
return img
def get_dist(p1,p2):
return math.fabs(p1,p2)
if __name__=="__main__":
img_array=get_img_array("0transfei.nii")
img_array=img_array.transpose(1,2,0)
h,w,c=img_array.shape
seed=[h//2,w//2,c//2]
t=0.01
seg_array=area_grow(img_array,seed,t)
seg_array=seg_array.transpose(2,0,1)
for img,seg in zip(img_array,seg_array):
plt.subplot(1,2,1)
plt.imshow(img)
plt.subplot(1,2,2)
plt.imshow(seg)
plt.show()