vtk - 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,而FOV
是img2
160。因此,我认为混合图可能是错误的。
此外,RadiAnt 还提供了融合图:
在 RadiAnt 融合图中,两个图像的动脉是重叠的,这就是我想要的。
vtkImageBlend
我的代码有什么问题吗?
解决方案
来自 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 个图像来源之间差异的增量来转换第二个图像。
推荐阅读
- vb.net - 将二进制字符串转换为十六进制字符串
- php - 如何修复编辑界面在 Laravel 5.7 中仅获取表中列的第一个单词?
- html - 是否可以根据属性名称调整输入字段宽度
- elasticsearch - Elasticsearch Completion Suggester:真正的标记化可能吗?
- c# - 如何计算特定字符在另一个特定字符之前出现在文本文件中的次数?
- shell - 使用 awk 根据另一列的值对列的值求和
- python - 多选下拉散景
- java - 在没有 Spring 的情况下从 XML 片段实例化 Camel 组件
- python - 没有名为“picamera”的模块
- python - 短短语的快速文本表示,但不适用于包含短短语的较长短语