三维区域生长
from operator import eq
import numpy as np
import pydicom as dicom
from skimage.measure import label
from skimage.measure import regionprops
from skimage.morphology import thin
import os
import SimpleITK as sptk
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import cv2
def regiongrowth(orig_image, seed_matrix, threshold):
"""3-D区域生长算法
# Arguments:
orig_image:待分割图像
seed_matrix:种子矩阵
threshold:生长条件,即待分割图中的像素值与目标像素值之间的可承受的差值
# Returns
seg:最终分割后的mask
num_region:分割区域的个数
# Example
regiongrow(orig_image, seed_matrix, 50)
"""
orig_image = np.array(orig_image, dtype=np.float32) # 将图像数值格式转为float
markers = seed_matrix#thin(seed_matrix) # 将种子所在区域缩小为一个点,后面限定区域时使用??????
coordinate_nonzero = markers.nonzero() # 当种子为矩阵时,获取种子点的坐标值,返回两个数组,分别是非零元素所在行和所在列
coordinate_nonzero = np.transpose(coordinate_nonzero) # 获取种子点的坐标值的转置
seed_value = []
for coordinate_i in coordinate_nonzero:
seed_value.append(orig_image[coordinate_i[0], coordinate_i[1], coordinate_i[2]]) # 获取种子点的灰度值
size_x, size_y, size_z = orig_image.shape
seg_image = np.array(np.zeros((size_x, size_y, size_z)), dtype=bool) # 初始化一个bool格式的矩阵储存分割结果
for i, each_seed_value in enumerate(seed_value):
all_satisfied = abs(orig_image - each_seed_value) <= threshold # 所有满足单个种子点阈值条件的像素点
seg_image = seg_image | all_satisfied # 所有满足多有种子点阈值条件的像素点
label_seg_image = label(seg_image) # 将所有连通区域打label????????
area_region = regionprops(label_seg_image) # 统计被标记的区域的面积分布,返回值为显示区域总数
seg = np.array(np.zeros((size_x, size_y, size_z)), dtype=np.float32) # 初始化一个float格式的矩阵储存分割结果
for masker in coordinate_nonzero: # 提取maskers所在的连通区域
for each_area_region in area_region:
for coord in each_area_region.coords:
if sum(eq(coord, masker)) == 2: # 若连通区域中包含masker,则保留此连通区域
for idx in each_area_region.coords:
seg[idx[0], idx[1], idx[2]] = 1
break
seg = label(seg) # 将有效的label进行标记
num_region = seg.max() # 有效连通label的个数
return seg, num_region
if __name__ == "__main__":
#one_slices = dicom.dcmread(r'D:\LIDC\dicm\LIDC-IDRI\LIDC-IDRI-0001\01-01-2000-30178\3000566-03192\000100.dcm', force=True)
#orig_image = one_slices.pixel_array
#orig_image= np.array(cv2.imread("D:\LIDC\cup.jpg"))
PathDicom = "D:/LIDC/dicm/LIDC-IDRI/LIDC-IDRI-0001/01-01-2000-30178/3000566-03192" # 与python文件同一个目录下的文件夹
lstFilesDCM = []
for dirName, subdirList, fileList in os.walk(PathDicom):
for filename in fileList:
if ".dcm" in filename.lower(): # 判断文件是否为dicom文件
lstFilesDCM.append(os.path.join(dirName, filename)) # 加入到列表中
array3D = np.zeros((1, 512, 512))
for dicmImage in lstFilesDCM:
image = sptk.ReadImage(dicmImage)
image_array2D = np.squeeze(sptk.GetArrayFromImage(image))
image_array = np.append(array3D, image_array2D)
dim = array3D.shape
array3D = image_array.reshape(dim[0] + 1, dim[1], dim[2])
array3D = np.delete(array3D, 0, 0)
array3D=array3D.transpose((1,2,0))
#print(orig_image.shape)
plt.figure()
plt.imshow(array3D[:,:,2])
plt.show()
#orig_image = (orig_image - np.min(orig_image))/(np.max(orig_image) - np.min(orig_image)) * 255
#orig_image = np.array(orig_image, dtype=np.uint8)
#plt.figure()
#plt.imshow(orig_image)
#plt.show()
# dst_image = np.zeros((orig_image.shape[0], orig_image.shape[1]))
# dst_image = cv2.adaptiveThreshold(orig_image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 511, 2)
# dst_image = dst_image / 255 * (np.max(orig_image) - np.min(orig_image)) + np.min(orig_image)
# plt.figure()
# plt.subplot(1, 2, 1)
# plt.imshow(orig_image)
# plt.subplot(1, 2, 2)
# plt.imshow(dst_image)
# plt.show()
size_x, size_y, size_z = array3D.shape
orig_image = np.array(array3D, dtype=np.float32)
orig_image_min = orig_image.min()
orig_image = orig_image - orig_image_min
orig_image_max = orig_image.max()
orig_image = orig_image / orig_image_max * 255
orig_image = np.array(orig_image, dtype=np.uint8)
seed_matrix = np.zeros((size_x, size_y, size_z))
# 指定想要分割的像素的坐标,按照dicom的坐标系
coordinate1_x = 260
coordinate1_y = 158
coordinate1_z = 2
coordinate2_x = 260
coordinate2_y = 370
coordinate2_z = 2
#coordinate1_x = 138
#coordinate1_y = 252
#coordinate2_x = 346
#coordinate2_y = 252
#coordinate1_x = 226
#coordinate1_y = 290
#coordinate2_x = 308
#coordinate2_y = 290
# 矩阵按行号、列号,与dicom正好相反
seed_matrix[coordinate1_x, coordinate1_y, coordinate1_z] = orig_image[coordinate1_x, coordinate1_y, coordinate1_z]
seed_matrix[coordinate2_x, coordinate2_y, coordinate2_z] = orig_image[coordinate2_x, coordinate2_y, coordinate2_z]
seg_image, num_region = regiongrowth(orig_image, seed_matrix, 3) # 需指定阈值
print("返回的矩阵维数:", seg_image.shape)
print("连通区域数目:", num_region)
plt.figure()
fig1=plt.subplot(1, 2, 1)
fig2 = plt.subplot(1, 2, 2)
plt.sca(fig1)
plt.imshow(orig_image[:,:,2])
plt.sca(fig2)
plt.imshow(seg_image[:,:,2])
plt.show()