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 ...

9 個月 ago

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

本篇介紹如何在 Ubuntu ...

10 個月 ago

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

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

10 個月 ago

Windows 使用 TPM 虛擬智慧卡保護 SSH 金鑰教學與範例

本篇介紹如何在 Windows...

11 個月 ago

Linux 以 Shamir’s Secret Sharing 分割保存金鑰教學與範例

介紹如何在 Linux 中使用...

11 個月 ago

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

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

11 個月 ago