我是dicom开发小组的初学者。我需要在dicom图像上创建一个定位器图像线。那么,有什么好主意吗?任何极客。
答案 0 :(得分:13)
大卫布拉班特让你已经朝着正确的方向前进(如果你想与DICOM合作,你一定要阅读并珍惜 dclunie的医学图片常见问题)。让我们看看我是否可以详细说明它并使您更容易实现。
我假设你有一个工具/库来从DICOM文件中提取标签(Offis'DCMTK?)。为了举例说明,我将参考CT扫描(许多切片,即许多图像)和侦察图像,您要在其上显示定位器线。每个DICOM图像,包括您的CT切片和您的侦察,都包含有关它们在空间中的位置的完整信息,在这两个标记中:
Group,Elem VR Value Name of the tag --------------------------------------------------------------------- (0020,0032) DS [-249.51172\-417.51172\-821] # ImagePositionPatient X0 Y0 Z0 (0020,0037) DS [1\0\0\0\1\0] # ImageOrientationPatient A B C D E F
ImagePositionPatient具有以(mm,y,z)表示的第一个传输像素的全局坐标(以左上角像素显示)。我把它们标记为X0,Y0,Z0。 ImageOrientationPatient包含两个向量,三个组件,指定第一行像素的方向余弦和图像的第一列像素。理解方向余弦不会受到伤害(参见例如http://mathworld.wolfram.com/DirectionCosine.html),但dclunie建议的方法直接与它们一起工作,所以现在让我们说它们为你提供了图像平面空间的方向。我将它们标记为A-F以使公式更容易。
现在,在dclunie给出的代码中(我相信它的目的是C,但它很简单,它应该像Java,C#,awk,Vala,Octave等一样工作),约定如下:< / p>
scr_ * =指的是图像,即CT切片
dst_ * =指目标图像,即侦察兵
* _ pos_x,* _pos_y,* _pos_z =上面的X0,Y0,Z0
* _ row_dircos_x,* _row_dircos_y,* _row_dircos_z =上面的A,B,C
* _ col_dircos_x,* _col_dircos_y,* _col_dircos_z =上面的D,E,F
设置正确的值后,只需应用以下内容:
dst_nrm_dircos_x = dst_row_dircos_y * dst_col_dircos_z
- dst_row_dircos_z * dst_col_dircos_y;
dst_nrm_dircos_y = dst_row_dircos_z * dst_col_dircos_x
- dst_row_dircos_x * dst_col_dircos_z;
dst_nrm_dircos_z = dst_row_dircos_x * dst_col_dircos_y
- dst_row_dircos_y * dst_col_dircos_x;
src_pos_x -= dst_pos_x;
src_pos_y -= dst_pos_y;
src_pos_z -= dst_pos_z;
dst_pos_x = dst_row_dircos_x * src_pos_x
+ dst_row_dircos_y * src_pos_y
+ dst_row_dircos_z * src_pos_z;
dst_pos_y = dst_col_dircos_x * src_pos_x
+ dst_col_dircos_y * src_pos_y
+ dst_col_dircos_z * src_pos_z;
dst_pos_z = dst_nrm_dircos_x * src_pos_x
+ dst_nrm_dircos_y * src_pos_y
+ dst_nrm_dircos_z * src_pos_z;
或者,如果您有一些花哨的矩阵类,您可以构建此矩阵并将其与您的点坐标相乘。
[ dst_row_dircos_x dst_row_dircos_y dst_row_dircos_z -dst_pos_x ] M = [ dst_col_dircos_x dst_col_dircos_y dst_col_dircos_z -dst_pos_y ] [ dst_nrm_dircos_x dst_nrm_dircos_y dst_nrm_dircos_z -dst_pos_z ] [ 0 0 0 1 ]
就是这样:
Scout_Point(x,y,z,1) = M * CT_Point(x,y,z,1)
所有这一切,我们应该转换为在scout上创建一条线,CT的哪些点?同样对于这个dclunie已经提出了一个通用的解决方案:
“我的方法是投影作为源图像边界框的正方形(即连接切片的TLHC,TRHC,BRHC和BLHC的线条)。”
如果投影CT切片的四个角点,则CT切片垂直于侦察线,而非垂直切片则为梯形线。现在,如果您的CT切片与坐标轴对齐(即ImageOrientationPatient = [1 \ 0 \ 0 \ 0 \ 1 \ 0]),则这四个点是微不足道的。您可以使用行数/列数和沿x / y方向的像素距离计算图像的宽度/高度(以mm为单位),并相应地进行求和。如果你想实现通用案例,那么你需要一点三角函数......或者可能不需要。也许是时候你读了方向余弦的定义,如果你还没有。
我会尽力让你走上正轨。例如。在TRHC上工作,您知道体素在图像平面中的位置:
# Pixel location of the TRHC x_pixel = number_of_columns-1 # Counting from 0 y_pixel = 0 z_pixel = 0 # We're on a plane!
DICOM中的像素距离值是指图像平面,因此您可以简单地将x和y乘以这些值,使其位置以mm为单位,而z为0(像素和mm)。我在谈论这些价值观:
(0028,0011) US 512 # 2, 1 Columns (0028,0010) US 512 # 2, 1 Rows (0028,0030) DS [0.9765625\0.9765625] # 20, 2 PixelSpacing
上面的矩阵M是从全局到图像坐标的一般变换,具有可用的方向余弦。您现在需要的是执行逆作业(图像到全局)和源图像(CT切片)的操作。我会让你去深入挖掘几何书籍,但我认为它应该是这样的(旋转部分是换位的,翻译没有符号变化,当然我们使用src_ *值):
[src_row_dircos_x src_col_dircos_x src_nrm_dircos_x src_pos_x ] M2 = [src_row_dircos_y src_col_dircos_y src_nrm_dircos_y src_pos_y ] [src_row_dircos_z src_col_dircos_z src_nrm_dircos_z src_pos_z ] [0 0 0 1 ]
将CT切片中的点(例如四个角)转换为毫米,然后应用M2将它们置于全局坐标中。然后你可以将它们提供给dclunie报告的程序。在使用之前交叉检查我的数学,例如用于患者诊断! ;-)
希望这有助于理解更好的dclunie方法。干杯