C# vtk 3D网格模型嵌入Dicom序列中

将一个3D 网格模型vtkPolyData  嵌入到 Dicom序列 vtkImageData 。

如图将一个球模型与Dicom数据层面进行融合的体绘制。

1.读取Dicom 序列,读取3D模型

vtk 读取Dicom序列不太好用,我用的ITK 读的然后转为 vtkImageData (不知道怎么转的可以看我的另一篇讲解)。

读取vtkPolyData 。

2. 模型 vtkPolyData 转换为 vtkImageData

注意:vtkImaData 的spacing越小 效果越好,但是受到  Dicom的spacing的限制。

3.对模型vtkImageData进行 Z 轴切片 然后在 对应 Dicom 切片 的位置修改数据。

  vtkMatrix4x4 axialElements = new vtkMatrix4x4();
  for (int n = 0; n < 4; n++)
  {
      for (int m = 0; m < 4; m++)
      {
          if (n == m)
          {
              axialElements.SetElement(n, m, 1);
          }
          else
          {
              axialElements.SetElement(n, m, 0);
          }
      }
  }
  vtkPoints points = new vtkPoints();

  vtkMatrix4x4 resliceAxes = new vtkMatrix4x4();
         

  for (int i = 0; i < imgSize[2]; i++)
  { 
      double[] point = new double[3];
      point[0] = itkCenter[0];
      point[1] = itkCenter[1];
      point[2] = itkOrgin[2] + i * itkSpacing[2];

      resliceAxes.DeepCopy(axialElements);
      resliceAxes.SetElement(0, 3, point[0]);
      resliceAxes.SetElement(1, 3, point[1]);
      resliceAxes.SetElement(2, 3, point[2]);
      

      vtkImageReslice itkImageReslice = vtkImageReslice.New();
      itkImageReslice.SetInputData(itkImageData);
      itkImageReslice.SetOutputDimensionality(2);
      itkImageReslice.SetInterpolationModeToLinear();
      itkImageReslice.SetResliceAxes(resliceAxes);
      itkImageReslice.Update();

      vtkImageData itkResliceData = new vtkImageData();
      itkResliceData.DeepCopy(itkImageReslice.GetOutput());
    
      
      vtkImageReslice stlImageReslice = vtkImageReslice.New();
      stlImageReslice.SetInputData(stlImageData);
      stlImageReslice.SetOutputDimensionality(2);
      stlImageReslice.SetInterpolationModeToLinear();
      stlImageReslice.SetResliceAxes(resliceAxes);
      stlImageReslice.Update();

      vtkImageData stlResliceData = new vtkImageData();
      stlResliceData.DeepCopy(stlImageReslice.GetOutput());

      ImageDataBlend(ref itkImageData, itkResliceData,  stlResliceData, i);

      Console.WriteLine(" i = " + i.ToString());
  }

 // 切片融合
 public void ImageDataBlend(ref vtkImageData itkImage, vtkImageData originImage, vtkImageData blendImage, int nz)
 {
     try
     {
         // 确定范围
         double[] originBound = originImage.GetBounds();
         double oriMinWidth = originBound[0];
         double oriMaxWidth = originBound[1];
         double oriMinHeight = originBound[2];
         double oriMaxHeight = originBound[3];
         int[] oriDim = originImage.GetDimensions();
         double[] oriSpacing = originImage.GetSpacing();
         double[] oriOrigin = originImage.GetOrigin();
          
         vtkDataArray oriDataArray = originImage.GetPointData().GetScalars();
     
         double[] blendBound = blendImage.GetBounds();
         double bleMinWidth = blendBound[0];
         double bleMaxWidth = blendBound[1];
         double bleMinHeight = blendBound[2];
         double bleMaxHeight = blendBound[3];
         int[] bleDim = blendImage.GetDimensions();
         double[] bleSpacing = blendImage.GetSpacing();
         double[] bleorigin = blendImage.GetOrigin();

         vtkDataArray bleDataArray = blendImage.GetPointData().GetScalars();
         int ny = 0;
         for (double y = oriOrigin[1]; y < oriMaxHeight; y = y + oriSpacing[1])
         {
             ny++;
             if (y < bleMinHeight || y > bleMaxHeight)
             {
                 continue;
             }
             int nx = 0;
             for (double x = oriOrigin[0]; x < oriMaxWidth; x = x + oriSpacing[0])
             {
                 nx++;
                 if (x < bleMinWidth || x > bleMaxWidth)
                 {
                     continue;
                 }
                 // 通过坐标获取 blendImage 像素 index
                 int dy = (int)Math.Ceiling((y - bleMinHeight) / bleSpacing[1]);
                 int dx = (int)Math.Ceiling((x - bleMinWidth) / bleSpacing[0]);

                 int bleIndex = (int)Math.Ceiling((y - bleMinHeight) / bleSpacing[1]) * bleDim[0]
                    + (int)Math.Ceiling((x - bleMinWidth) / bleSpacing[0]);


                 int oriIndex =  ny * oriDim[1] + nx;
                 if (bleIndex > bleDataArray.GetNumberOfValues() - 1 || bleIndex <0)
                 {
                     continue;
                 }
                 
                 int bleValue = (int)blendImage.GetScalarComponentAsDouble(dx, dy, 0, 0);

                 if (bleValue == 0)
                 {
                     continue;
                 }
                 if (oriIndex > oriDataArray.GetNumberOfValues() - 1)
                 {
                     continue;
                 }
                 itkImage.SetScalarComponentFromDouble(nx, ny, nz, 0, 51.0);
             }
         }
     }
     catch (Exception ex)
     {
         Console.WriteLine(  "err");
         
     }
    
 }

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值