三维CT图像重建算法
三维CT图像重建是一个复杂的过程,涉及从多个二维投影重建三维体积。下面我将提供一个完整的MATLAB实现,包括滤波反投影(FBP)算法和迭代重建算法(如SART),以及相关的预处理和后处理步骤。
三维CT重建算法实现
matlab
% 三维CT图像重建算法
clear; clc; close all;
%% 1. 参数设置
fprintf('设置重建参数...\n');
% 扫描几何参数
num_angles = 360; % 投影角度数
angles = linspace(0, 360-360/num_angles, num_angles); % 角度范围 (度)
source_to_detector = 1000; % 源到探测器的距离 (mm)
source_to_object = 500; % 源到物体的距离 (mm)
detector_size = 256; % 探测器尺寸 (像素)
detector_pixel_size = 0.5; % 探测器像素尺寸 (mm)
% 重建参数
volume_size = 256; % 重建体积尺寸 (体素)
voxel_size = 0.25; % 体素尺寸 (mm)
num_iterations = 10; % 迭代算法迭代次数
% 滤波器参数
filter_type = 'ram-lak'; % 滤波器类型: 'ram-lak', 'shepp-logan', 'cosine', 'hamming'
%% 2. 生成模拟三维Shepp-Logan模体
fprintf('生成模拟三维Shepp-Logan模体...\n');
phantom_3d = generate_3d_shepp_logan(volume_size);
% 显示模体切片
figure;
subplot(2,2,1);
imagesc(squeeze(phantom_3d(volume_size/2, :, :)));
title('XY平面中心切片');
axis image; colormap gray; colorbar;
subplot(2,2,2);
imagesc(squeeze(phantom_3d(:, volume_size/2, :)));
title('XZ平面中心切片');
axis image; colormap gray; colorbar;
subplot(2,2,3);
imagesc(squeeze(phantom_3d(:, :, volume_size/2)));
title('YZ平面中心切片');
axis image; colormap gray; colorbar;
subplot(2,2,4);
isosurface(phantom_3d, 0.5);
title('三维等值面');
axis equal; axis vis3d; camlight; lighting gouraud;
%% 3. 模拟投影数据采集 (正向投影)
fprintf('模拟投影数据采集...\n');
sinogram = forward_project_3d(phantom_3d, angles, detector_size, ...
source_to_detector, source_to_object, ...
detector_pixel_size, voxel_size);
% 显示正弦图
figure;
imagesc(sinogram);
title('正弦图 (所有角度)');
xlabel('探测器位置');
ylabel('投影角度');
colormap gray; colorbar;
%% 4. 添加噪声 (模拟真实CT数据)
fprintf('添加噪声模拟真实数据...\n');
noise_level = 0.05; % 噪声水平
sinogram_noisy = add_ct_noise(sinogram, noise_level);
% 显示带噪声的正弦图
figure;
imagesc(sinogram_noisy);
title('带噪声的正弦图');
xlabel('探测器位置');
ylabel('投影角度');
colormap gray; colorbar;
%% 5. 滤波反投影 (FBP) 重建
fprintf('开始滤波反投影重建...\n');
recon_fbp = fbp_reconstruct_3d(sinogram_noisy, angles, volume_size, ...
source_to_detector, source_to_object, ...
detector_pixel_size, voxel_size, filter_type);
% 显示FBP重建结果
figure;
subplot(2,2,1);
imagesc(squeeze(recon_fbp(volume_size/2, :, :)));
title('FBP: XY平面中心切片');
axis image; colormap gray; colorbar;
subplot(2,2,2);
imagesc(squeeze(recon_fbp(:, volume_size/2, :)));
title('FBP: XZ平面中心切片');
axis image; colormap gray; colorbar;
subplot(2,2,3);
imagesc(squeeze(recon_fbp(:, :, volume_size/2)));
title('FBP: YZ平面中心切片');
axis image; colormap gray; colorbar;
subplot(2,2,4);
isosurface(recon_fbp, 0.3);
title('FBP: 三维等值面');
axis equal; axis vis3d; camlight; lighting gouraud;
%% 6. 迭代重建算法 (SART)
fprintf('开始SART迭代重建...\n');
recon_sart = sart_reconstruct_3d(sinogram_noisy, angles, volume_size, ...
source_to_detector, source_to_object, ...
detector_pixel_size, voxel_size, num_iterations);
% 显示SART重建结果
figure;
subplot(2,2,1);
imagesc(squeeze(recon_sart(volume_size/2, :, :)));
title('SART: XY平面中心切片');
axis image; colormap gray; colorbar;
subplot(2,2,2);
imagesc(squeeze(recon_sart(:, volume_size/2, :)));
title('SART: XZ平面中心切片');
axis image; colormap gray; colorbar;
subplot(2,2,3);
imagesc(squeeze(recon_sart(:, :, volume_size/2)));
title('SART: YZ平面中心切片');
axis image; colormap gray; colorbar;
subplot(2,2,4);
isosurface(recon_sart, 0.3);
title('SART: 三维等值面');
axis equal; axis vis3d; camlight; lighting gouraud;
%% 7. 重建质量评估
fprintf('评估重建质量...\n');
% 计算均方根误差 (RMSE)
rmse_fbp = compute_rmse(phantom_3d, recon_fbp);
rmse_sart = compute_rmse(phantom_3d, recon_sart);
% 计算结构相似性指数 (SSIM)
ssim_fbp = compute_ssim_3d(phantom_3d, recon_fbp);
ssim_sart = compute_ssim_3d(phantom_3d, recon_sart);
fprintf('重建质量指标:\n');
fprintf('FBP - RMSE: %.4f, SSIM: %.4f\n', rmse_fbp, ssim_fbp);
fprintf('SART - RMSE: %.4f, SSIM: %.4f\n', rmse_sart, ssim_sart);
% 绘制中心行剖面比较
center_slice = volume_size/2;
phantom_profile = squeeze(phantom_3d(center_slice, center_slice, :));
fbp_profile = squeeze(recon_fbp(center_slice, center_slice, :));
sart_profile = squeeze(recon_sart(center_slice, center_slice, :));
figure;
plot(phantom_profile, 'k-', 'LineWidth', 2);
hold on;
plot(fbp_profile, 'r--', 'LineWidth', 1.5);
plot(sart_profile, 'b-.', 'LineWidth', 1.5);
legend('原始模体', 'FBP重建', 'SART重建');
title('中心行剖面比较');
xlabel('体素位置');
ylabel('强度值');
grid on;
%% 8. 辅助函数定义
function phantom_3d = generate_3d_shepp_logan(size)
% 生成三维Shepp-Logan模体
% 基于2D Shepp-Logan模体扩展为3D
% 生成2D Shepp-Logan模体
phantom_2d = phantom('Modified Shepp-Logan', size);
% 扩展为3D
phantom_3d = zeros(size, size, size);
for z = 1:size
% 在Z方向上添加一些变化以创建3D结构
scale = 1 - 0.5 * abs(z - size/2) / (size/2);
phantom_3d(:, :, z) = phantom_2d * scale;
% 添加一些球体以创建真正的3D结构
if z > size/4 && z < 3*size/4
% 在中心区域添加球体
[x, y] = meshgrid(1:size, 1:size);
center = size/2;
radius = size/8;
% 创建球体
sphere = ((x - center).^2 + (y - center).^2) <= radius^2;
phantom_3d(:, :, z) = phantom_3d(:, :, z) + 0.3 * sphere;
end
end
% 归一化到[0, 1]范围
phantom_3d = (phantom_3d - min(phantom_3d(:))) / (max(phantom_3d(:)) - min(phantom_3d(:)));
end
function sinogram = forward_project_3d(volume, angles, detector_size, ...
source_to_detector, source_to_object, ...
detector_pixel_size, voxel_size)
% 三维正向投影 - 模拟CT扫描过程
num_angles = length(angles);
sinogram = zeros(num_angles, detector_size);
% 计算几何参数
magnification = source_to_detector / source_to_object;
detector_length = detector_size * detector_pixel_size;
% 创建探测器坐标
detector_coords = linspace(-detector_length/2, detector_length/2, detector_size);
% 对每个角度进行投影
for i = 1:num_angles
angle = angles(i);
% 旋转体积
rotated_volume = imrotate3(volume, angle, [0 0 1], 'crop', 'linear');
% 计算投影 (沿X轴积分)
projection = squeeze(sum(rotated_volume, 1));
% 考虑几何放大
projection = imresize(projection, [detector_size, detector_size] * magnification);
% 提取中心行作为投影
center_row = round(size(projection, 1)/2);
sinogram(i, :) = projection(center_row, :);
end
end
function sinogram_noisy = add_ct_noise(sinogram, noise_level)
% 添加CT噪声模拟真实数据
% 确保正弦图为正值
sinogram = max(sinogram, 0);
% 模拟光子计数噪声 (泊松噪声)
max_val = max(sinogram(:));
sinogram_noisy = imnoise(sinogram / max_val, 'poisson') * max_val;
% 添加高斯噪声
sinogram_noisy = imnoise(sinogram_noisy, 'gaussian', 0, noise_level^2);
end
function recon_volume = fbp_reconstruct_3d(sinogram, angles, volume_size, ...
source_to_detector, source_to_object, ...
detector_pixel_size, voxel_size, filter_type)
% 三维滤波反投影重建
num_angles = length(angles);
recon_volume = zeros(volume_size, volume_size, volume_size);
% 计算几何参数
magnification = source_to_detector / source_to_object;
detector_length = detector_size * detector_pixel_size;
% 创建滤波器
filter = create_filter(filter_type, detector_size, detector_pixel_size);
% 对每个角度进行反投影
for i = 1:num_angles
angle = angles(i);
% 获取当前角度的投影
projection = sinogram(i, :);
% 滤波投影
filtered_proj = filter_projections(projection, filter);
% 反投影到体积
recon_volume = backproject_3d(recon_volume, filtered_proj, angle, ...
volume_size, voxel_size, ...
source_to_detector, source_to_object, ...
detector_pixel_size);
end
% 归一化重建体积
recon_volume = recon_volume / num_angles;
end
function filter = create_filter(filter_type, detector_size, detector_pixel_size)
% 创建重建滤波器
% 创建频率轴
freq = linspace(-1, 1, detector_size) * (1/(2*detector_pixel_size));
% 创建Ram-Lak滤波器 (斜坡滤波器)
ramp_filter = abs(freq);
% 根据滤波器类型应用窗函数
switch lower(filter_type)
case 'ram-lak'
filter = ramp_filter;
case 'shepp-logan'
% Shepp-Logan滤波器: sinc窗斜坡滤波器
sinc_window = sinc(freq / (2*max(freq)));
filter = ramp_filter .* sinc_window;
case 'cosine'
% Cosine滤波器
cosine_window = cos(pi * freq / (2*max(freq)));
filter = ramp_filter .* cosine_window;
case 'hamming'
% Hamming窗滤波器
hamming_window = 0.54 + 0.46 * cos(pi * freq / max(freq));
filter = ramp_filter .* hamming_window;
otherwise
error('未知滤波器类型: %s', filter_type);
end
% 确保滤波器为行向量
filter = filter(:)';
end
function filtered_proj = filter_projections(projection, filter)
% 滤波投影数据
% 傅里叶变换
proj_fft = fft(projection);
% 应用滤波器
filtered_fft = proj_fft .* filter;
% 逆傅里叶变换
filtered_proj = real(ifft(filtered_fft));
end
function volume = backproject_3d(volume, projection, angle, volume_size, voxel_size, ...
source_to_detector, source_to_object, detector_pixel_size)
% 三维反投影
% 计算几何参数
magnification = source_to_detector / source_to_object;
detector_length = detector_size * detector_pixel_size;
% 创建体积坐标网格
[x, y, z] = meshgrid(1:volume_size, 1:volume_size, 1:volume_size);
% 转换为物理坐标 (以体积中心为原点)
x = (x - volume_size/2) * voxel_size;
y = (y - volume_size/2) * voxel_size;
z = (z - volume_size/2) * voxel_size;
% 旋转坐标系统以匹配当前角度
theta = deg2rad(angle);
rot_x = x * cos(theta) - y * sin(theta);
rot_y = x * sin(theta) + y * cos(theta);
rot_z = z; % Z轴不变
% 计算探测器上的位置
u = (source_to_detector * rot_x) ./ (source_to_object + rot_y);
% 转换为探测器像素索引
detector_coords = linspace(-detector_length/2, detector_length/2, length(projection));
pixel_indices = interp1(detector_coords, 1:length(projection), u, 'linear', 'extrap');
% 确保索引在有效范围内
pixel_indices = max(1, min(length(projection), pixel_indices));
% 插值投影值
proj_values = interp1(1:length(projection), projection, pixel_indices, 'linear', 0);
% 添加到体积中 (考虑几何权重)
weight = source_to_detector^2 ./ (source_to_object + rot_y).^2;
volume = volume + proj_values .* weight;
end
function recon_volume = sart_reconstruct_3d(sinogram, angles, volume_size, ...
source_to_detector, source_to_object, ...
detector_pixel_size, voxel_size, num_iterations)
% 三维同步代数重建技术 (SART)
num_angles = length(angles);
recon_volume = zeros(volume_size, volume_size, volume_size);
% 预处理正弦图
sinogram = max(sinogram, 0); % 确保非负
% 迭代重建
for iter = 1:num_iterations
fprintf('SART迭代 %d/%d\n', iter, num_iterations);
% 对每个角度进行更新
for i = 1:num_angles
angle = angles(i);
% 计算当前角度的正向投影
proj_estimate = forward_project_3d_single(recon_volume, angle, ...
detector_size, source_to_detector, ...
source_to_object, detector_pixel_size, ...
voxel_size);
% 计算投影误差
proj_error = sinogram(i, :) - proj_estimate;
% 反投影误差到体积空间
error_volume = backproject_3d_single(zeros(size(recon_volume)), proj_error, angle, ...
volume_size, voxel_size, ...
source_to_detector, source_to_object, ...
detector_pixel_size);
% 计算权重体积 (用于归一化)
weight_volume = backproject_3d_single(zeros(size(recon_volume)), ones(size(proj_error)), angle, ...
volume_size, voxel_size, ...
source_to_detector, source_to_object, ...
detector_pixel_size);
% 避免除以零
weight_volume(weight_volume == 0) = 1;
% 更新重建体积
recon_volume = recon_volume + error_volume ./ weight_volume;
% 施加非负约束
recon_volume = max(recon_volume, 0);
end
end
end
function projection = forward_project_3d_single(volume, angle, detector_size, ...
source_to_detector, source_to_object, ...
detector_pixel_size, voxel_size)
% 单角度三维正向投影
% 计算几何参数
magnification = source_to_detector / source_to_object;
detector_length = detector_size * detector_pixel_size;
% 旋转体积
rotated_volume = imrotate3(volume, angle, [0 0 1], 'crop', 'linear');
% 计算投影 (沿X轴积分)
projection = squeeze(sum(rotated_volume, 1));
% 考虑几何放大
projection = imresize(projection, [detector_size, detector_size] * magnification);
% 提取中心行作为投影
center_row = round(size(projection, 1)/2);
projection = projection(center_row, :);
end
function volume = backproject_3d_single(volume, projection, angle, volume_size, voxel_size, ...
source_to_detector, source_to_object, detector_pixel_size)
% 单角度三维反投影
% 计算几何参数
magnification = source_to_detector / source_to_object;
detector_length = detector_size * detector_pixel_size;
% 创建体积坐标网格
[x, y, z] = meshgrid(1:volume_size, 1:volume_size, 1:volume_size);
% 转换为物理坐标 (以体积中心为原点)
x = (x - volume_size/2) * voxel_size;
y = (y - volume_size/2) * voxel_size;
z = (z - volume_size/2) * voxel_size;
% 旋转坐标系统以匹配当前角度
theta = deg2rad(angle);
rot_x = x * cos(theta) - y * sin(theta);
rot_y = x * sin(theta) + y * cos(theta);
rot_z = z; % Z轴不变
% 计算探测器上的位置
u = (source_to_detector * rot_x) ./ (source_to_object + rot_y);
% 转换为探测器像素索引
detector_coords = linspace(-detector_length/2, detector_length/2, length(projection));
pixel_indices = interp1(detector_coords, 1:length(projection), u, 'linear', 'extrap');
% 确保索引在有效范围内
pixel_indices = max(1, min(length(projection), pixel_indices));
% 插值投影值
proj_values = interp1(1:length(projection), projection, pixel_indices, 'linear', 0);
% 添加到体积中 (考虑几何权重)
weight = source_to_detector^2 ./ (source_to_object + rot_y).^2;
volume = volume + proj_values .* weight;
end
function rmse = compute_rmse(original, reconstructed)
% 计算均方根误差
diff = original - reconstructed;
rmse = sqrt(mean(diff(:).^2));
end
function ssim_val = compute_ssim_3d(original, reconstructed)
% 计算三维结构相似性指数
% 简化版本:计算所有切片的平均SSIM
num_slices = size(original, 3);
ssim_vals = zeros(1, num_slices);
for i = 1:num_slices
ssim_vals(i) = ssim(squeeze(original(:, :, i)), squeeze(reconstructed(:, :, i)));
end
ssim_val = mean(ssim_vals);
end
算法说明
这个实现包含了两种主要的CT重建算法:
1. 滤波反投影 (FBP) 算法
- 原理:对每个角度的投影数据进行滤波,然后反投影到三维空间
- 优点:计算速度快,适用于实时成像
- 缺点:对噪声敏感,需要完整的投影数据
2. 同步代数重建技术 (SART)
- 原理:迭代算法,通过多次正向和反向投影逐步优化重建结果
- 优点:对噪声和不完全数据更鲁棒,重建质量更高
- 缺点:计算量大,需要多次迭代
关键组件
- 三维模体生成:创建三维Shepp-Logan模体作为测试数据
- 正向投影:模拟CT扫描过程,生成投影数据
- 噪声添加:模拟真实CT数据中的噪声
- 滤波反投影:实现FBP重建算法
- 迭代重建:实现SART算法
- 质量评估:计算RMSE和SSIM评估重建质量
参考代码 三维CT图像重建算法 www.youwenfan.com/contentcsl/63932.html
使用说明
- 代码首先设置CT扫描和重建参数
- 生成三维Shepp-Logan模体作为测试数据
- 模拟CT扫描过程,生成投影数据并添加噪声
- 使用FBP和SART算法进行三维重建
- 评估并比较两种算法的重建质量
扩展功能
这个实现可以进一步扩展:
- 更多重建算法:添加OSEM、TV正则化等高级算法
- GPU加速:使用MATLAB的GPU计算功能加速重建过程
- 实际数据接口:添加DICOM格式数据读写功能
- 高级滤波:添加更先进的噪声滤波和伪影减少技术
- 并行计算:使用并行计算工具箱加速迭代重建