能否逆向还原vtkImageReslice的3D图像重切片操作?
问题描述
我有一张3D图像和一个仿射矩阵(affine matrix),在Python中使用vtkImageReslice得到重切片后的numpy数组。在对该数组完成算法处理(如分割)后,希望将其还原至原始状态(包括形状、坐标等),使其可与重切片前的图像进行对比,请问是否可行?
以下是我所用fury包中调用vtkImageReslice的代码片段,期望逆向该流程:
image_resliced = vtk.vtkImageReslice() set_input(image_resliced, im) image_resliced.SetResliceTransform(transform) image_resliced.AutoCropOutputOn() # 支持各向异性体素,同时允许按体素坐标切片 RZS = affine[:3, :3] zooms = np.sqrt(np.sum(RZS * RZS, axis=0)) image_resliced.SetOutputSpacing(*zooms) image_resliced.SetInterpolationModeToLinear() image_resliced.Update() vtk_resliced_data = image_resliced.GetOutput() ex1, ex2, ey1, ey2, ez1, ez2 = vtk_resliced_data.GetExtent() resliced = numpy_support.vtk_to_numpy( vtk_resliced_data.GetPointData().GetScalars())
可行方案
完全可以实现逆向流程,将处理后的重切片图像还原到原始图像的空间中,核心是利用原仿射变换的逆变换,结合VTK的图像重采样工具完成。具体步骤如下:
1. 提前保存重切片关键参数
正向重切片时,必须记录以下核心信息(是逆向操作的必要依据):
- 原始图像的元数据:
Extent、Spacing、Origin - 重切片使用的仿射矩阵
affine(或transform对象) - 重切片后图像的
Extent、Spacing、Origin(即vtk_resliced_data的对应属性)
2. 逆向变换实现步骤
步骤1:将处理后的numpy数组转回VTK图像格式
把处理完成的resliced数组重新包装为VTK图像,确保元数据与重切片后的VTK图像一致:
# 重塑数组形状,匹配重切片后的图像尺寸 resliced_shape = (ex2 - ex1 + 1, ey2 - ey1 + 1, ez2 - ez1 + 1) resliced_reshaped = resliced.reshape(resliced_shape).transpose(2,1,0) # 适配VTK的维度顺序 # 创建VTK图像数据对象 vtk_processed = vtk.vtkImageData() vtk_processed.SetExtent(vtk_resliced_data.GetExtent()) vtk_processed.SetSpacing(vtk_resliced_data.GetSpacing()) vtk_processed.SetOrigin(vtk_resliced_data.GetOrigin()) vtk_processed.AllocateScalars(vtk_resliced_data.GetScalarType(), 1) # 将numpy数组写入VTK图像 scalar_data = numpy_support.numpy_to_vtk( num_array=resliced_reshaped.ravel(), deep=True, array_type=vtk_resliced_data.GetScalarType() ) scalar_data.SetName("Scalars") vtk_processed.GetPointData().SetScalars(scalar_data)
步骤2:计算原仿射变换的逆矩阵
逆向映射需要使用原变换的逆矩阵,将处理后的图像坐标转换回原始空间:
# 计算仿射矩阵的逆矩阵 inv_affine = np.linalg.inv(affine) # 转换为VTK可识别的变换对象 inv_transform = vtk.vtkTransform() inv_transform.SetMatrix(inv_affine.flatten())
步骤3:执行逆向重采样
将输出参数设置为原始图像的属性,通过vtkImageReslice把处理后的图像映射回原始空间:
# 获取原始图像的元数据 original_extent = im.GetExtent() original_spacing = im.GetSpacing() original_origin = im.GetOrigin() # 初始化逆向重切片对象 image_reslice_inv = vtk.vtkImageReslice() set_input(image_reslice_inv, vtk_processed) image_reslice_inv.SetResliceTransform(inv_transform) image_reslice_inv.SetOutputExtent(original_extent) image_reslice_inv.SetOutputSpacing(original_spacing) image_reslice_inv.SetOutputOrigin(original_origin) image_reslice_inv.SetInterpolationModeToLinear() # 和正向保持一致,减少误差 image_reslice_inv.Update() # 将结果转回numpy数组 vtk_restored = image_reslice_inv.GetOutput() restored_array = numpy_support.vtk_to_numpy(vtk_restored.GetPointData().GetScalars()) restored_array = restored_array.reshape( (original_extent[1]-original_extent[0]+1, original_extent[3]-original_extent[2]+1, original_extent[5]-original_extent[4]+1) ).transpose(2,1,0)
3. 关键注意事项
- 正向和逆向必须使用相同的插值方式(比如都用线性插值),避免引入额外误差;
- 逆向时不要开启
AutoCropOutputOn(),直接指定原始图像的Extent即可; - 元数据(Origin、Spacing、Extent)必须完整保存,这是空间映射的核心依据,缺一不可。
内容的提问来源于stack exchange,提问作者jongsung park
相关产品推荐
相关产品推荐

