介紹如何使用 ITK 的 ResampleImageFilter 進行影像的各種座標轉換以及重新取樣。
ITK 的 ResampleImageFilter 可以用來套用 ITK 的各種轉換(transform),並且以指定的內插方法(interpolator)進行影像的重新取樣(resample),得到新座標系統下的影像。
測試用影像
這裡我們以一張簡單的 2D 影像作為示範用的資料。
import itk
import matplotlib.pyplot as plt
# 影像像素資料類型
PixelType = itk.SS
# 影像維度
Dimension = 2
# 影像類型
ImageType = itk.Image[PixelType, Dimension]
# 建立影像 Reader
ReaderType = itk.ImageFileReader[ImageType]
reader = ReaderType.New()
reader.SetFileName("moving.mhd")
reader.Update()
# 讀取影像
inputImage = reader.GetOutput()
# 取得影像基本資訊
size = inputImage.GetLargestPossibleRegion().GetSize()
spacing = inputImage.GetSpacing()
origin = inputImage.GetOrigin()
print("Size: {}".format(size))
print("Spacing: {}".format(spacing))
print("Origin: {}".format(origin))
Size: itkSize2 ([256, 256]) Spacing: itkVectorD2 ([1, 1]) Origin: itkPointD2 ([0, 0])
ScaleTransform 縮放轉換
以下是一個以 ResampleImageFilter 套用 ScaleTransform 轉換的簡單範例,可將影像以指定的比例放大或縮小。
# 實體座標系統用的資料類型
ScalarType = itk.D
# 計算中心點實體座標
centralPixel = itk.Index[Dimension]()
centralPixel[0] = int(size[0] / 2)
centralPixel[1] = int(size[1] / 2)
centralPoint = itk.Point[ScalarType, Dimension]()
centralPoint[0] = origin[0] + centralPixel[0] / spacing[0]
centralPoint[1] = origin[1] + centralPixel[1] / spacing[1]
# 建立 ScaleTransform 縮放轉換
scaleTransform = itk.ScaleTransform[ScalarType, Dimension].New()
# 設定轉換參數
parameters = scaleTransform.GetParameters()
parameters[0] = 1.5 # X 軸 Scale
parameters[1] = 1.5 # Y 軸 Scale
scaleTransform.SetParameters(parameters)
scaleTransform.SetCenter(centralPoint)
# 建立內插器
interpolatorType = itk.LinearInterpolateImageFunction[ImageType, ScalarType]
interpolator = interpolatorType.New()
# 建立 Resampler
resamplerType = itk.ResampleImageFilter[ImageType, ImageType]
resampleFilter = resamplerType.New()
# 設定 Resampler 各項參數
resampleFilter.SetInput(inputImage)
resampleFilter.SetTransform(scaleTransform)
resampleFilter.SetInterpolator(interpolator)
resampleFilter.SetSize(size)
resampleFilter.SetOutputSpacing(spacing)
# 實際執行
resampleFilter.Update()
# 分開顯示兩張影像
fig, axs = plt.subplots(1, 2)
axs[0].imshow(itk.GetArrayViewFromImage(inputImage), cmap='gray')
axs[0].set_title('Input Image')
axs[1].imshow(itk.GetArrayViewFromImage(resampleFilter.GetOutput()), cmap='gray')
axs[1].set_title('Output Image')
plt.show()

ResampleImageFilter 在重新取樣時,需要設定輸出的影像資料(size 與 spacing 等),除了逐一設定之外,亦可使用 SetReferenceImage() 直接從另外一張影像將這些資訊複製過來。
ResampleImageFilter 亦可使用串流(streaming)的方式來處理大型影像(例如搭配 ImageFileWriter 或 StreamingImageFilter 建立串流),但前提是套用的轉換必須是線性(linear)的;若搭配非線性(non-linear)的轉換,則在 ResampleImageFilter 這一步就必須將整張影像的資料湊齊才能進行處理,但在這一步之前或之後,可以分開拆成串流處理。
TranslationTransform 平移轉換
以下是一個以 ResampleImageFilter 套用 TranslationTransform 轉換的簡單範例,可將影像做平移轉換。
# 建立 TranslationTransform 平移轉換
translationTransform = itk.TranslationTransform[ScalarType, Dimension].New()
parameters = translationTransform.GetParameters()
parameters[0] = 29 # X 軸平移
parameters[1] = 14 # Y 軸平移
translationTransform.SetParameters(parameters)
# 建立 Resampler
resamplerType = itk.ResampleImageFilter[ImageType, ImageType]
resampleFilter = resamplerType.New()
# 設定 Resampler 各項參數
resampleFilter.SetInput(inputImage)
resampleFilter.SetTransform(translationTransform)
resampleFilter.SetInterpolator(interpolator)
resampleFilter.SetSize(size)
resampleFilter.SetOutputSpacing(spacing)
# 實際執行
resampleFilter.Update()
# 分開顯示兩張影像
fig, axs = plt.subplots(1, 2)
axs[0].imshow(itk.GetArrayViewFromImage(inputImage), cmap='gray')
axs[0].set_title('Input Image')
axs[1].imshow(itk.GetArrayViewFromImage(resampleFilter.GetOutput()), cmap='gray')
axs[1].set_title('Output Image')
plt.show()

AffineTransform 線性轉換
以下是一個以 ResampleImageFilter 套用 AffineTransform 轉換的簡單範例,可將影像做各種線性轉換。
# 建立 AffineTransform 線性轉換
affineTransform = itk.AffineTransform[ScalarType, Dimension].New()
# 設定旋轉與平移參數
affineTransform.Rotate2D(0.4)
offset = itk.Vector[ScalarType, Dimension]()
offset[0] = 45.0
offset[1] = -32.0
affineTransform.Translate(offset)
# 建立 Resampler
resamplerType = itk.ResampleImageFilter[ImageType, ImageType]
resampleFilter = resamplerType.New()
# 設定 Resampler 各項參數
resampleFilter.SetInput(inputImage)
resampleFilter.SetTransform(affineTransform)
resampleFilter.SetInterpolator(interpolator)
resampleFilter.SetSize(size)
resampleFilter.SetOutputSpacing(spacing)
# 實際執行
resampleFilter.Update()
# 分開顯示兩張影像
fig, axs = plt.subplots(1, 2)
axs[0].imshow(itk.GetArrayViewFromImage(inputImage), cmap='gray')
axs[0].set_title('Input Image')
axs[1].imshow(itk.GetArrayViewFromImage(resampleFilter.GetOutput()), cmap='gray')
axs[1].set_title('Output Image')
plt.show()
# 顯示轉換參數
parameters = affineTransform.GetParameters()
print("Affine Transfrom Parameters:")
for r in range(len(parameters)):
print(parameters[r])

Affine Transfrom Parameters: 0.9210609940028851 -0.3894183423086505 0.3894183423086505 0.9210609940028851 45.0 -32.0
