在Matlab中将DICOM仿射矩阵从图像空间转换为患者空间 [英] DICOM affine matrix transformation from image space to patient space in Matlab

查看:248
本文介绍了在Matlab中将DICOM仿射矩阵从图像空间转换为患者空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过nifti头很容易获得仿射矩阵.但是,在DICOM标头中有很多条目,但是我不清楚哪些条目描述了将哪个参数转换为哪个新空间.

From the nifti header its easy to get the affine matrix. However in the DICOM header there are lots of entries, but its unclear to me which entries describe the transformation of which parameter to which new space.

我找到了教程,该教程非常详细,但我找不到条目他们指的是.另外,该教程是为Python而不是Matlab编写的.它列出了这些标题条目:

I have found a tutorial which is quite detailed, but I cant find the entries they refer to. Also, that tutorial is written for Python, not Matlab. It lists these header entries:

Entries needed:
Image Position (0020,0032)
Image Orientation (0020,0037)
Pixel Spacing (0028,0030)

如果使用 dicominfo() 加载标头,则找不到这些内容.也许它们是特定于供应商的,或者它们嵌套在结构中的某个位置.他们所指的像素间距也由两个值组成,所以我认为他们的教程仅适用于单切片转换.将需要更多有关切片厚度和切片间隙的标头条目.计算z坐标的正确变换也不容易.

I cant find these if I load the header with dicominfo() . Maybe they are vendor specific or maybe they are nested away somewhere in the struct. Also the Pixel Spacing they refer to consists of two values, so I think their tutorial will only work for single slice transformations. More header entries about slice thickness and slicegap would be needed. Its also not easy to calculate the correct transformation for the z coordinates.

有人知道如何找到这些条目,或者如何将图像坐标与来自DICOM标头的其他信息转换为患者坐标吗?我使用Matlab.

Does anybody know how to find these entries or how to transform image coordinates to patient coordinates with other information from a DICOM header? I use Matlab.

推荐答案

好,因此它们嵌套在可能是该结构的供应商特定条目中.当在Matlab中加载时,嵌套的名称为 inf.PerFrameFunctionalGroupsSequence.Item_X. ,然后是帧号,然后是一些更直接/易于解释的嵌套,所以我不需要在这里添加它.但是在那里搜索您需要的条目.切片间距称为 SpacingBetweenSlices (或在单个切片情况下为切片厚度),像素间距称为 PixelSpacing >,然后是 ImagePositionPatient (用于翻译),以及 ImageOrientationPatient (用于旋转).下面是我按照下面的nipy链接中的步骤进行操作时编写的代码.

Ok so they were nested away in what might be a vendor specific entry of the struct. When loaded in Matlab, the name of the nest was inf.PerFrameFunctionalGroupsSequence.Item_X., then the framenumber, and then some more nesting which was more straightforward/self explanatory so I wont need to add it here. But search for the entries you need there. The slice spacing is called SpacingBetweenSlices (or slice thickness in the single slice case), the pixel spacing is called PixelSpacing and then there are ImagePositionPatient for the translation and ImageOrientationPatient for the rotation. Below is the code I wrote when following the steps from the nipy link below.

会发生什么情况,您将方向余弦加载到旋转矩阵中以对齐基本向量然后将像素间距和切片间距加载到矩阵中以缩放基本矢量,并加载图像位置以平移新的坐标系.在z方向上找到Directoin余弦需要进行一些计算,因为dicom显然是为2D图像设计的.在单切片情况下,z方向余弦是与x和y方向余弦(二者之间的叉积)正交的单位矢量,在多切片情况下,您可以根据slcies之间平移的所有差异来计算它.之后,您仍然想应用转换也不是那么直接.

What happens is you load the direction cosines in a rotation matrix to align the basis vectors and you load the the pixel spacing and slice spacing in a matrix to scale the basis vectors and you load the image position to translate the new coordinate system. Finding the directoin cosines for the z direction takes some calculations because dicom apparently was designed for 2d images. In the single slice case the z direction cosines is the unit vector orthogonal to the x and y direction cosines (the cross product between the two) and in the multi slice case you can calculate it from all the differences in the translations between the slcies. After this you still want to apply the transformation which is also not immediately straightforward.

%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 results in this affine formula:

所以基本上我遵循了教程.最大的困难是使Z方向和平移正确.对我来说,找到识别并转换正确条目的方法也不是一件容易的事.我确实认为我的答案为该教程增添了一些内容,因为很难找到它们所引用的条目,现在我编写了一些Matlab代码,从DICOM标头中获取仿射矩阵.在使用找到的仿射矩阵之前,您可能还需要找到所有帧的Z坐标,如果您的数据集具有四个以上的维,则这可能并不容易(dicomread将所有更高的维放在第四个大维度)

So basically I followed this tutorial. What was the biggest struggle was getting the Z direction and the translation correct. Also finding identifying and converting the correct entries was not straightforward for me. I do think my answer adds something to that tutorial though, because it was pretty hard to find the entries they refer to and now I wrote some Matlab code getting the affine matrix from a DICOM header. Before using the found affine matrix you also might need to find the Z coordinates for all of your frames, which might not be trivial if your dataset has more than four dimensions (dicomread puts all higher dimensions in one big fourth dimension)

-编辑- 校正了Z方向和变换的平移

-Edit- Corrected Z direction and translation of the transformation

这篇关于在Matlab中将DICOM仿射矩阵从图像空间转换为患者空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆