Python

Python 處理 TIFF 三維立體影像降解析度教學與範例

介紹如何在 Python 中使用 ITK 模組處理 TIFF 檔案序列組成的大型影像。

標準處理方式

如果伺服器的記憶體夠大,足夠容納整個影像的話,可以直接一次將整個影像讀取至記憶體,進行各種處理後,再轉存至輸出檔案中。

ITK 函式庫

這是以標準 ITK 函式庫來處理 TIFF 檔案序列影像降解析度的程式碼,程式碼結構幾乎跟 C++ 版本相同。

#!/usr/bin/python3
import itk
import glob

# 取得 TIFF 影像序列檔案名稱
imgFilenames = sorted(glob.glob("image_folder/*.tif"))

# 設定影像類型
PixelType = itk.ctype('signed short')
Dimension = 3
ImageType = itk.Image[PixelType, Dimension]

# 讀取影像
reader = itk.ImageSeriesReader[ImageType].New()
reader.SetImageIO(itk.TIFFImageIO.New())
reader.SetFileNames(imgFilenames)

# 設定 Voxel Size
changeInfImgFilter = itk.ChangeInformationImageFilter[ImageType].New()
# Voxel Size: 1.82um x 1.82um x 4um
changeInfImgFilter.SetOutputSpacing([1.82, 1.82, 4])
changeInfImgFilter.ChangeSpacingOn()
changeInfImgFilter.SetInput(reader.GetOutput())

# 降低解析度
shrinkFilter = itk.ShrinkImageFilter[ImageType, ImageType].New()
shrinkFilter.SetShrinkFactors([5, 5, 2])
shrinkFilter.SetInput(changeInfImgFilter.GetOutput())

# 輸出影像
WriterType = itk.ImageFileWriter[ImageType]
writer = WriterType.New()
writer.SetFileName("output.nrrd")
writer.SetInput(shrinkFilter.GetOutput())

# 顯示處理進度資訊
watcher1 = itk.SimpleFilterWatcher(reader, "Read Image")
watcher2 = itk.SimpleFilterWatcher(shrinkFilter, "Shrink Image")
watcher3 = itk.SimpleFilterWatcher(writer, "Write Image")

# 實際執行
writer.Update()

SimpleITK 函式庫

這是以 SimpleITK 函式庫來處理 TIFF 檔案序列影像降解析度的程式碼,效果跟上面的 ITK 版本相同,但語法簡潔許多。

#!/usr/bin/python3
import SimpleITK as sitk
import glob

# 取得 TIFF 影像序列檔案名稱
imgFilenames = sorted(glob.glob("image_folder/*.tif"))

# 讀取影像
image = sitk.ReadImage(imgFilenames)

# 設定 Voxel Size
image.SetSpacing([1.82, 1.82, 4])

# 降低解析度
image = sitk.Shrink(image, [5, 5, 2])

# 輸出影像
sitk.WriteImage(image, "output.nrrd")

批次處理單張 2D 影像

當影像的大小過大,無法直接載入至記憶體時,可改用分批處理的方式,一次處理張 TIFF 影像的降解析度,最後再將所有降解析度的 TIFF 影像合併成單一影像檔案。

#!/usr/bin/python3
import SimpleITK as sitk
import glob

# 取得 TIFF 影像序列檔案名稱
imgFilenames = sorted(glob.glob("image_folder/*.tif"))

# 暫存目錄
tmpFolder = "tmp/"

# 降解析度設定
shrinkFactor = [5, 5, 2]

# 原始 Voxel Size
voxelSize = [1.82, 1.82, 4]

# Z 軸降為 1/2 解析度
for imgFilename in imgFilenames[::shrinkFactor[2]]:
    # 讀取影像
    image = sitk.ReadImage(imgFilename)

    # 降低解析度
    image = sitk.Shrink(image, shrinkFactor[0:2])

    # 輸出影像
    sitk.WriteImage(image, tmpFolder + imgFilename.replace('/', '_'))

# 取得 TIFF 影像序列檔案名稱
imgFilenames = sorted(glob.glob(tmpFolder + '*.tif'))

# 讀取影像
image = sitk.ReadImage(imgFilenames)

# 設定 Voxel Size
image.SetSpacing([a*b for a,b in zip(voxelSize, shrinkFactor)])

# 輸出影像
sitk.WriteImage(image, "output.nrrd")

壓縮 NRRD 影像檔案

SimpleITK 輸出的 NRRD 影像檔案是未壓縮的,若需要產生有壓縮的 NRRD 檔案,可以改用 nrrd 模組來輸出:

import nrrd

# 輸出壓縮 NRRD 影像
data = sitk.GetArrayViewFromImage(image)
header = {'spacings': [a*b for a,b in zip(voxelSize, shrinkFactor)]}
nrrd.write("output.nrrd", data, header)

參考資料:Office 指南ITKPythonPackageITKExamples

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