(MATLAB)DICOM序列的读取与数字体模重建

DICOM序列的读取与数字体模重建


by HPC_ZY

之前写了一些关于医学影像三维重建(可视化)的文章,不少网友对原始数据那一部分提问。所以写此文,分享DICOM序列重建三维数字体模的方法。


DICOM格式

DICOM具体格式与解析方法本文不讲,感兴趣可参考DICOM官网大佬博客


DICOM序列读取

DICOM数据的读取与处理可参考:MATLAB医学DICOM影像读取与预处理
通常情况下DICOM文件的命名与其序列编号顺序一致,但不排除例外(我就遇到过命名与顺序完全不同的数据),如下表

情况举例(假如一个有五个文件的序列,括号内为序列号)
顺序正确、序列完整01.DCM(1)02.DCM(2)03.DCM(3)04.DCM(4)05.DCM(5)
顺序错误、序列完整01.DCM(3)02.DCM(2)03.DCM(1)04.DCM(5)05.DCM(4)
顺序正确、序列缺失01.DCM(1)02.DCM(2)03.DCM(4)04.DCM(6)05.DCM(7)
  1. 顺序数据的处理
    初始化三维矩阵,利用for循环读取,存入每一层即可。如下:
%% 情况一:顺序正确、序列完整
N = 5;
DCM = zeros(512,512,N);
% 读取
for n = 1:N
filename = ['0',num2str(n),'.DCM']% 此处使用自己的文件名
DCM(:,:,n) = dicomread(filename ); 
end
  1. 乱序数据的处理
    在情况一的基础上,读取文件(0x0020,0x1041)Slice Location数据元中真实空间位置,进行重排序。如下:
%% 情况二:顺序错误、序列完整
N = 5;
DCM = zeros(512,512,N);
IDX = zeros(1,N);

% 读取
for n = 1:N
filename = ['0',num2str(n),'.DCM']% 此处使用自己的文件名
DCM(:,:,n) = dicomread(filename); 
info = dicominfo(filename);
IDX(n) = info.SliceLocation;
end

% 重排序
[~,idx] = sord(IDX);
DCM = DCM(:,:,idx);
  1. 缺失数据的处理
    (一种解决方案)可在情况二的基础上,利用插值算法补齐缺失。(不举例)

数字体模重建

其本质就是利用插值算法,将分辨率更低的方向进行重采样。
注:这一步并非必要,仅仅作为图像处理时有上节的DCM就足够。如果后续算法有实际的物理意义,或希望每个体素xyz方向尺度一致,才需要进行一下处理。

此方法代码示例,

% 转为double才能interp
DCM = double(DCM); % 用前面方法读入的 DCM

% info 是上述 info = dicominfo(filename)获取的
ps = info.PixelSpacing; % 我的数据是0.5mm;
sps = info.SpacingBetweenSlices; % 我的数据是5mm;

% 原始网格
[R,C,D] = size(DCM);
[X1,Y1,Z1] = meshgrid(1:R,1:C,1:D);

% 采样网格
dz = ps/sps;
[X2,Y2,Z2] = meshgrid(1:R,1:C,1:dz:D);

% 插值
newDCM = interp3(X1,Y1,Z1,DCM,X2,Y2,Z2);

上述重采样方法虽然简单快速,但其结果不具备物理意义。所以我们通常使用以下重采样方法:

在这里插入图片描述
m o d e l ( i , j , k ) = model(i,j,k) = model(i,j,k)=
( 1 − a ) ⋅ ( 1 − b ) ⋅ ( 1 − c ) ⋅ d c m ( x , y , z ) + ( 1 − a ) ⋅ ( 1 − b ) ⋅ c ⋅ d c m ( x , y , z + 1 ) (1-a)·(1-b)·(1-c)·dcm(x,y,z) + (1-a)·(1-b)·c·dcm(x,y,z+1) (1a)(1b)(1c)dcm(x,y,z)+(1a)(1b)cdcm(x,y,z+1) + a ⋅ ( 1 − b ) ⋅ ( 1 − c ) ⋅ d c m ( x + 1 , y , z ) + a ⋅ ( 1 − b ) ⋅ c ⋅ d c m ( x + 1 , y , z + 1 ) +a·(1-b)·(1-c)·dcm(x+1,y,z) + a·(1-b)·c·dcm(x+1,y,z+1) +a(1b)(1c)dcm(x+1,y,z)+a(1b)cdcm(x+1,y,z+1) + ( 1 − a ) ⋅ b ⋅ ( 1 − c ) ⋅ d c m ( x , y + 1 , z ) + ( 1 − a ) ⋅ b ⋅ c ⋅ d c m ( x , y + 1 , z + 1 ) +(1-a)·b·(1-c)·dcm(x,y+1,z) + (1-a)·b·c·dcm(x,y+1,z+1) +(1a)b(1c)dcm(x,y+1,z)+(1a)bcdcm(x,y+1,z+1) + a ⋅ b ⋅ ( 1 − c ) ⋅ d c m ( x + 1 , y + 1 , z ) + a ⋅ b ⋅ c ⋅ d c m ( x + 1 , y + 1 , z + 1 ) +a·b·(1-c)·dcm(x+1,y+1,z) + a·b·c·dcm(x+1,y+1,z+1) +ab(1c)dcm(x+1,y+1,z)+abcdcm(x+1,y+1,z+1)
其中,model为重采样后的CT三维体数据,dcm为原始CT数据。

关于a,b,c,比如model(i,j,k) 的位置在 (5.5, 3.1, 6),那么有:
x = 5, y = 3, z = 6
a = 0.5, b = 0.1, c = 0

例子,一个尺寸为512·512·83的CT序列,扫描间隔为(0.6523, 0.6523, 2.5000)mm,重采样后尺寸为512·512·315。如下图所示,
在这里插入图片描述

% 假设
DCM = double(DCM); % 用前面方法读入的 DCM
scale = 1; % 设置越大,模型越大
info.PixelSpacing = 0.5;
info.SpacingBetweenSlices = 5;

% 原始网格
[R,C,D] = size(DCM);
[X1,Y1,Z1] = meshgrid(1:R,1:C,1:D);

% 采样网格
mR = R*scale;
mC = C*scale;
mD = D*scale*info.SpacingBetweenSlices/info.PixelSpacing;
dx = (R-1)/(mR-1);
dy = (C-1)/(mC-1);
dz = (D-1)/(mD-1);
[X2,Y2,Z2] = meshgrid(1:dx:R,1:dy:C,1:dz:D);

% 插值
newDCM = interp3(X1,Y1,Z1,DCM,X2,Y2,Z2);

其他

由于实验数据为内部资料,不提供测试数据与代码

评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值