如何计算体素大小?
How to calculate a Voxel size?
提供来自 DICOM header 的以下信息,如何计算体素大小的第三个值?我假设前两个值是 0.515625 和 0.515625。
BitsAllocated: "16"
BitsStored: "12"
Columns: 512
HighBit: "11"
ImageOrientation: "1[=10=][=10=][=10=]\-1[=10=]"
ImagePosition: "-144\-34.72422415.599976"
ImageType: "ORIGINAL\PRIMARY\AXIAL\HELIX"
InstanceNumber: "456"
Modality: "CT"
PhotometricInterpretation: "MONOCHROME2"
PixelRepresentation: "0"
PixelSpacing: "0.515625[=10=].515625"
RescaleIntercept: "1"
Rows: 512
SamplesPerPixel: "1"
SeriesDescription: "CERVEAU SANS IV"
SeriesNumber: "3"
SliceThickness: "1.50"
WindowCenter: "00040[=10=]040"
WindowWidth: "00120[=10=]120"
imagesFormat: "jpg"
modality: "CT"
name: "soft tissue"
nodeId: "557621"
pixelHeight: "0.515625"
pixelWidth: "0.515625"
注意:我收到一个 JPEG 图像堆栈,而不是 DICOM,它附带一个文件,其中包含我在上面发布的值。如果需要,我可以返回并在文件中索取更多信息。
PixelSpacing (0028,0030) 给出了图像中列和行方向的两种尺寸。您要求的第三个值是切片厚度 (0018,0050)。
在某些重建(MIP 或类似)的情况下,切片厚度的值可能高于两个相邻图像的距离。
因此,如果您将此单个图像用作自己的图像,则必须使用切片厚度。但是如果你有一堆图像并且想要做 3d 渲染或重建或类似的,那么我建议通过两个相邻图像的距离来计算第三个体素大小。
参考资料:
https://dicom.innolitics.com/ciods/ct-image/image-plane
http://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.34.12.html
仅给定一个切片的标签,您必须使用 SliceThickness
作为第三维,但我不建议这样做,因为这不能保证给出切片之间的距离。有提供此信息的标签 SpacingBetweenSlices
,但您的情况似乎不存在。
最好的方法是利用相邻切片之间ImagePositionPatient
的差异。为此,您当然还需要下一个切片的标签。附带说明:在您的列表中,ImageOrientation
和 ImagePosition
应该更好地阅读 ImageOrientationPatient
和 ImagePositionPatient
,因为 ImageOrientation
和 ImagePosition
是其他标签(不存在于 CT 图像中)。
ImagePositionPatient
给出切片左上角在 DICOM 患者坐标中的位置,要计算距离,您必须考虑该坐标系中切片的方向。这是由 ImageOrientationPatient
给出的,它包含 DICOM 坐标中切片的归一化行和列方向余弦向量。您可以在 DICOM standard.
中阅读该内容
方向矩阵的前两个分量由ImageOrientationPatient
提供(例如第一个和第二个三个数),第三个分量可以通过这两个分量的叉积来计算。
所以,在伪代码中,这看起来像这样:
orient1 = vector(ImageOrientationPatient[0], ImageOrientationPatient[1], ImageOrientationPatient[2])
orient2 = vector(ImageOrientationPatient[3], ImageOrientationPatient[4], ImageOrientationPatient[5])
orient3 = orient1 x orient2 // cross product
orient_matrix = matrix(orient1, orient2, orient3)
pos1 = vector(ImagePositionPatient[0], ImagePositionPatient[1], ImagePositionPatient[2]) // from current slice
pos2 = vector(ImagePositionPatient[0], ImagePositionPatient[1], ImagePositionPatient[2]) // from adjacent slice
diff_pos = pos2 - pos1
image_pos = orient_matrix o diff_pos / length(orient3) // normalized dot product
voxel_z = image_pos.z
更新:正如@gofal 所指出的,第一个版本是不正确的。我还包括规范化(例如 length(orient3)
删除),但严格来说这些值应该已经规范化了。
提供来自 DICOM header 的以下信息,如何计算体素大小的第三个值?我假设前两个值是 0.515625 和 0.515625。
BitsAllocated: "16"
BitsStored: "12"
Columns: 512
HighBit: "11"
ImageOrientation: "1[=10=][=10=][=10=]\-1[=10=]"
ImagePosition: "-144\-34.72422415.599976"
ImageType: "ORIGINAL\PRIMARY\AXIAL\HELIX"
InstanceNumber: "456"
Modality: "CT"
PhotometricInterpretation: "MONOCHROME2"
PixelRepresentation: "0"
PixelSpacing: "0.515625[=10=].515625"
RescaleIntercept: "1"
Rows: 512
SamplesPerPixel: "1"
SeriesDescription: "CERVEAU SANS IV"
SeriesNumber: "3"
SliceThickness: "1.50"
WindowCenter: "00040[=10=]040"
WindowWidth: "00120[=10=]120"
imagesFormat: "jpg"
modality: "CT"
name: "soft tissue"
nodeId: "557621"
pixelHeight: "0.515625"
pixelWidth: "0.515625"
注意:我收到一个 JPEG 图像堆栈,而不是 DICOM,它附带一个文件,其中包含我在上面发布的值。如果需要,我可以返回并在文件中索取更多信息。
PixelSpacing (0028,0030) 给出了图像中列和行方向的两种尺寸。您要求的第三个值是切片厚度 (0018,0050)。
在某些重建(MIP 或类似)的情况下,切片厚度的值可能高于两个相邻图像的距离。 因此,如果您将此单个图像用作自己的图像,则必须使用切片厚度。但是如果你有一堆图像并且想要做 3d 渲染或重建或类似的,那么我建议通过两个相邻图像的距离来计算第三个体素大小。
参考资料: https://dicom.innolitics.com/ciods/ct-image/image-plane http://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.34.12.html
仅给定一个切片的标签,您必须使用 SliceThickness
作为第三维,但我不建议这样做,因为这不能保证给出切片之间的距离。有提供此信息的标签 SpacingBetweenSlices
,但您的情况似乎不存在。
最好的方法是利用相邻切片之间ImagePositionPatient
的差异。为此,您当然还需要下一个切片的标签。附带说明:在您的列表中,ImageOrientation
和 ImagePosition
应该更好地阅读 ImageOrientationPatient
和 ImagePositionPatient
,因为 ImageOrientation
和 ImagePosition
是其他标签(不存在于 CT 图像中)。
ImagePositionPatient
给出切片左上角在 DICOM 患者坐标中的位置,要计算距离,您必须考虑该坐标系中切片的方向。这是由 ImageOrientationPatient
给出的,它包含 DICOM 坐标中切片的归一化行和列方向余弦向量。您可以在 DICOM standard.
方向矩阵的前两个分量由ImageOrientationPatient
提供(例如第一个和第二个三个数),第三个分量可以通过这两个分量的叉积来计算。
所以,在伪代码中,这看起来像这样:
orient1 = vector(ImageOrientationPatient[0], ImageOrientationPatient[1], ImageOrientationPatient[2])
orient2 = vector(ImageOrientationPatient[3], ImageOrientationPatient[4], ImageOrientationPatient[5])
orient3 = orient1 x orient2 // cross product
orient_matrix = matrix(orient1, orient2, orient3)
pos1 = vector(ImagePositionPatient[0], ImagePositionPatient[1], ImagePositionPatient[2]) // from current slice
pos2 = vector(ImagePositionPatient[0], ImagePositionPatient[1], ImagePositionPatient[2]) // from adjacent slice
diff_pos = pos2 - pos1
image_pos = orient_matrix o diff_pos / length(orient3) // normalized dot product
voxel_z = image_pos.z
更新:正如@gofal 所指出的,第一个版本是不正确的。我还包括规范化(例如 length(orient3)
删除),但严格来说这些值应该已经规范化了。