图像分割任务的数据预处理
今天我们要处理的肺栓塞数据参考文章(doi.org/10.1007/s00330-020-06699-8),我没有肺栓塞数据,今天使用乳腺癌数据代替。准备的数据image和mask都是nii格式的数据。今天仅处理了image没有处理mask。
1、查看一位患者的数据形状
import nibabel as nib
# 加载 .nii 文件
file_path = r"D:\Data\DegmentData\OriginalNii\DCE\zhang_san.nii"
image = nib.load(file_path)
# 获取数据数组
data = image.get_fdata()
# 打印数据的形状
print("数据的形状:", data.shape)
数据的形状: (480, 480, 36)
2、将原始的36张图像进行可视化
import nibabel as nib
import matplotlib.pyplot as plt
# 加载处理后的NIfTI文件
processed_path = r"D:\Data\DegmentData\OriginalNii\DCE\CAO_ZHAN_GUO.nii"
processed_img = nib.load(processed_path)
processed_data = processed_img.get_fdata() # 获取处理后的数据,形状为(480, 480, 36)
# 可视化36张图像
def visualize_slices(data, num_slices):
"""
可视化3D数据中的多张切片
:param data: 3D数据,形状为(height, width, depth)
:param num_slices: 需要可视化的切片数量
"""
depth = data.shape[2] # 获取切片的数量
slice_indices = np.linspace(0, depth - 1, num_slices, dtype=int) # 均匀选择切片索引
# 创建子图
fig, axes = plt.subplots(6, 6, figsize=(15, 15)) # 6x6的子图布局
fig.suptitle("Processed Image Slices", fontsize=16)
for i, idx in enumerate(slice_indices):
ax = axes[i // 6, i % 6] # 获取当前子图
ax.imshow(data[:, :, idx], cmap="gray") # 显示切片
ax.set_title(f"Slice {idx}")
ax.axis("off") # 关闭坐标轴
plt.tight_layout()
plt.show()
# 可视化36张切片
visualize_slices(processed_data, 36)
3、对一个文件夹处理,将数据进行窗宽、窗位(窗宽160-180,窗位620-650)及最大最小归一化处理,改为 512,512大小,每个nii数据的36张图像不改变
DCE文件夹下存放着每位患者的nii数据,处理后保存到一个新的文件夹中
import os
import nibabel as nib
import numpy as np
from scipy.ndimage import zoom
from tqdm import tqdm # 导入tqdm库用于显示进度条
# 输入文件夹路径和输出文件夹路径
input_folder = r"D:\Data\DegmentData\OriginalNii\DCE" # 输入文件夹路径
output_folder = r"D:\Data\DegmentData\ProcessedNii\DCE" # 输出文件夹路径
# 如果输出文件夹不存在,创建它
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# 获取输入文件夹中的所有.nii文件
nii_files = [f for f in os.listdir(input_folder) if f.endswith(".nii")]
# 使用tqdm显示处理进度
for filename in tqdm(nii_files, desc="Processing files", unit="file"):
file_path = os.path.join(input_folder, filename) # 获取每个文件的完整路径
print(f"\n正在处理文件: {file_path}")
# 读取NIfTI文件
img = nib.load(file_path)
data = img.get_fdata() # 获取图像数据,形状为(480, 480, 36)
# 定义窗口宽度和窗位
window_width = 180 # 窗宽
window_level = 635 # 窗位 (620-650的中间值)
# 计算窗口范围
window_min = window_level - window_width / 2
window_max = window_level + window_width / 2
# 窗口处理:将像素值限制在[window_min, window_max]范围内
data_windowed = np.clip(data, window_min, window_max)
# 最小-最大归一化到[0, 1]范围
data_normalized = (data_windowed - window_min) / (window_max - window_min)
# 确保归一化后的值在[0, 1]范围内
data_normalized = np.clip(data_normalized, 0, 1)
# 调整图像大小到(512, 512, 36),只改变前两个维度,第三维不变
new_shape = (512, 512, data_normalized.shape[2])
zoom_factors = (new_shape[0] / data_normalized.shape[0], new_shape[1] / data_normalized.shape[1], 1) # 保持张数不变
data_resized = zoom(data_normalized, zoom_factors, order=1) # 使用双线性插值 (order=1)
# 打印调整后的数据形状
print(f"调整后的数据形状: {data_resized.shape}")
# 构建新的文件名,将原始文件名的`.nii`替换为`_processed.nii`
output_filename = filename.replace(".nii", "_processed.nii")
output_file_path = os.path.join(output_folder, output_filename)
# 保存处理后的数据为新的NIfTI文件
processed_img = nib.Nifti1Image(data_resized, img.affine, img.header)
nib.save(processed_img, output_file_path)
print(f"处理完成,文件已保存到: {output_file_path}")
# 所有文件处理完成
print("\n所有数据处理完成!")
对处理后的一位患者数据进行可视化,仅画出9张图像。
import nibabel as nib
import matplotlib.pyplot as plt
import numpy as np
# 加载处理后的NIfTI文件
processed_path = r"D:\Data\DegmentData\OriginalNii\DCE\CAO_ZHAN_GUO_processed.nii"
processed_img = nib.load(processed_path)
processed_data = processed_img.get_fdata() # 获取处理后的数据,形状为(480, 480, 36)
# 可视化9张图像
def visualize_slices(data, num_slices):
"""
可视化3D数据中的多张切片
:param data: 3D数据,形状为(height, width, depth)
:param num_slices: 需要可视化的切片数量
"""
depth = data.shape[2] # 获取切片的数量
slice_indices = np.linspace(0, depth - 1, num_slices, dtype=int) # 均匀选择切片索引
# 创建子图
fig, axes = plt.subplots(3, 3, figsize=(12, 12)) # 3x3的子图布局
fig.suptitle("Processed Image Slices", fontsize=16)
for i, idx in enumerate(slice_indices):
ax = axes[i // 3, i % 3] # 获取当前子图
ax.imshow(data[:, :, idx], cmap="gray") # 显示切片
ax.set_title(f"Slice {idx}")
ax.axis("off") # 关闭坐标轴
plt.tight_layout()
plt.show()
# 可视化9张切片
visualize_slices(processed_data, 9)
这里处理的不好,因为论文中的是CT肺栓塞的图像,我的是乳腺MRI的图像。如果是肺栓塞的图像应该是好的。
4对一个文件夹处理,将数据进行窗宽160-180,窗位620-650及最大最小归一化处理,并进行三通道处理。改为( 512,512,3)--可以不进行三通处理,论文中处理了
可以不进行三通道处理,之前的是36张图像,处理后成了3张图像。 对image进行了三通道处理,mask也要进行三通道处理,但是,mask进行插值缩放512×512是,使用的是最邻近插值。
将文件夹下的所有数据进行处理保存到新的文件夹下
import os
import nibabel as nib
import numpy as np
from scipy.ndimage import zoom
from tqdm import tqdm # 导入tqdm库用于显示进度条
# 输入文件夹路径和输出文件夹路径
input_folder = r"D:\Data\DegmentData\OriginalNii\DCE" # 输入文件夹路径
output_folder = r"D:\Data\DegmentData\ProcessedNii\DCE" # 输出文件夹路径
# 如果输出文件夹不存在,创建它
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# 获取输入文件夹中的所有.nii文件
nii_files = [f for f in os.listdir(input_folder) if f.endswith(".nii")]
# 使用tqdm显示处理进度
for i, filename in tqdm(enumerate(nii_files, 1), desc="Processing files", total=len(nii_files), unit="file"):
file_path = os.path.join(input_folder, filename) # 获取每个文件的完整路径
print(f"\n正在处理第{i}个文件: {file_path}")
# 读取NIfTI文件
img = nib.load(file_path)
data = img.get_fdata() # 获取图像数据,形状为(480, 480, 36)
# 定义窗口宽度和窗位
window_width = 180 # 窗宽
window_level = 635 # 窗位 (620-650的中间值)
# 计算窗口范围
window_min = window_level - window_width / 2
window_max = window_level + window_width / 2
# 窗口处理:将像素值限制在[window_min, window_max]范围内
data_windowed = np.clip(data, window_min, window_max)
# 最小-最大归一化到[0, 1]范围
data_normalized = (data_windowed - window_min) / (window_max - window_min)
# 确保归一化后的值在[0, 1]范围内
data_normalized = np.clip(data_normalized, 0, 1)
# 调整图像大小到(512, 512, 36),只改变前两个维度,第三维不变
new_shape = (512, 512, data_normalized.shape[2])
zoom_factors = (new_shape[0] / data_normalized.shape[0], new_shape[1] / data_normalized.shape[1], 1) # 保持张数不变
data_resized = zoom(data_normalized, zoom_factors, order=1) # 使用双线性插值 (order=1)
# 创建三通道图像 (512, 512, 3),我们将从数据的不同切片生成RGB通道
# 例如,我们使用第1、第18、第36个切片作为R、G、B通道(也可以选择其他合适的切片)
channel_1 = data_resized[:, :, 0] # 使用第1个切片作为R通道
channel_2 = data_resized[:, :, 17] # 使用第18个切片作为G通道
channel_3 = data_resized[:, :, 35] # 使用第36个切片作为B通道
# 合并为三通道图像
rgb_image = np.stack([channel_1, channel_2, channel_3], axis=-1)
# 打印调整后的数据形状
print(f"调整后的三通道图像形状: {rgb_image.shape}")
# 构建新的文件名,将原始文件名的`.nii`替换为`_processed.nii`
output_filename = filename.replace(".nii", "_processed.nii")
output_file_path = os.path.join(output_folder, output_filename)
# 保存处理后的数据为新的NIfTI文件
processed_img = nib.Nifti1Image(rgb_image, img.affine, img.header)
nib.save(processed_img, output_file_path)
print(f"处理完成,文件已保存到: {output_file_path}")
# 所有文件处理完成
print("\n所有数据处理完成!")
对一个病人的数据进行可视化
import matplotlib.pyplot as plt
import numpy as np
# 假设已经有 rgb_image (512, 512, 3),即三个通道的合成图像
# 这里是如何以灰度图显示每个通道以及合成后的RGB图像
def visualize_rgb_channels_in_gray(rgb_image):
# 分离RGB通道
channel_1 = rgb_image[:, :, 0] # R通道
channel_2 = rgb_image[:, :, 1] # G通道
channel_3 = rgb_image[:, :, 2] # B通道
# 创建子图,展示R、G、B通道以及合成的RGB图像(以灰度显示)
fig, axes = plt.subplots(2, 2, figsize=(10, 10))
# 可视化R通道(灰度)
axes[0, 0].imshow(channel_1, cmap="gray")
axes[0, 0].set_title("Red Channel (Gray)")
axes[0, 0].axis('off')
# 可视化G通道(灰度)
axes[0, 1].imshow(channel_2, cmap="gray")
axes[0, 1].set_title("Green Channel (Gray)")
axes[0, 1].axis('off')
# 可视化B通道(灰度)
axes[1, 0].imshow(channel_3, cmap="gray")
axes[1, 0].set_title("Blue Channel (Gray)")
axes[1, 0].axis('off')
# 可视化合成后的RGB图像(灰度)
axes[1, 1].imshow(rgb_image, cmap="gray")
axes[1, 1].set_title("RGB Image (Gray)")
axes[1, 1].axis('off')
# 调整布局
plt.tight_layout()
plt.show()
# 调用可视化函数
visualize_rgb_channels_in_gray(rgb_image)