三维CT图像重建算法

三维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)

  • 原理:迭代算法,通过多次正向和反向投影逐步优化重建结果
  • 优点:对噪声和不完全数据更鲁棒,重建质量更高
  • 缺点:计算量大,需要多次迭代

关键组件

  1. 三维模体生成:创建三维Shepp-Logan模体作为测试数据
  2. 正向投影:模拟CT扫描过程,生成投影数据
  3. 噪声添加:模拟真实CT数据中的噪声
  4. 滤波反投影:实现FBP重建算法
  5. 迭代重建:实现SART算法
  6. 质量评估:计算RMSE和SSIM评估重建质量

参考代码 三维CT图像重建算法 www.youwenfan.com/contentcsl/63932.html

使用说明

  1. 代码首先设置CT扫描和重建参数
  2. 生成三维Shepp-Logan模体作为测试数据
  3. 模拟CT扫描过程,生成投影数据并添加噪声
  4. 使用FBP和SART算法进行三维重建
  5. 评估并比较两种算法的重建质量

扩展功能

这个实现可以进一步扩展:

  1. 更多重建算法:添加OSEM、TV正则化等高级算法
  2. GPU加速:使用MATLAB的GPU计算功能加速重建过程
  3. 实际数据接口:添加DICOM格式数据读写功能
  4. 高级滤波:添加更先进的噪声滤波和伪影减少技术
  5. 并行计算:使用并行计算工具箱加速迭代重建
相关推荐
她说人狗殊途1 小时前
时间复杂度(按增长速度从低到高排序)包括以下几类,用于描述算法执行时间随输入规模 n 增长的变化趋势:
数据结构·算法·排序算法
计科土狗1 小时前
算法基础入门第一章
c++·算法
与己斗其乐无穷1 小时前
算法(二)滑动窗口
算法
Ghost-Face1 小时前
恭喜自己,挑战成功!
算法
Miraitowa_cheems1 小时前
LeetCode算法日记 - Day 102: 不相交的线
数据结构·算法·leetcode·深度优先·动态规划
ByteX1 小时前
算法练习-成功之后不许掉队
算法
蒙奇D索大1 小时前
【算法】 递归实战应用:从暴力迭代到快速幂的优化之路
笔记·考研·算法·改行学it
Miraitowa_cheems1 小时前
LeetCode算法日记 - Day 101: 最长公共子序列
数据结构·算法·leetcode·深度优先·动态规划
DuHz2 小时前
基于信号分解的FMCW雷达相互干扰抑制——论文阅读
论文阅读·算法·汽车·信息与通信·毫米波雷达