本教程演示如何在LEADTOOLS中加载和显示2D DICOM图像切片堆栈作为3D对象MedicalViewer
WinForms控制。
概述 | |
---|---|
总结 | 本教程介绍了如何在WinForms c#应用程序中加载和显示2D DICOM图像切片堆栈作为3D对象。 |
完成时间 | 30分钟 |
Visual Studio项目 | 下载教程项目(12kb) |
平台 | Windows WinForms c#应用程序 |
IDE | Visual Studio 2019, 2022 |
开发许可 | 下载LEADTOOLS |
步骤,熟悉创建项目和显示DICOM映像的基本步骤添加引用和设置License而且在医疗查看器中加载和显示DICOM图像教程,在工作之前加载和显示DICOM图像切片作为一个3D对象- WinForms c#教程。
的Medical3DControl
提供医疗3D对象,并与MedicalViewer
类继承的MedicalViewerBaseCell
类的基本对象,这意味着它与MedicalViewerMultiCell
类用于正常显示二维医学图像。
要使用正确的测量和缩放正确地渲染3D体积,需要以下信息:
此外,对于给定的一组2D图像切片,截面平面必须平行且顺序正确。
为了说明问题,本教程使用image1.dcm
样本:< INSTALL_DIR > \ LEADTOOLS22 \ \ \ DICOM图像资源
这是一个磁共振(MR)样本,其中包含了正确顺序的图像以及存储在数据集标签中的上述信息。
中创建的项目的副本开始在医疗查看器中加载和显示DICOM图像教程。如果项目不可用,请按照该教程中的步骤创建它。
所需要的参考资料取决于项目的目的。引用可以通过以下两种方法中的一种添加(但不能同时添加)。
如果使用NuGet引用,本教程需要以下NuGet包:
Leadtools.Medical.Viewer.WinForms
Leadtools。如Jpeg2000
如果使用本地DLL引用,则需要以下DLL。
dll位于< INSTALL_DIR > \ LEADTOOLS22 \ Bin \ Dotnet4 \ x64
:
Leadtools.dll
Leadtools.Codecs.Cmp.dll
Leadtools.Codecs.J2k.dll
Leadtools.Dicom.dll
Leadtools.MedicalViewer.dll
Leadtools.Medical3D.dll
有关应用程序需要哪些DLL文件的完整列表,请参阅你的申请中包含的文件.
许可证解锁项目所需的特性。它必须在调用任何工具箱函数之前设置。有关详细信息,包括针对不同平台的教程,请参阅设置运行时License.
有两种类型的运行时许可证:
现在已经将LEADTOOLS引用添加到项目中,并设置了许可证,可以开始编码了。
右键单击Form1.cs
在解决方案资源管理器并选择视图代码以显示表单后面的代码。
添加Leadtools。Medical3D
到使用
块在文件顶部。
使用系统;
使用先;
使用System.Windows.Forms;
使用Leadtools;
使用Leadtools.Dicom;
使用Leadtools.Medical3D;
使用Leadtools.MedicalViewer;
添加Medical3DControl
对象添加到全局变量。
私人MedicalViewer _medicalViewer;
私人MedicalViewerMultiCell _cell;
私人Medical3DControl _control3D;
修改loadDICOMToolStripMenuItem_Click
事件处理程序来添加对Initialize3DControl
函数之后_medicalViewer.Cells.Add (_cell)
.
//添加初始化的单元格
_medicalViewer.Cells.Add (_cell);
//初始化3D控件
如果(_cell.Image。PageCount >
Initialize3DControl (_cell.Image。宽度,_cell.Image。高度,_cell.Image.PageCount);
确保将下面的代码添加到Initialize3DControl
函数。
私人无效Initialize3DControl (int宽度,int高度,inttotalFrames)
{
//创建3D控件
保龄球usesoftwarerender = !CanUse3DTexturing(宽度,高度,totalFrames);
_control3D =新Medical3DControl (useSoftwareRendering);
_control3D.ObjectsContainer。RenderingType = Medical3DVolumeRenderingType.Auto;
_control3D.ObjectsContainer.Objects.Add (新Medical3DObject ());
//初始化3D帧
保龄球created = _control3D.ObjectsContainer.Objects[0].MemoryEfficientInit(totalFrames);
如果创建(!)
{
//删除对象
_control3D.ObjectsContainer.Objects.RemoveAt (0);
_control3D.Dispose ();
_control3D =零;
返回;
}
//添加3D控制动作
_control3D.AddAction (MedicalViewerActionType.WindowLevel);
_control3D.AddAction (MedicalViewerActionType.Rotate3DObject);
_control3D.AddAction (MedicalViewerActionType.Scale3DObject);
_control3D.SetAction (MedicalViewerActionType。Rotate3DObject MedicalViewerMouseButtons。对,MedicalViewerActionFlags.Active);
_control3D.SetAction (MedicalViewerActionType。WindowLevel MedicalViewerMouseButtons。离开,MedicalViewerActionFlags.Active);
_control3D.SetAction (MedicalViewerActionType。Scale3DObject MedicalViewerMouseButtons。中间,MedicalViewerActionFlags.Active);
}
初始化3D控件后,修改控件中的代码loadDICOMToolStripMenuItem_Click
事件处理程序获取数据集中每一帧的图像位置信息,并使用它将帧正确地加载到3D控件中。
//初始化3D控件
如果(_cell.Image。PageCount >
Initialize3DControl (_cell.Image。宽度,_cell.Image。高度,_cell.Image.PageCount);
如果(_control3D ! =零)
{
//用DICOM文件中的图像位置信息填充单元格帧
SetCellFramesImagePosition(数据集);
//添加图像页到3D控制帧
为(int指数= 0;index < _cell.Image.PageCount;指数+ +)
{
_cell.Image。Page = index + 1;
_control3D.ObjectsContainer.Objects[0].MemoryEfficientSetFrame(_cell.Image.Clone(), index, _cell.GetImagePosition(index),真正的);
}
}
添加一个名为SetCellFramesImagePosition (DicomDataSet数据集)
.方法中调用此方法loadDICOMToolStripMenuItem_Click
事件处理程序,如上所示。添加下面的代码来从DICOM数据集加载图像位置信息,并在2D单元格中的每个帧的属性中设置它。
私人无效SetCellFramesImagePosition (DicomDataSet数据集)
{
int指数= 0;
DicomElement元素= dataSet。FindFirstElement (零, DicomTag。PerFrameFunctionalGroupsSequence,真正的);
如果(元素! =零)
{
element =数据集。GetChildElement(元素,真正的);
DicomElement firsttem =数据集。FindFirstElement (element, DicomTag.Item,真正的);
而(firstItem ! =零)
{
element =数据集。GetChildElement (firstItem真正的);
element =数据集。FindFirstElement (element, DicomTag.PlanePositionSequence,真正的);
element =数据集。GetChildElement(元素,真正的);
element =数据集。FindFirstElement (element, DicomTag.Item,真正的);
element =数据集。GetChildElement(元素,真正的);
element =数据集。FindFirstElement (element, DicomTag.ImagePositionPatient,真正的);
如果(元素! =零)
{
双[] doubleArray =数据集。GetDoubleValue(element, 0,3);
_cell。SetImagePosition(指数,Point3D.FromDoubleArray (doubleArray),假);
指数+ +;
}
firstItem =数据集。GetNextElement (firstItem真正的,真正的);
}
}
}
将所有帧加载到3D控件后,将下面的代码添加到loadDICOMToolStripMenuItem_Click
事件处理程序来完成帧和标记的设置。
如果(_control3D ! =零)
{
//用DICOM文件中的图像位置信息填充单元格帧
SetCellFramesImagePosition(数据集);
//添加图像页到3D控制帧
为(int指数= 0;index < _cell.Image.PageCount;指数+ +)
{
_cell.Image。Page = index + 1;
_control3D.ObjectsContainer.Objects[0].MemoryEfficientSetFrame(_cell.Image.Clone(), index, _cell.GetImagePosition(index),真正的);
}
//从DICOM获取图像方向
SetCellImageOrientation(数据集);
//从DICOM获取像素间距
SetCellPixelSpacing(数据集);
/ /完成
_control3D.ObjectsContainer.Objects [0] .MemoryEfficientEnd (_cell。ImageOrientation _cell.PixelSpacing);
//设置标签
Set3DTags ();
}
添加两个名为SetCellImageOrientation (DicomDataSet数据集)
而且SetCellPixelSpacing (DicomDataSet数据集)
.方法中调用这两个方法loadDICOMToolStripMenuItem_Click
事件处理程序,如上所示。将下面的代码添加到SetCellImageOrientation
函数从数据集中获取图像方向。
私人无效SetCellImageOrientation (DicomDataSet数据集)
{
DicomElement元素= dataSet。FindFirstElement (零, DicomTag。PerFrameFunctionalGroupsSequence,真正的);
如果(元素! =零)
{
element =数据集。GetChildElement(元素,真正的);
element =数据集。FindFirstElement (element, DicomTag.Item,真正的);
element =数据集。GetChildElement(元素,真正的);
element =数据集。FindFirstElement (element, DicomTag.PlaneOrientationSequence,真正的);
element =数据集。GetChildElement(元素,真正的);
element =数据集。FindFirstElement (element, DicomTag.Item,真正的);
element =数据集。GetChildElement(元素,真正的);
element =数据集。FindFirstElement (element, DicomTag.ImageOrientationPatient,真正的);
双[] doubleArray =数据集。GetDoubleValue(element, 0,6);
_cell。ImageOrientation =新浮动[] {(浮动) doubleArray [0], (浮动) doubleArray [1], (浮动) doubleArray [2], (浮动) doubleArray [3], (浮动) doubleArray [4], (浮动) doubleArray [5]};
}
}
将下面的代码添加到SetCellPixelSpacing
函数从数据集中获取像素间距信息。
私人无效SetCellPixelSpacing (DicomDataSet数据集)
{
DicomElement元素= dataSet。FindFirstElement (零, DicomTag。SharedFunctionalGroupsSequence,真正的);
如果(元素! =零)
{
element =数据集。FindFirstElement (element, DicomTag.Item,假);
element =数据集。FindFirstElement (element, DicomTag.PixelMeasuresSequence,假);
element =数据集。FindFirstElement (element, DicomTag.Item,假);
element =数据集。FindFirstElement (element, DicomTag.PixelSpacing,假);
双[] doubleArray =数据集。GetDoubleValue(element, 0,2);
_cell。PixelSpacing =新Point2D (doubleArray [0], doubleArray [1]);
}
}
在Program类中添加一个名为Set3DTags()的新函数。类的底部调用此函数loadDICOMToolStripMenuItem_Click
事件处理程序,如前一步所示。
添加下面的代码,使用来自2D单元格的标签设置相关的3D控件标签。
私人无效Set3DTags ()
{
MedicalViewerTagInformation信息;
//从多单元格中加载用户数据标签
Information = _cell。MedicalViewerTagAlignment.TopRight GetTag (2);
如果(信息! =零) _control3D。MedicalViewerTagAlignment SetTag(1。TopRight,信息。类型,information.Text);
Information = _cell。MedicalViewerTagAlignment.TopRight GetTag (3);
如果(信息! =零) _control3D。MedicalViewerTagAlignment SetTag(2。TopRight,信息。类型,information.Text);
Information = _cell。MedicalViewerTagAlignment.TopRight GetTag(4日);
如果(信息! =零) _control3D。MedicalViewerTagAlignment SetTag(3。TopRight,信息。类型,information.Text);
Information = _cell。MedicalViewerTagAlignment.TopRight GetTag(5日);
如果(信息! =零) _control3D。MedicalViewerTagAlignment SetTag(4。TopRight,信息。类型,information.Text);
Information = _cell。MedicalViewerTagAlignment.TopRight GetTag(6日);
如果(信息! =零) _control3D。MedicalViewerTagAlignment SetTag(5。TopRight,信息。类型,information.Text);
Information = _cell。MedicalViewerTagAlignment.TopRight GetTag(7日);
如果(信息! =零) _control3D。MedicalViewerTagAlignment SetTag(5。TopRight,信息。类型,information.Text);
//其他标签
_control3D。MedicalViewerTagAlignment SetTag(4。TopLeft MedicalViewerTagType.Frame);
_control3D。MedicalViewerTagAlignment SetTag(6日。TopLeft MedicalViewerTagType.Scale);
_control3D。MedicalViewerTagAlignment SetTag(2。BottomLeft MedicalViewerTagType.WindowLevelData);
_control3D。MedicalViewerTagAlignment SetTag(1。BottomLeft MedicalViewerTagType.FieldOfView);
_control3D。MedicalViewerTagAlignment SetTag(0。BottomLeft MedicalViewerTagType.RulerUnit);
}
在解决方案资源管理器,双击Form1.cs
在设计器中显示。添加一个细胞类型菜单menuStrip1
与一个&VRT和一个&2D细胞菜单项。右键单击每个项目并取消选中启用两者皆可选。使用_menuVolumeVRT
而且_menu2DCell
作为每个菜单项的Name属性。
为细胞类型菜单对象,单击事件图标。属性窗口.然后,双击DropDownOpening事件来创建事件处理程序(如果不存在)。
控件中添加以下代码cellTypeToolStripMenuItem_DropDownOpening
事件处理程序。
私人无效cellTypeToolStripMenuItem_DropDownOpening (对象发送者,EventArgs
{
保龄球Allow3D =假;
保龄球Allow2D =假;
如果(_cell ! =零)
Allow2D =真正的;
如果(_control3D ! =零)
Allow3D =真正的;
_menuVolumeVRT。启用= Allow3D;
_menu2DCell。启用= Allow2D;
}
双击VRT菜单项编辑其事件处理程序。添加以下代码将3D控件加载到查看器中(如果可用的话)。
私人无效_menuVolumeVRT_Click (对象发送者,EventArgs
{
foreach(ToolStripMenuItem ToolStripMenuItem在cellTypeToolStripMenuItem.DropDownItems)
toolStripMenuItem。检查=假;
_menuVolumeVRT。检查=真正的;
如果(_medicalViewer。Cells[0] != _control3D)
{
_medicalViewer.Cells.Clear ();
_medicalViewer.Cells.Add (_control3D);
}
}
接下来,双击2 d细胞菜单项编辑其事件处理程序。添加以下代码将2D单元格加载到查看器中。
私人无效_menu2DCell_Click (对象发送者,EventArgs
{
foreach(ToolStripMenuItem ToolStripMenuItem在cellTypeToolStripMenuItem.DropDownItems)
toolStripMenuItem。检查=假;
_menu2DCell。检查=真正的;
如果(_medicalViewer。细胞[0]!= _cell)
{
_medicalViewer.Cells.Clear ();
_medicalViewer.Cells.Add (_cell);
}
}
最后,添加下面的代码,以便在加载新图像时从所选单元格类型菜单项中清除选中标记。
私人无效loadDICOMToolStripMenuItem_Click (对象发送者,EventArgs
{
试一试
{
//清除现有单元格
如果(_medicalViewer.Cells。计数> 0)
_medicalViewer.Cells.Clear ();
//清除单元格类型菜单中的对号
foreach(ToolStripMenuItem ToolStripMenuItem在cellTypeToolStripMenuItem.DropDownItems)
toolStripMenuItem。检查=假;
按下运行项目F5,或选择Debug ->开始调试.
如果正确地执行了上述步骤,则应用程序将运行,并允许加载和显示选定的2D DICOM图像切片集MedicalViewer
三维空间的控制。可以使用image1.dcm
样本:< INSTALL_DIR > \ LEADTOOLS22 \ \ \ DICOM图像资源
加载示例文件,然后选择Cell Type -> VRT.
方法中渲染3D DICOM图像所必需的引用MedicalViewer
WinForms控制。