Python

Python 使用 ITK ResampleImageFilter 影像座標轉換、重新取樣教學與範例

介紹如何使用 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)的方式來處理大型影像(例如搭配 ImageFileWriterStreamingImageFilter 建立串流),但前提是套用的轉換必須是線性(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

參考資料:ITKExamples

Share
Published by
Office Guide
Tags: ITK

Recent Posts

Python 使用 PyAutoGUI 自動操作滑鼠與鍵盤

本篇介紹如何在 Python ...

1 年 ago

Ubuntu Linux 以 WireGuard 架設 VPN 伺服器教學與範例

本篇介紹如何在 Ubuntu ...

1 年 ago

Linux 網路設定 ip 指令用法教學與範例

本篇介紹如何在 Linux 系...

1 年 ago

Linux 以 Cryptsetup、LUKS 加密 USB 隨身碟教學與範例

介紹如何在 Linux 系統中...

1 年 ago