该代码是根据输入文件的origin,spacing,size,direction和目标文件的spacing,size,direction计算出目标文件的origin。目的是显示图像时,图像在中间。读者应先了解医学图像和SimpleITK,参考链接为Fundamental Concepts — SimpleITK 2.0rc2 documentation。代码如下:
def resize_image_itk(input_file, output_file, interpolator=sitk.sitkNearestNeighbor):
img = sitk.ReadImage(input_file)
# 原始图像数据
origin = img.GetOrigin() # 原origin:[86.09500122070312, 126.51000213623047, -68.25]
spacing = img.GetSpacing() # [1.0, 1.0, 1.0]
size = img.GetSize() # [172, 220, 156]
direction = img.GetDirection() # 原Direction:[-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0]
# 新文件想要保存的数据
newSize = [256, 256, 256]
newSpacing = [1.0, 1.0, 1.0]
newdirection = [1.0, 0.0, 0.0, 0.0, -0.0, -1.0, 0.0, -1.0, 0.0]
# 计算origin_shift(由newSize和newSpacing引起):[42.0, 18.0, 50.0]
origin_shift = [(size[dim] * spacing[dim]-newSize[dim] * newSpacing[dim]) / 2 for dim in range(3)]
# 判断是各个维度的的origin_shift是+/-[42, 18, -50]
arr_direction = np.array(direction).reshape(3, 3)
shift = arr_direction.dot(origin_shift)
trans_origin = [x + y for x, y in zip(origin, shift)]
# 解决由Direction引起的origin变化
# 计算图像中心,中心不会变
shift = np.array(newSize)/2
# 通过方向余弦矩阵与shift相乘得物理坐标系的偏移
center_physical = arr_direction.dot(shift) + trans_origin
# 中心在任何方向余弦矩阵的坐标系的坐标都是(128,128,128),映射回实际坐标系(物理坐标系,但原点是该方向余弦矩阵的坐标系)得到偏移
# 结果为[-127.90499877929688, 144.510009765625, 137.75]
arr_newdirection = np.array(newdirection).reshape(3, 3)
new_origin = center_physical -arr_newdirection.dot(shift)
# 创建重采样器对象
resampler = sitk.ResampleImageFilter()
resampler.SetSize(newSize)
resampler.SetOutputSpacing(newSpacing)
resampler.SetOutputDirection(newdirection)
resampler.SetOutputOrigin(new_origin)
resampler.SetOutputPixelType(sitk.sitkUInt8)
resampler.SetTransform(sitk.Transform(3, sitk.sitkIdentity))
resampler.SetInterpolator(interpolator)
resampler.SetDefaultPixelValue(0)
# 将图像重采样到新的尺寸
resampled_img = resampler.Execute(img)
# 保存新图像
sitk.WriteImage(resampled_img, output_file)