计算世界坐标涉及到的图像属性有:
orientation
spacing
origin
世界坐标计算:
[
P
x
P
y
P
z
1
]
=
[
X
x
Δ
i
Y
x
Δ
j
Z
x
Δ
k
S
x
P
y
Δ
i
Y
y
Δ
j
Z
y
Δ
k
S
y
P
z
Δ
i
Y
z
Δ
j
Z
z
Δ
k
S
z
0
0
0
1
]
[
i
j
k
1
]
=
M
[
i
j
k
1
]
\left[ \begin{matrix} P_x \\ P_y \\ P_z \\ 1 \end{matrix} \right] = \left[ \begin{matrix} X_x \Delta_i&Y_x\Delta_j&Z_x\Delta_k &S_x \\ P_y \Delta_i&Y_y\Delta_j&Z_y\Delta_k&S_y\\ P_z\Delta_i&Y_z\Delta_j&Z_z\Delta_k&S_z \\ 0&0&0&1 \end{matrix} \right]\left[ \begin{matrix} i \\ j \\ k\\ 1 \end{matrix} \right] =M\left[ \begin{matrix} i \\ j \\ k \\ 1 \end{matrix} \right]
⎣⎢⎢⎡PxPyPz1⎦⎥⎥⎤=⎣⎢⎢⎡XxΔiPyΔiPzΔi0YxΔjYyΔjYzΔj0ZxΔkZyΔkZzΔk0SxSySz1⎦⎥⎥⎤⎣⎢⎢⎡ijk1⎦⎥⎥⎤=M⎣⎢⎢⎡ijk1⎦⎥⎥⎤
图像坐标计算:
[
i
j
k
1
]
=
M
−
1
⋅
[
P
x
P
y
P
z
1
]
\left[ \begin{matrix} i \\ j \\ k \\ 1 \end{matrix} \right] = M^{-1}\cdot \left[ \begin{matrix} P_x \\ P_y \\ P_z \\ 1 \end{matrix} \right]
⎣⎢⎢⎡ijk1⎦⎥⎥⎤=M−1⋅⎣⎢⎢⎡PxPyPz1⎦⎥⎥⎤
/* voxel index to point world position */
void IJK2WP(double* origin,
double* spacing,
double* orientation,
int* ijk, double* wp)
{
// |x| | x1*spx y1*spy z1*spz dx| |i|
// |y| = | x2*spx y2*spy z2*spz dy| * |j|
// |z| | x3*spx y3*spy z3*spz dz| |k|
// |1| | 0 0 0 1| |1|
double orientation_z[3];
vtkMath::Cross(orientation, orientation + 3, orientation_z);
vtkMath::Normalize(orientation_z);
auto matrix = vtkSmartPointer<vtkMatrix4x4>::New();
matrix->Identity();
for (int i = 0; i < 3; i++)
{
matrix->SetElement(i, 0, orientation[i] * spacing[0]);
matrix->SetElement(i, 1, orientation[i + 3] * spacing[1]);
matrix->SetElement(i, 2, orientation_z[i] * spacing[2]);
matrix->SetElement(i, 3, origin[i]);
}
double index[]{ ijk[0],ijk[1] ,ijk[2] ,1 };
double* temp = matrix->MultiplyDoublePoint(index);
wp[0] = temp[0];
wp[1] = temp[1];
wp[2] = temp[2];
}
/* point world position to voxel index */
void WP2IJK(double* origin,
double* spacing,
double* orientation,
double* wp, int* ijk)
{
double orientation_z[3];
vtkMath::Cross(orientation, orientation + 3, orientation_z);
vtkMath::Normalize(orientation_z);
auto matrix = vtkSmartPointer<vtkMatrix4x4>::New();
matrix->Identity();
for (int i = 0; i < 3; i++)
{
matrix->SetElement(i, 0, orientation[i] * spacing[0]);
matrix->SetElement(i, 1, orientation[i + 3] * spacing[1]);
matrix->SetElement(i, 2, orientation_z[i] * spacing[2]);
matrix->SetElement(i, 3, origin[i]);
}
auto invertMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
vtkMatrix4x4::Invert(matrix, invertMatrix);
double wp4[]{ wp[0],wp[1],wp[2],1 };
auto temp = invertMatrix->MultiplyDoublePoint(wp4);
ijk[0] = temp[0];
ijk[1] = temp[1];
ijk[2] = temp[2];
}
参考:医学图像坐标变换