MRI的N4偏场校正

N4BiasFieldCorrection: MRI的N4偏场校正

N4偏置场的定义和产生原因

MR scans often display intensity non-uniformities due to variations in the magnetic field. So, one part of an image might appear lighter or darker when visualized, solely because of variations in the magnetic field. The map of these variations is called the bias field. The bias field can cause problems for a classifier as the variations in signal intensity are not due to any anatomical differences.

简单代码实现与讲解

1
2
3
4
5
6
7
# 导入 SimpleITK 库,它是一个用于医学图像分析的开源工具包。
# SimpleITK 提供了丰富的算法来进行图像分割、图像配准以及其他图像处理任务。
# "as sitk" 是为库设置一个简短的别名,方便后续代码的调用。
import SimpleITK as sitk
# 定义一个字符串变量 imagePath,用于存储医学图像文件的完整路径。
# 在这个例子中,它指向的是一个 .nrrd 格式的文件。NRRD (Nearly Raw Raster Data) 是一种用于存储三维或更高维度图像数据的文件格式,常用于医学影像领域。
imagePath = 'C:/Users/RONG/Desktop/Images/001/Lung_image.nrrd'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 使用之前定义的 imagePath 变量,读取原始的医学图像文件。
# sitk.ReadImage() 会返回一个 SimpleITK 的 Image 对象。
input_image = sitk.ReadImage(imagePath)

# 使用 Otsu 自动阈值算法为输入图像创建一个二值掩模(mask)。
# 这个掩模用于区分图像中的前景(如身体组织)和背景。
# Otsu 算法能自动找到一个最佳阈值来完成分割。
# 参数 (0, 1) 分别代表掩模中背景和前景的像素值,200 是计算时直方图的分箱数量。
mask_image = sitk.OtsuThreshold(input_image, 0, 1, 200)

# 将输入图像的像素数据类型转换为 32 位浮点型(float)。
# N4 偏置场校正算法要求输入图像是浮点型数据才能进行精确计算。
input_image = sitk.Cast(input_image, sitk.sitkFloat32)

# 创建一个 N4 偏置场校正滤波器的实例。
# 这个滤波器可以修正由于磁场不均匀等因素导致的图像灰度缓慢变化的问题。
corrector = sitk.N4BiasFieldCorrectionImageFilter()

# 执行校正算法。
# 它需要两个参数:待校正的图像 (input_image) 和一个掩模 (mask_image)。
# 掩模会告诉算法只在感兴趣的区域(前景)内进行校正,从而提高效率和准确性。
output_image = corrector.Execute(input_image, mask_image)

# 将校正完成后的图像数据类型从浮点型转回 16 位有符号整型(short integer)。
# 这是一种常见的医学图像存储格式,可以减小文件体积。
output_image = sitk.Cast(output_image, sitk.sitkInt16)

# 将校正后的图像保存到硬盘。
# 文件名是 'Lung_N4.nii.gz',格式为 NIfTI(.nii),并使用 gzip (.gz) 进行压缩。
sitk.WriteImage(output_image, 'C:/Users/RONG/Desktop/Images/001/Lung_N4.nii.gz')

# 同时,将生成的掩模图像也保存下来。
# 这在后续的分割、分析或可视化步骤中可能会用到。
sitk.WriteImage(mask_image, 'C:/Users/RONG/Desktop/Images/001/Lung_mask.nii.gz')

以上可以在B站可见

批处理

好的,没有问题。为了实现批处理,我们需要对代码进行一些修改,使其能够:

  1. 遍历一个文件夹中的所有文件。
  2. 通过文件名中的特定前缀来筛选要处理的文件。
  3. 根据原始文件名生成新的输出文件名(前面加上”N4_”)。

下面是修改后的完整代码,以及详细的使用说明。


批处理 Python 脚本

batch_n4_correction.py

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# 导入所需的库
import SimpleITK as sitk
import os
import glob

def perform_n4_correction(input_path, output_path):
"""
对单个图像文件执行 N4 偏置场校正。

参数:
input_path (str): 输入图像的完整路径。
output_path (str): 校正后图像的保存路径。
"""
print("-" * 50)
print(f"正在处理: {os.path.basename(input_path)}")

try:
# 1. 读取图像
input_image = sitk.ReadImage(input_path)

# 2. 使用 Otsu 自动阈值创建掩模 (mask)
# 这是一个稳健的方法,可以自动区分前景和背景
mask_image = sitk.OtsuThreshold(input_image, 0, 1, 200)

# 3. 将输入图像类型转换为浮点型(N4算法要求)
input_image_float = sitk.Cast(input_image, sitk.sitkFloat32)

# 4. 创建并执行 N4 校正器
corrector = sitk.N4BiasFieldCorrectionImageFilter()
output_image = corrector.Execute(input_image_float, mask_image)

# 5. 将校正后的图像转回原始数据类型或常用的 Int16
# 这里我们转回 Int16,这是医学图像常用的存储格式
output_image = sitk.Cast(output_image, sitk.sitkInt16)

# 6. 保存校正后的图像
sitk.WriteImage(output_image, output_path)
print(f"处理完成, 已保存至: {os.path.basename(output_path)}")

except Exception as e:
# 如果处理过程中发生任何错误,打印错误信息并继续处理下一个文件
print(f"处理文件 {os.path.basename(input_path)} 时发生错误: {e}")


# ===================================================================
# 主程序入口
# ===================================================================
if __name__ == '__main__':
# --- 用户配置区域 ---
# 1. 设置包含原始图像的文件夹路径
# '.' 表示当前文件夹 (脚本所在的文件夹)
input_directory = './data'

# 2. 设置存放校正后图像的文件夹路径
# 如果文件夹不存在,程序会自动创建
output_directory = './output'

# 3. 设置你想要处理的文件的【特定前缀】
# 例如,如果你的文件是 'T1_001.nii.gz', 'T1_002.nii.gz' ...
# 那么前缀就是 'T1_'
# 如果要处理文件夹下所有 .nii.gz 文件,可以将前缀设置为空字符串 ''
file_prefix = 'sub'

# 4. 设置文件的扩展名
file_extension = '.nii.gz'
# --- 配置结束 ---


# 检查并创建输出文件夹
if not os.path.exists(output_directory):
os.makedirs(output_directory)
print(f"已创建输出文件夹: {output_directory}")

# 构建文件搜索模式
# 例如: './data/sub*.nii.gz'
search_pattern = os.path.join(input_directory, f"{file_prefix}*{file_extension}")

# 使用 glob 查找所有匹配前缀和扩展名的文件
file_list = glob.glob(search_pattern)

if not file_list:
print(f"在文件夹 '{input_directory}' 中未找到任何以 '{file_prefix}' 开头的文件。")
else:
print(f"找到 {len(file_list)} 个匹配的文件,开始批处理...")
# 遍历找到的每个文件
for input_file_path in file_list:
# 获取不带路径的文件名
base_name = os.path.basename(input_file_path)

# 构建新的输出文件名 (前面加上 'N4_')
output_name = f"N4_{base_name}"

# 构建完整的输出文件路径
output_file_path = os.path.join(output_directory, output_name)

# 调用函数进行 N4 校正
perform_n4_correction(input_file_path, output_file_path)

print("-" * 50)
print("所有任务已完成!")

如何使用这个脚本

  1. 文件和文件夹结构:

    为了方便管理,建议你创建如下的文件夹结构:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    主文件夹/
    ├── data/ <-- 把所有原始图像文件放在这里
    │ ├── sub-001.nii.gz
    │ ├── sub-002.nii.gz
    │ └── other-file.txt

    ├── output/ <-- 这个文件夹脚本会自动创建,用来存放结果

    └── batch_n4_correction.py <-- 把上面的Python代码保存成这个文件
  2. 修改配置:

    打开 batch_n4_correction.py 文件,找到 用户配置区域 并根据你的需求修改:

    • input_directory: 设置为你的原始数据文件夹路径(示例中是 './data')。
    • output_directory: 设置为你希望保存结果的文件夹路径(示例中是 './output')。
    • file_prefix: 这是关键。设置你想要处理的文件的公共前缀。例如,如果你的文件名都是 sub-001.nii.gz, sub-002.nii.gz 等,你的前缀就是 sub-。如果想处理文件夹下所有 .nii.gz 文件,就把它设置成空字符串 ''
  3. 运行脚本:

    打开终端(Terminal)或命令提示符(Command Prompt),进入到主文件夹(包含脚本和data文件夹的地方),然后运行脚本:

    Bash

    1
    python batch_n4_correction.py

脚本会自动查找 data 文件夹下所有符合前缀要求的文件,逐一进行 N4 校正,并将结果(以 N4_ 开头命名)保存到 output 文件夹中。


MRI的N4偏场校正
https://xingdayup.github.io/2025/07/29/N4BiasFieldCorrection/
Author
Jesse Chen
Posted on
July 29, 2025
Licensed under