从nifti标题中很容易得到仿射矩阵。但是在DICOM标题中有很多条目,但我不清楚哪些条目描述了哪个参数转换到哪个新空间。
我发现tutorial非常详细,但我找不到他们所引用的条目。此外,该教程是为Python而不是Matlab编写的。它列出了这些标题条目:
Entries needed:
Image Position (0020,0032)
Image Orientation (0020,0037)
Pixel Spacing (0028,0030)
如果我使用 dicominfo() 加载标题,我就无法找到这些内容。也许它们是供应商特定的,或者它们可能嵌套在结构中的某个地方。另外,它们引用的Pixel Spacing包含两个值,因此我认为他们的教程仅适用于单个切片转换。将需要更多关于切片厚度和切片间隙的标头条目。计算z坐标的正确变换也不容易。
是否有人知道如何找到这些条目或如何使用DICOM标题中的其他信息将图像坐标转换为患者坐标?我使用Matlab。
答案 0 :(得分:9)
好的,所以它们嵌套在可能是结构的特定于供应商的条目中。当在Matlab中加载时,嵌套的名称是 inf.PerFrameFunctionalGroupsSequence.Item_X。 ,然后是framenumber,然后是一些更直接/自我解释的嵌套,所以我不需要在这里添加它。但是在那里搜索你需要的条目。切片间距称为 SpacingBetweenSlices (或单切片情况下的切片厚度),像素间距称为 PixelSpacing 然后有 ImagePositionPatient 用于翻译, ImageOrientationPatient 用于旋转。下面是我按照下面的nipy链接中的步骤编写的代码。
您可以在旋转矩阵中加载direction cosines以对齐基矢量,然后在矩阵中加载像素间距和切片间距以缩放基矢量,并加载图像位置以平移基矢量新的坐标系。找到z方向的直接余弦需要一些计算,因为dicom显然是为2d图像设计的。在单切片情况下,z方向余弦是与x和y方向余弦(两者之间的叉积)正交的单位向量,并且在多切片情况下,您可以根据间隙之间的平移中的所有差异来计算它。在此之后你仍然想要apply the transformation,这也不是直接的直接。
%load the header
inf = dicominfo(filename, 'dictionary', yourvendorspecificdictfilehere);
nSl = double(inf.MRSeriesNrOfSlices);
nY = double(inf.Height);
nX = double(inf.Width);
T1 = double(inf.PerFrameFunctionalGroupsSequence.Item_1.PlanePositionSequence.Item_1.ImagePositionPatient);
%load pixel spacing / scaling / resolution
RowColSpacing = double(inf.PerFrameFunctionalGroupsSequence.Item_1.PixelMeasuresSequence.Item_1.PixelSpacing);
%of inf.PerFrameFunctionalGroupsSequence.Item_1.PrivatePerFrameSq.Item_1.Pixel_Spacing;
dx = double(RowColSpacing(1));
dX = [1; 1; 1].*dx;%cols
dy = double(RowColSpacing(2));
dY = [1; 1; 1].*dy;%rows
dz = double(inf.SpacingBetweenSlices);%inf.PerFrameFunctionalGroupsSequence.Item_1.PrivatePerFrameSq.Item_1.SliceThickness; %thickness of spacing?
dZ = [1; 1; 1].*dz;
%directional cosines per basis vector
dircosXY = double(inf.PerFrameFunctionalGroupsSequence.Item_1.PlaneOrientationSequence.Item_1.ImageOrientationPatient);
dircosX = dircosXY(1:3);
dircosY = dircosXY(4:6);
if nSl == 1;
dircosZ = cross(dircosX,dircosY);%orthogonal to other two direction cosines!
else
N = nSl;%double(inf.NumberOfFrames);
TN = double(-eval(['inf.PerFrameFunctionalGroupsSequence.Item_',sprintf('%d', N),'.PlanePositionSequence.Item_1.ImagePositionPatient']));
dircosZ = ((T1-TN)./nSl)./dZ;
end
%all dircos together
dimensionmixing = [dircosX dircosY dircosZ];
%all spacing together
dimensionscaling = [dX dY dZ];
%mixing and spacing of dimensions together
R = dimensionmixing.*dimensionscaling;%maps from image basis to patientbasis
%offset and R together
A = [[R T1];[0 0 0 1]];
%you probably want to switch X and Y
%(depending on how you load your dicom into a matlab array)
Aold = A;
A(:,1) = Aold(:,2);
A(:,2) = Aold(:,1);
这导致了这个仿射公式:
基本上我遵循了this教程。最大的困难是获得Z方向和翻译正确。找到识别和转换正确的条目对我来说并不简单。我确实认为我的答案在该教程中添加了一些内容,因为很难找到它们所引用的条目,现在我写了一些Matlab代码从DICOM标题中获取仿射矩阵。在使用找到的仿射矩阵之前,您可能还需要找到所有帧的Z坐标,如果您的数据集具有四个以上的维度(dicomread将所有更高维度放在one big fourth dimension中),那么这可能并不简单
CNC中 修正了Z方向和转换的转换