今天要实现的任务还是提取肿瘤的感兴趣区域。
有两个文件,一个是nii的原始图像文件,一个是nii的标签文件。我们要实现的是:在标签文件上选出最大层面,然后把最大层面的ROI映射到原始图像区域,在原始图像上提裁剪出ROI区域,这次裁剪的方法和上期的不同,上次是将ROI的整个边界区域提取出来,插值到224*224。这次是在标签上找到勾画ROI的最多的那一层,找到这个ROI区域的中心点在整个图像的坐标,然后根据这个坐标在映射到原始图像上,向四周延申出224*224大小的图像。这就不能保证勾画的边界。
python
import os
import SimpleITK as sitk
import numpy as np
'''
这个脚本是根据ROI的中心坐标来映射到原图像上,裁剪出大小为224*224的图像,超出区域用0填充
如果需要保存上下共三个层面,中心点还是使用的最大层面ROI的中心坐标,因为往上往下一层可能没有勾画,就会报错
'''
label_path= r"C:\Users\Administrator\Desktop\Breast\benign_label\AN_YU_MEI-label.nii"
image_path = r"C:\Users\Administrator\Desktop\Breast\benign\DCE\AN_YU_MEI.nii"
# 找出勾画ROI数值最多的那一层
def max_index(label_array):
# 遍历每张图片
max_nonzero_pixels = 0
max_nonzero_index = None
for i in range(label_array.shape[0]):
# 计算当前图片中非零像素的数量
nonzero_pixels = np.count_nonzero(label_array[i])
# 如果当前图片的非零像素数量比之前的最大值大,则更新最大值和对应的索引
if nonzero_pixels > max_nonzero_pixels:
max_nonzero_pixels = nonzero_pixels
max_nonzero_index = i
return max_nonzero_index
# 根据勾画的ROI,找到其中心坐标
def find_roi_center(max_label):
# 找到所有 ROI 区域的索引
indices = np.where(max_label == 1)
# 计算中心点坐标
center_x = int(np.round(np.mean(indices[0])))
center_y = int(np.round(np.mean(indices[1])))
return (center_x, center_y)
# 根据找到的中心点坐标,以此为中心,映射到原图上,向四周延申到224*224
def crop_roi(max_image, roi_center):
# 计算裁剪区域的边界坐标
x_min = max(0, roi_center[0] - 112)
x_max = min(max_image.shape[0], roi_center[0] + 112)
y_min = max(0, roi_center[1] - 112)
y_max = min(max_image.shape[1], roi_center[1] + 112)
# 创建一个空的224x224大小的数组,并用0填充
cropped_image = np.zeros((224, 224))
# 计算裁剪区域在目标数组中的位置
cropped_x_min = max(0, 112 - (roi_center[0] - x_min))
cropped_x_max = cropped_x_min + min(x_max - x_min, 224)
cropped_y_min = max(0, 112 - (roi_center[1] - y_min))
cropped_y_max = cropped_y_min + min(y_max - y_min, 224)
# 将ROI区域复制到裁剪图像中
cropped_image[cropped_x_min:cropped_x_max, cropped_y_min:cropped_y_max] = max_image[x_min:x_max, y_min:y_max]
return cropped_image
# 读取标签和原始图像
image_label = sitk.ReadImage(label_path)
# 读取原始NII文件
image_origin = sitk.ReadImage(image_path)
# 转换为NumPy数组
origin_array = sitk.GetArrayFromImage(image_origin)
label_array = sitk.GetArrayFromImage(image_label)
# 提取像素值
origin_array = np.array([origin_array[i] for i in range(origin_array.shape[0])])
label_array = np.array([label_array[i] for i in range(label_array.shape[0])])
# 找到最大值的索引
max_index = max_index(label_array)
# 找出标签中勾画ROI最多的那张图像
max_image = origin_array[max_index]
max_label =label_array[max_index]
#找到ROI的中心点
roi_center = find_roi_center(max_label)
# 根据中心点坐标向四周延伸裁剪出224*224
cropped_image = crop_roi(max_image, roi_center)
print("裁剪后的图像:\n", cropped_image.shape)
print("ROI 中心点坐标:", roi_center)
如果需要保存三个层面则运行以下函数,这里使用了中间的那一层ROI的中心点作为三个层面的中心点坐标,因为有的ROI可能就勾画了一层两层,没有三层,这样代码就会报错
python
def three_image(max_index):
max_label0 = label_array[max_index-1]
max_label1 = label_array[max_index]
max_label2 = label_array[max_index+1]
max_image0 = origin_array[max_index-1]
max_image1 = origin_array[max_index]
max_image2 = origin_array[max_index+1]
# 找到ROI的中心点
#roi_center0 = find_roi_center(max_label0)
roi_center1 = find_roi_center(max_label1)
#roi_center2 = find_roi_center(max_label2)
# 根据中心点坐标向四周延伸裁剪出224*224
cropped_image0 = crop_roi(max_image0, roi_center1)
cropped_image1 = crop_roi(max_image1, roi_center1)
cropped_image2 = crop_roi(max_image2, roi_center1)
# 将三个图像数组堆叠成一个新的数组
stacked_images = np.stack((cropped_image0, cropped_image1, cropped_image2))
return stacked_images
images = three_image(max_index)
print("保存了三个层面的图像:", images.shape )
全部代码
python
import os
import SimpleITK as sitk
import numpy as np
'''
这个脚本是根据ROI的中心坐标来映射到原图像上,裁剪出大小为224*224的图像,超出区域用0填充
如果需要保存上下共三个层面,中心点还是使用的最大层面ROI的中心坐标,因为往上往下一层可能没有勾画,就会报错
'''
label_path= r"C:\Users\Administrator\Desktop\Breast\benign_label\AN_YU_MEI-label.nii"
image_path = r"C:\Users\Administrator\Desktop\Breast\benign\DCE\AN_YU_MEI.nii"
# 找出勾画ROI数值最多的那一层
def max_index(label_array):
# 遍历每张图片
max_nonzero_pixels = 0
max_nonzero_index = None
for i in range(label_array.shape[0]):
# 计算当前图片中非零像素的数量
nonzero_pixels = np.count_nonzero(label_array[i])
# 如果当前图片的非零像素数量比之前的最大值大,则更新最大值和对应的索引
if nonzero_pixels > max_nonzero_pixels:
max_nonzero_pixels = nonzero_pixels
max_nonzero_index = i
return max_nonzero_index
# 根据勾画的ROI,找到其中心坐标
def find_roi_center(max_label):
# 找到所有 ROI 区域的索引
indices = np.where(max_label == 1)
# 计算中心点坐标
center_x = int(np.round(np.mean(indices[0])))
center_y = int(np.round(np.mean(indices[1])))
return (center_x, center_y)
# 根据找到的中心点坐标,以此为中心,映射到原图上,向四周延申到224*224
def crop_roi(max_image, roi_center):
# 计算裁剪区域的边界坐标
x_min = max(0, roi_center[0] - 112)
x_max = min(max_image.shape[0], roi_center[0] + 112)
y_min = max(0, roi_center[1] - 112)
y_max = min(max_image.shape[1], roi_center[1] + 112)
# 创建一个空的224x224大小的数组,并用0填充
cropped_image = np.zeros((224, 224))
# 计算裁剪区域在目标数组中的位置
cropped_x_min = max(0, 112 - (roi_center[0] - x_min))
cropped_x_max = cropped_x_min + min(x_max - x_min, 224)
cropped_y_min = max(0, 112 - (roi_center[1] - y_min))
cropped_y_max = cropped_y_min + min(y_max - y_min, 224)
# 将ROI区域复制到裁剪图像中
cropped_image[cropped_x_min:cropped_x_max, cropped_y_min:cropped_y_max] = max_image[x_min:x_max, y_min:y_max]
return cropped_image
# 读取标签和原始图像
image_label = sitk.ReadImage(label_path)
# 读取原始NII文件
image_origin = sitk.ReadImage(image_path)
# 转换为NumPy数组
origin_array = sitk.GetArrayFromImage(image_origin)
label_array = sitk.GetArrayFromImage(image_label)
# 提取像素值
origin_array = np.array([origin_array[i] for i in range(origin_array.shape[0])])
label_array = np.array([label_array[i] for i in range(label_array.shape[0])])
# 找到最大值的索引
max_index = max_index(label_array)
# 找出标签中勾画ROI最多的那张图像
max_image = origin_array[max_index]
max_label =label_array[max_index]
#找到ROI的中心点
roi_center = find_roi_center(max_label)
# 根据中心点坐标向四周延伸裁剪出224*224
cropped_image = crop_roi(max_image, roi_center)
print("裁剪后的图像:\n", cropped_image.shape)
print("ROI 中心点坐标:", roi_center)
def three_image(max_index):
max_label0 = label_array[max_index-1]
max_label1 = label_array[max_index]
max_label2 = label_array[max_index+1]
max_image0 = origin_array[max_index-1]
max_image1 = origin_array[max_index]
max_image2 = origin_array[max_index+1]
# 找到ROI的中心点
#roi_center0 = find_roi_center(max_label0)
roi_center1 = find_roi_center(max_label1)
#roi_center2 = find_roi_center(max_label2)
# 根据中心点坐标向四周延伸裁剪出224*224
cropped_image0 = crop_roi(max_image0, roi_center1)
cropped_image1 = crop_roi(max_image1, roi_center1)
cropped_image2 = crop_roi(max_image2, roi_center1)
# 将三个图像数组堆叠成一个新的数组
stacked_images = np.stack((cropped_image0, cropped_image1, cropped_image2))
return stacked_images
images = three_image(max_index)
print("保存了三个层面的图像:", images.shape )
写成类的代码,添加了保存的文件
import os
import SimpleITK as sitk
import numpy as np
class ImageProcessor:
def __init__(self, label_path, image_path):
self.label_path = label_path
self.image_path = image_path
self.origin_array = None
self.label_array = None
self.max_index = None
self.max_image = None
self.max_label = None
self.roi_center = None
# 读取标签和原始图像
def read_images(self):
image_label = sitk.ReadImage(self.label_path)
image_origin = sitk.ReadImage(self.image_path)
# 转换为NumPy数组
self.origin_array = sitk.GetArrayFromImage(image_origin)
self.label_array = sitk.GetArrayFromImage(image_label)
# 提取像素值
self.origin_array = np.array([self.origin_array[i] for i in range(self.origin_array.shape[0])])
self.label_array = np.array([self.label_array[i] for i in range(self.label_array.shape[0])])
# 找出勾画ROI数值最多的那一层
def find_max_index(self):
# 遍历每张图片
max_nonzero_pixels = 0
max_nonzero_index = None
for i in range(self.label_array.shape[0]):
# 计算当前图片中非零像素的数量
nonzero_pixels = np.count_nonzero(self.label_array[i])
# 如果当前图片的非零像素数量比之前的最大值大,则更新最大值和对应的索引
if nonzero_pixels > max_nonzero_pixels:
max_nonzero_pixels = nonzero_pixels
max_nonzero_index = i
self.max_index = max_nonzero_index
# 根据找到的中心点坐标,以此为中心,映射到原图上,向四周延伸到224*224
def crop_roi(self):
# 找出标签中勾画ROI最多的那张图像
self.max_image = self.origin_array[self.max_index]
self.max_label = self.label_array[self.max_index]
#找到ROI的中心点
self.roi_center = self.find_roi_center(self.max_label)
# 根据中心点坐标向四周延伸裁剪出224*224
cropped_image = self._crop_roi(self.max_image, self.roi_center)
return cropped_image
# 根据勾画的ROI,找到其中心坐标
def find_roi_center(self, max_label):
# 找到所有 ROI 区域的索引
indices = np.where(max_label == 1)
# 计算中心点坐标
center_x = int(np.round(np.mean(indices[0])))
center_y = int(np.round(np.mean(indices[1])))
return (center_x, center_y)
def _crop_roi(self, max_image, roi_center):
# 计算裁剪区域的边界坐标
x_min = max(0, roi_center[0] - 112)
x_max = min(max_image.shape[0], roi_center[0] + 112)
y_min = max(0, roi_center[1] - 112)
y_max = min(max_image.shape[1], roi_center[1] + 112)
# 创建一个空的224x224大小的数组,并用0填充
cropped_image = np.zeros((224, 224))
# 计算裁剪区域在目标数组中的位置
cropped_x_min = max(0, 112 - (roi_center[0] - x_min))
cropped_x_max = cropped_x_min + min(x_max - x_min, 224)
cropped_y_min = max(0, 112 - (roi_center[1] - y_min))
cropped_y_max = cropped_y_min + min(y_max - y_min, 224)
# 将ROI区域复制到裁剪图像中
cropped_image[cropped_x_min:cropped_x_max, cropped_y_min:cropped_y_max] = max_image[x_min:x_max, y_min:y_max]
return cropped_image
# 保存裁剪后的图像
def save_cropped_image(self, output_path):
cropped_image = self.crop_roi()
# 保存裁剪后的图像
sitk.WriteImage(sitk.GetImageFromArray(cropped_image), output_path)
# 保存三个层面的图像
def save_three_images(self, output_path):
images = self._three_image()
# 保存三个层面的图像
sitk.WriteImage(sitk.GetImageFromArray(images), output_path)
# 根据最大值索引裁剪出三个层面的图像
def _three_image(self):
max_label0 = self.label_array[self.max_index - 1]
max_label1 = self.label_array[self.max_index]
max_label2 = self.label_array[self.max_index + 1]
max_image0 = self.origin_array[self.max_index - 1]
max_image1 = self.origin_array[self.max_index]
max_image2 = self.origin_array[self.max_index + 1]
# 找到ROI的中心点
roi_center1 = self.find_roi_center(max_label1)
# 根据中心点坐标向四周延伸裁剪出224*224
cropped_image0 = self._crop_roi(max_image0, roi_center1)
cropped_image1 = self._crop_roi(max_image1, roi_center1)
cropped_image2 = self._crop_roi(max_image2, roi_center1)
# 将三个图像数组堆叠成一个新的数组
stacked_images = np.stack((cropped_image0, cropped_image1, cropped_image2))
return stacked_images
# 示例用法
label_path = r"C:\Users\Administrator\Desktop\Breast\benign_label\AN_YU_MEI-label.nii"
image_path = r"C:\Users\Administrator\Desktop\Breast\benign\DCE\AN_YU_MEI.nii"
output_path = r"C:\Users\Administrator\Desktop\output_image.nii"
processor = ImageProcessor(label_path, image_path)
processor.read_images()
processor.find_max_index()
cropped_image = processor.crop_roi()
processor.save_cropped_image(output_path)
processor.save_three_images(output_path)