首页 > 解决方案 > VTK:为什么 vtkImageBlend 结果与 RadiAnt 不同

问题描述

假设我有两个图像,并且动脉(红色箭头)的位置大致相同:

在此处输入图像描述

现在,我需要在一个图中显示这两个图像,vtkImageBlend为此我使用了 。我的代码是:

import vtk

img1 = vtk.vtkDICOMImageReader()
img1.SetFileName('C:\\Users\\MLoong\\Desktop\\dicom_data\\Chang Cheng\\TOF\\IM_0198')
img1.Update()
print('img1: ', img1.GetOutput().GetSpacing())
print('img1: ', img1.GetOutput().GetExtent())

img2 = vtk.vtkDICOMImageReader()
img2.SetFileName('C:\\Users\\MLoong\\Desktop\\dicom_data\\Chang Cheng\\SNAP\\IM_0502')
img2.Update()
print('img2: ', img2.GetOutput().GetSpacing())
print('img2: ', img2.GetOutput().GetExtent())

image_blender = vtk.vtkImageBlend()
image_blender.AddInputConnection(img1.GetOutputPort())
image_blender.AddInputConnection(img2.GetOutputPort())
image_blender.SetOpacity(0, 0.1)
image_blender.SetOpacity(1, 0.9)
image_blender.Update()

imageActor = vtk.vtkImageActor()
windowLevel = vtk.vtkImageMapToWindowLevelColors()
imageActor.GetMapper().SetInputConnection(windowLevel.GetOutputPort())


ren = vtk.vtkRenderer()
ren.AddActor(imageActor)
ren.SetBackground(0.1, 0.2, 0.4)

renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
renWin.SetSize(400, 400)

iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)

windowLevel.SetInputData(image_blender.GetOutput())
windowLevel.Update()

renWin.Render()

iren.Start()

结果是:

在此处输入图像描述

在上图中,img2大约是 的一半img1

但是,打印的信息是:

img1:  (0.3571428656578064, 0.3571428656578064, 1.399999976158142)
img1:  (0, 559, 0, 559, 0, 0)
img2:  (0.5, 0.5, 1.0)
img2:  (0, 319, 0, 319, 0, 0)

对于img1,范围为 (560, 560),间距为 (0.357, 0.357)。因此,FOV是:0.357*560=200,而FOVimg2160。因此,我认为混合图可能是错误的。

此外,RadiAnt 还提供了融合图:

在此处输入图像描述

在 RadiAnt 融合图中,两个图像的动脉是重叠的,这就是我想要的。

vtkImageBlend我的代码有什么问题吗?

标签: vtk

解决方案


来自 vtkImageBlend 的详细描述:

“使用 alpha 或不透明度将图像混合在一起 vtkImageBlend 将 L、LA、RGB 或 RGBA 图像作为输入,并根据每个输入的 alpha 值和/或不透明度设置将它们混合。

输出的间距、原点、范围和组件数量与第一个输入的相同。”

因此,您需要确保具有相同的间距、范围和原点。

解决它的方法是创建具有相同属性的新 2 vtkImageData 并将现有数据复制到新图像中。在这里我处理程度:

private static void AdjustImage(ref vtkImageData oldImage, int[] newDimensions)
{
    vtkImageData newImage = new vtkImageData();
    vtkInformation info = new vtkInformation();
    int[] oldDimensions = oldImage.GetDimensions();
    double[] spacing = oldImage.GetSpacing();

    newImage.SetDimensions(newDimensions[0], newDimensions[1], newDimensions[2]);
    vtkImageData.SetScalarType(4/*VTK_SHORT*/, info);
    vtkImageData.SetNumberOfScalarComponents(1, info);//The components that each pixel needs to represent =1 is the index quantity map      
    newImage.AllocateScalars(info);//It is very important to allocate memory and generate image data. After the image is generated, the default value of all pixels is 0 
    newImage.SetSpacing(spacing[0], spacing[1], spacing[2]);

    vtkImageData data = oldImage;
        Parallel.For(0, newDimensions[0], i =>
        {
            if (i < oldDimensions[0])
            {
                Parallel.For(0, newDimensions[1], j =>
                {
                    if (j < oldDimensions[1])
                    {
                        Parallel.For(0, newDimensions[2], k =>
                        {
                            if (k < oldDimensions[2])
                            {
                                newImage.SetScalarComponentFromDouble(i, j,
                                    newDimensions[2] - 1 - k, 0,
                                    data.GetScalarComponentAsDouble(i, j,
                                        oldDimensions[2] - 1 - k, 0));
                            }
                            else
                            {
                                SetImageToDefault(newImage, newDimensions, i, j, k);
                            }
                        });
                    }
                    else
                    {
                        SetImageToDefault(newImage, newDimensions, i, j);
                    }
                });
            }
            else
            {
                SetImageToDefault(newImage, newDimensions, i);
            }
        });

        oldImage.Dispose();
        oldImage = newImage;
}

private static void SetImageToDefault(vtkImageData img, int[] imageDimensions, int i, int j, int k)
{
    const double transparentHu = -1000;
    img.SetScalarComponentFromDouble(i, j, imageDimensions[2] - 1 - k, 0, transparentHu);
}

之后,您将需要通过 2 个图像来源之间差异的增量来转换第二个图像。


推荐阅读