本文由Markdown语法编辑器编辑完成。
需求背景:
在之前已经完成的图像分割算法中,已经为医生提供了阈值分割、区域增长、盒切和模型切割这四种分割算法,而且这些算法可以组合进行使用。但是客户(医生)在进行实际的操作时,还是会遇到这些算法难以方便解决的情况。比如,当患者在扫描CT或MRI时,病床并不是平直的(盒切只能是平直的),而是呈弧线形的。因此,医生提议能否由医生自己在MPR的某一层面绘制一个图形,然后以这个图形作为横截面,扩展成一个柱状,然后再进行切割。
解决方案
根据需求,结合之前自己做过的项目,后来选定了实现这个功能需要使用的VTK的类,基本实现了这个需求。
以下是基本的代码:
//Construct the pipeline.
vtkSmartPointer< vtkKochanekSpline > xSpline = vtkSmartPointer< vtkKochanekSpline >::New();
vtkSmartPointer< vtkKochanekSpline > ySpline = vtkSmartPointer< vtkKochanekSpline >::New();
vtkSmartPointer< vtkKochanekSpline > zSpline = vtkSmartPointer< vtkKochanekSpline >::New();
vtkSmartPointer<vtkParametricSpline> spline =
vtkSmartPointer< vtkParametricSpline >::New();
spline->SetXSpline( xSpline );
spline->SetYSpline( ySpline );
spline->SetZSpline( zSpline );
//manualEllipsePathModel里面存着之前在轴状位绘制的椭圆弧的点集合.
//这里将DxPoint转化为vtkPoints,塞给spline.
QVector<DxPoint> vecEllipsePathPoints = manualEllipsePathModel->GetEllipsePolygonPath();
vtkSmartPointer< vtkPoints > spPoints = vtkSmartPointer< vtkPoints >::New();
for ( int i = 0; i < vecEllipsePathPoints.size(); i++ )
{
double worldPathPoint[3] = {vecEllipsePathPoints[i].X(), vecEllipsePathPoints[i].Y(), vecEllipsePathPoints[i].Z()};
spPoints->InsertNextPoint( worldPathPoint );
}
double originPathPoint[3] = {vecEllipsePathPoints[0].X(), vecEllipsePathPoints[0].Y(), vecEllipsePathPoints[0].Z()};
spPoints->InsertNextPoint( originPathPoint );
spline->SetPoints();
vtkSmartPointer<vtkParametricFunctionSource> functionSource = vtkSmartPointer<vtkParametricFunctionSource>::New();
functionSource ->SetParametricFunction(spline);
vtkSmartPointer<vtkLinearExtrusionFilter> linearPosExtrusionFilter= vtkSmartPointer< vtkLinearExtrusionFilter>::New();
linearPosExtrusionFilter ->SetInputConnection( functionSource->GetOutputPort());
linearPosExtrusionFilter->SetExtrusionTypeToVectorExtrusion();
double linearPosExtrusionVector[3] = {0.0, 0.0, 1.0};
linearPosExtrusionFilter->SetVector(linearPosExtrusionVector);
double posScaleFactor = 300.0;
linearPosExtrusionFilter->SetScaleFactor(posScaleFactor );
linearPosExtrusionFilter->CappingOn();
linearPosExtrusionFilter->Update();
vtkSmartPointer<vtkPolydata> polydata =
vtkSmartPointer<vtkPolydata>::New();
polydata = linearPosExtrusionFilter->GetOutput();
以上部分的代码是根据在轴状位上绘制的一条椭圆弧,然后按照给定的方向,扩展一定的高度,形成一个椭圆柱的代码。
以上图分别为在轴状位上根据外接矩形的两个对角端点而绘制的椭圆 ,以及由这个椭圆扩展而成的椭圆柱的图形。
以下介绍如何在另外两个矢状位和冠状位上显示切割该柱状体后的代码。
最终的效果图为:
由图可知,一个方向向量为(0.0,0.0,1.0)的椭圆柱,与轴状位的截面是一个椭圆,与矢状位和冠状位的截面则是一个矩形。其中,矢状位矩形的宽度对应椭圆的短轴的2倍,冠状位矩形的宽度对应椭圆的长轴的2倍,而它们两者的高度都是这个椭圆柱本身的高度。
未完待续……