dicomImageReader = vtkDICOMImageReader.New();
dicomImageReader.SetDirectoryName(DicPath);
dicomImageReader.Update();
resliceImageViewers = new vtkResliceImageViewer[SliceNum];
for (int i = 0; i < SliceNum; i++)
{
resliceImageViewers[i] = vtkResliceImageViewer.New();
resliceImageViewers[i].SetInputData(dicomImageReader.GetOutput());
vtkResliceCursorLineRepresentation rep = vtkResliceCursorLineRepresentation.SafeDownCast(resliceImageViewers[i].GetResliceCursorWidget().GetRepresentation());
for (int k = 0; k < 3; k++)
{
rep.GetResliceCursorActor().GetCenterlineProperty(k).SetRepresentationToWireframe();
rep.GetResliceCursorActor().GetCenterlineProperty(k).RenderLinesAsTubesOn();
rep.GetResliceCursorActor().GetCenterlineProperty(k).SetLineWidth(2);
switch (k)
{
case 0:
;
rep.GetResliceCursorActor().GetCenterlineProperty(k).SetColor(0, 0, 255);
break;
case 1:
rep.GetResliceCursorActor().GetCenterlineProperty(k).SetColor(0, 255, 0);
break;
case 2:
rep.GetResliceCursorActor().GetCenterlineProperty(k).SetColor(255, 0, 0);
break;
}
}
switch (i)
{
case 0:
{
resliceImageViewers[i].SetRenderWindow(renderWindowControlAxial.RenderWindow);
resliceImageViewers[i].SetupInteractor(renderWindowControlAxial.RenderWindow.GetInteractor());
rep.GetResliceCursorActor().GetCursorAlgorithm().SetReslicePlaneNormalToZAxis();
resliceImageViewers[i].SetSliceOrientationToXY();
break;
}
case 1:
{
resliceImageViewers[i].SetRenderWindow(renderWindowControlSagittal.RenderWindow);
resliceImageViewers[i].SetupInteractor(renderWindowControlSagittal.RenderWindow.GetInteractor());
rep.GetResliceCursorActor().GetCursorAlgorithm().SetReslicePlaneNormalToXAxis();
resliceImageViewers[i].SetSliceOrientationToYZ();
break;
}
case 2:
{
resliceImageViewers[i].SetRenderWindow(renderWindowControlCoronal.RenderWindow);
resliceImageViewers[i].SetupInteractor(renderWindowControlCoronal.RenderWindow.GetInteractor());
rep.GetResliceCursorActor().GetCursorAlgorithm().SetReslicePlaneNormalToYAxis();
resliceImageViewers[i].SetSliceOrientationToXZ();
break;
}
}
resliceImageViewers[i].SetResliceModeToAxisAligned();
resliceImageViewers[i].SetLookupTable(resliceImageViewers[0].GetLookupTable());
resliceImageViewers[i].SetColorWindow(DefaultWindowLevel[0]);
resliceImageViewers[i].SetColorLevel(DefaultWindowLevel[1]);
resliceImageViewers[i].SetThickMode(0);
resliceImageViewers[i].SetResliceMode(1);
rep.SetManipulationMode(2);
resliceImageViewers[i].SetResliceCursor(resliceImageViewers[0].GetResliceCursor());
//resliceImageViewers[i].GetResliceCursorWidget().SetEnabled(1);
resliceImageViewers[i].GetResliceCursorWidget().SetManageWindowLevel(0);
resliceImageViewers[i].SetSlice(resliceImageViewers[i].GetSliceMax() / 2);
resliceImageViewers[i].GetRenderer().ResetCameraScreenSpace();
resliceImageViewers[i].Render();
resliceImageViewers[i].Reset();
}
自己可以代码翻转吗,用类似opencv之类的
vtk源码写死了一部分东西,修改vtk源码或者加载图像后重新设置视角和平面即可
void vtkResliceCursor::Reset()
{
this->XAxis[0] = 1.0;
this->XAxis[1] = 0.0;
this->XAxis[2] = 0.0;
this->YAxis[0] = 0.0;
this->YAxis[1] = 1.0;
this->YAxis[2] = 0.0;
this->ZAxis[0] = 0.0;
this->ZAxis[1] = 0.0;
this->ZAxis[2] = 1.0;
this->XViewUp[0] = 0.0;
this->XViewUp[1] = 0.0;
this->XViewUp[2] = 1.0;
this->YViewUp[0] = 0.0;
this->YViewUp[1] = 0.0;
this->YViewUp[2] = 1.0;
this->ZViewUp[0] = 0.0;
this->ZViewUp[1] = -1.0;
this->ZViewUp[2] = 0.0;
if (this->GetImage())
{
this->GetImage()->GetCenter(this->Center);
}
else
{
this->Center[0] = 0.0;
this->Center[1] = 0.0;
this->Center[2] = 0.0;
}
for (int i = 0; i < 3; i++)
{
this->GetPlane(i)->SetOrigin(this->Center);
}
this->ReslicePlanes->GetItem(0)->SetNormal(1, 0, 0);
this->ReslicePlanes->GetItem(1)->SetNormal(0, -1, 0);
this->ReslicePlanes->GetItem(2)->SetNormal(0, 0, 1);
this->BuildCursorTopology();
this->BuildCursorGeometry();
this->Modified();
}
void vtkResliceImageViewer::UpdateOrientation()
{
// Set the camera position
vtkCamera* cam = this->Renderer ? this->Renderer->GetActiveCamera() : nullptr;
if (cam)
{
switch (this->SliceOrientation)
{
case vtkImageViewer2::SLICE_ORIENTATION_XY:
cam->SetFocalPoint(0, 0, 0);
cam->SetPosition(0, 0, 1); // -1 if medical ?
cam->SetViewUp(0, 1, 0);
break;
case vtkImageViewer2::SLICE_ORIENTATION_XZ:
cam->SetFocalPoint(0, 0, 0);
cam->SetPosition(0, -1, 0); // 1 if medical ?
cam->SetViewUp(0, 0, 1);
break;
case vtkImageViewer2::SLICE_ORIENTATION_YZ:
cam->SetFocalPoint(0, 0, 0);
cam->SetPosition(1, 0, 0); // -1 if medical ?
cam->SetViewUp(0, 0, 1);
break;
}
}
}
vtkResliceImageViewer实现MPR,斜切模式下显示的图像不再是原始图像,而是通过三维重建得到的图像,所以想要在斜切模式下展示正确图像,只需要修改光标类下的图像视角以及切线平面即可
public static void ResliceCursorReset(this vtkResliceCursor cursor)
{
if (cursor == null) return;
cursor.SetXViewUp(0, 0, -1);
cursor.SetYViewUp(0, 0, -1);
cursor.SetZViewUp(0, 1, 0);
cursor.GetPlane(1).SetNormal(0, 1, 0);
}
想要原始图像正确展示图像,重新设置相加视角和位置即可
public static void CameraReset(this vtkCamera camera,int sliceIndex)
{
if (camera == null) return;
if (sliceIndex == 0) camera.SetViewUp(0, 0, -1);
else if (sliceIndex == 1)
{
camera.SetPosition(0, 1, 0);
camera.SetViewUp(0, 0, -1);
}
}
该回答引用ChatGPT-3.5,仅供参考,不保证完全正确
要解决反向和翻转的问题,可以尝试在创建vtkResliceImageViewer对象之后添加以下代码:
resliceImageViewers[i].SetResliceAxesDirectionCosines(dicomImageReader.GetOutput().GetDirection());
resliceImageViewers[i].SetResliceAxesOrigin(dicomImageReader.GetOutput().GetOrigin());
这将使用DICOM图像的方向余弦和原点信息来设置切面的方向和位置。这样可以确保切面与图像匹配并且不会出现反向或翻转的情况。
在你的代码中,可以将上述代码添加到以下位置:
switch (i)
{
case 0:
{
resliceImageViewers[i].SetRenderWindow(renderWindowControlAxial.RenderWindow);
resliceImageViewers[i].SetupInteractor(renderWindowControlAxial.RenderWindow.GetInteractor());
rep.GetResliceCursorActor().GetCursorAlgorithm().SetReslicePlaneNormalToZAxis();
resliceImageViewers[i].SetSliceOrientationToXY();
break;
}
case 1:
{
resliceImageViewers[i].SetRenderWindow(renderWindowControlSagittal.RenderWindow);
resliceImageViewers[i].SetupInteractor(renderWindowControlSagittal.RenderWindow.GetInteractor());
rep.GetResliceCursorActor().GetCursorAlgorithm().SetReslicePlaneNormalToXAxis();
resliceImageViewers[i].SetSliceOrientationToYZ();
break;
}
case 2:
{
resliceImageViewers[i].SetRenderWindow(renderWindowControlCoronal.RenderWindow);
resliceImageViewers[i].SetupInteractor(renderWindowControlCoronal.RenderWindow.GetInteractor());
rep.GetResliceCursorActor().GetCursorAlgorithm().SetReslicePlaneNormalToYAxis();
resliceImageViewers[i].SetSliceOrientationToXZ();
break;
}
}
// 添加以下代码
resliceImageViewers[i].SetResliceAxesDirectionCosines(dicomImageReader.GetOutput().GetDirection());
resliceImageViewers[i].SetResliceAxesOrigin(dicomImageReader.GetOutput().GetOrigin());
通过这样设置切面的方向和位置,应该能够解决反向和翻转的问题。
该回答引用NewBing,仅供参考,不保证完全正确
根据我从网络上搜索到的信息,ActiViz.Net是一个集成了VTK(可视化工具包)的.NET框架,可以用于在.NET编程语言中使用VTK的强大功能。VTK是一个用于3D图形,数据可视化,数据处理等的面向对象的软件系统。¹
您的代码看起来是使用了vtkResliceImageViewer类来实现MPR功能,这个类可以根据不同的切面方向来显示DICOM图像。²
我注意到您的代码中没有设置切面图像的方向属性,这可能导致图像显示不正确。您可以尝试在每个resliceImageViewer对象上调用SetResliceAxesDirectionCosines方法,传入一个包含三个方向余弦向量的数组,来指定切面图像的方向。³
例如,如果您想让XY切面图像与DICOM图像的方向一致,您可以这样写:
resliceImageViewers[0].SetResliceAxesDirectionCosines(new double[] { 1, 0, 0, 0, 1, 0, 0, 0, 1 });
如果您想让YZ切面图像与DICOM图像的方向一致,您可以这样写:
resliceImageViewers[1].SetResliceAxesDirectionCosines(new double[] { 0, 1, 0, 0, 0, -1, -1, 0, 0 });
如果您想让XZ切面图像与DICOM图像的方向一致,您可以这样写:
resliceImageViewers[2].SetResliceAxesDirectionCosines(new double[] { 1, 0, 0, 0, 0, -1, 0, -1, 0 });
这些方向余弦向量是根据DICOM标准中定义的Image Position和Image Orientation计算得到的。³
源: 与必应的对话, 2023/7/18
(1) ActiViz .NET User's Guide Version 9 - Kitware Europe. https://www.kitware.eu/wp-content/uploads/2021/02/ActiViz.NET_9.0_Users_Guide.pdf.
(2) GitHub - dikubb/Activiz-Demo: MPR Demo using Activiz. https://github.com/dikubb/Activiz-Demo.
(3) How can i determine the ImagePosition of the reconstructed MPR DICOM image?. https://stackoverflow.com/questions/6846761/how-can-i-determine-the-imageposition-of-the-reconstructed-mpr-dicom-image.
(4) undefined. http://www.kitware.com/.
(5) undefined. https://training.kitware.fr/browse.
(6) undefined. https://www.kitware.eu/service/support.
(7) undefined. https://www.kitware.com/what-we-offer/#books.
(8) undefined. http://www.vtk.org/.
(9) undefined. http://www.slicer.org/.
(10) undefined. http://www.paraview.org/.
该回答引用ChatGPT-4.0,仅供参考。
要解决反向和翻转的问题,可以尝试在创建vtkResliceImageViewer对象之后添加以下代码:
resliceImageViewers[i].SetResliceAxesDirectionCosines(dicomImageReader.GetOutput().GetDirection());
resliceImageViewers[i].SetResliceAxesOrigin(dicomImageReader.GetOutput().GetOrigin());
这将使用DICOM图像的方向余弦和原点信息来设置切面的方向和位置。这样可以确保切面与图像匹配并且不会出现反向或翻转的情况。
在你的代码中,可以将上述代码添加到以下位置:
switch (i)
{
case 0:
{
resliceImageViewers[i].SetRenderWindow(renderWindowControlAxial.RenderWindow);
resliceImageViewers[i].SetupInteractor(renderWindowControlAxial.RenderWindow.GetInteractor());
rep.GetResliceCursorActor().GetCursorAlgorithm().SetReslicePlaneNormalToZAxis();
resliceImageViewers[i].SetSliceOrientationToXY();
break;
}
case 1:
{
resliceImageViewers[i].SetRenderWindow(renderWindowControlSagittal.RenderWindow);
resliceImageViewers[i].SetupInteractor(renderWindowControlSagittal.RenderWindow.GetInteractor());
rep.GetResliceCursorActor().GetCursorAlgorithm().SetReslicePlaneNormalToXAxis();
resliceImageViewers[i].SetSliceOrientationToYZ();
break;
}
case 2:
{
resliceImageViewers[i].SetRenderWindow(renderWindowControlCoronal.RenderWindow);
resliceImageViewers[i].SetupInteractor(renderWindowControlCoronal.RenderWindow.GetInteractor());
rep.GetResliceCursorActor().GetCursorAlgorithm().SetReslicePlaneNormalToYAxis();
resliceImageViewers[i].SetSliceOrientationToXZ();
break;
}
}
// 添加以下代码
resliceImageViewers[i].SetResliceAxesDirectionCosines(dicomImageReader.GetOutput().GetDirection());
resliceImageViewers[i].SetResliceAxesOrigin(dicomImageReader.GetOutput().GetOrigin());