• 跳至主要導覽
  • 跳至主要內容
  • 跳至主要資訊欄
Office 指南

Office 指南

辦公室工作實用教學

  • Excel
  • Word
  • PowerPoint
  • Windows
  • PowerShell
  • R

ITK 計算 3D 二元遮罩影像物件數量與體積

介紹如何在 Python 中使用 ITK 函式庫計算 3D 二元遮罩影像中的物件數量與體積。

讀取原始影像

載入原始的 3D 細胞影像:

import itk
import itkwidgets

# 載入影像
image = itk.imread("3d_monolayer_xy1_ch2.tif")

# 查看影像
itkwidgets.view(image)
原始影像
原始影像

這裡所使用的 3D 細胞影像可以從 CellProfiler 的 GitHub 網站上取得。

產生遮罩影像

使用 BinaryThresholdImageFilter 以門檻值方式產生遮罩影像:

# 以門檻值方式產生遮罩影像
binFilter = itk.BinaryThresholdImageFilter[ImageType, ImageType].New()

# 設定門檻值
binFilter.SetLowerThreshold(110)
binFilter.SetUpperThreshold(255)

binFilter.SetInsideValue(255)
binFilter.SetOutsideValue(0)
binFilter.SetInput(image)
binFilter.Update()

# 查看影像
itkwidgets.view(binFilter.GetOutput())
遮罩影像
遮罩影像

產生物件標註影像

使用 ConnectedComponentImageFilter 將二元影像遮罩轉為物件標註:

# 產生物件標註影像
ccFilter = itk.ConnectedComponentImageFilter[ImageType, CCImageType].New()
ccFilter.SetInput(binFilter.GetOutput())

# 只計算局部區域時可用遮罩控制
#ccFilter.SetMaskImage(anotherMaskImage)

# 計算寬度為 1 像素大小的物件時,需要啟用 Fully Connected 選項
#ccFilter.SetFullyConnected(True)

ccFilter.Update()

# 查看影像
itkwidgets.view(ccFilter.GetOutput())
標註影像
標註影像

查看所有物件的數量:

# 物件數量
print("Object Count:", ccFilter.GetObjectCount())
Object Count: 4320

由於影像中有許多雜訊都會被判定為獨立的物件,因此在初步的處理結果中,物件的數量會遠大於實際的物件數量,必須再進一步處理。

保留前 N 個最大的物件

LabelShapeKeepNObjectsImageFilter 可以根據各種物件的屬性(預設是像素數),取出前 N 個最大的物件:

# 保留前 N 個最大的物件
keepNObjFilter = itk.LabelShapeKeepNObjectsImageFilter[CCImageType].New()
keepNObjFilter.SetInput(ccFilter.GetOutput())
keepNObjFilter.SetBackgroundValue(0)

# 保留前 20 個最大的物件
keepNObjFilter.SetNumberOfObjects(20)

# 根據物件的像素數量排序(NUMBER_OF_PIXELS = 100)
keepNObjFilter.SetAttribute(100)

keepNObjFilter.Update()

# 查看影像
itkwidgets.view(keepNObjFilter.GetOutput())
前 20 個最大的物件
前 20 個最大的物件

依照物件大小重新編排標註

另一種常見的後處理方式是使用 RelabelComponentImageFilter 依照物件大小重新編排物件標註,並且排除太小的物件:

# 依照物件大小重新編排物件標註
relabelFilter = itk.RelabelComponentImageFilter[CCImageType, CCImageType].New()
relabelFilter.SetInput(ccFilter.GetOutput())

# 設定物件的最低像素數
relabelFilter.SetMinimumObjectSize(1000)

relabelFilter.Update()

# 物件數量
print("Number of Object:", relabelFilter.GetNumberOfObjects())
Number of Object: 18

列出重新編排後的所有物件:

# 列出所有物件的大小
for i in range(1, relabelFilter.GetNumberOfObjects()+1):
    print("Label {}: Size = {}".format(i, relabelFilter.GetSizeOfObjectInPixels(i)))
Label 1: Size = 96923
Label 2: Size = 87725
Label 3: Size = 44710
Label 4: Size = 44152
Label 5: Size = 44129
Label 6: Size = 42240
Label 7: Size = 39144
Label 8: Size = 36027
Label 9: Size = 33964
Label 10: Size = 32491
Label 11: Size = 31588
Label 12: Size = 30674
Label 13: Size = 29314
Label 14: Size = 21026
Label 15: Size = 12549
Label 16: Size = 4779
Label 17: Size = 3656
Label 18: Size = 2733

這裡透過 GetSizeOfObjectInPixels 所取得的體積其單位是 voxel,若要獲取物件實際的體積,可以改用 GetSizeOfObjectInPhysicalUnits。

串流處理

對於大型影像,可以使用 StreamingImageFilter 串流分批處理的方式處理。

import itk
import itkwidgets

PixelType = itk.UC
Dimension = 3
ImageType = itk.Image[PixelType, Dimension]
CCImageType = itk.Image[itk.US, Dimension]

# 載入影像
imageFilename = "3d_monolayer_xy1_ch2.tif"
reader = itk.ImageFileReader[ImageType].New(FileName=imageFilename)

# 以門檻值方式產生遮罩影像
binFilter = itk.BinaryThresholdImageFilter[ImageType, ImageType].New()
binFilter.SetLowerThreshold(110)
binFilter.SetUpperThreshold(255)
binFilter.SetInsideValue(255)
binFilter.SetOutsideValue(0)
binFilter.SetInput(reader.GetOutput())

# 產生物件標註影像
ccFilter = itk.ConnectedComponentImageFilter[ImageType, CCImageType].New()
ccFilter.SetInput(binFilter.GetOutput())

# 依照物件大小重新編排物件標註
relabelFilter = itk.RelabelComponentImageFilter[CCImageType, CCImageType].New()
relabelFilter.SetInput(ccFilter.GetOutput())
relabelFilter.SetMinimumObjectSize(1000)

# 設定分割數量
numberOfSplits = 4

# 建立 PipelineMonitorImageFilter 查看 Streaming 每次處理的範圍
monitorFilter = itk.PipelineMonitorImageFilter[CCImageType].New()
monitorFilter.SetInput(relabelFilter.GetOutput())

# 建立 StreamingImageFilter 將資料以 Streaming 分批處理
streamingFilter = itk.StreamingImageFilter[CCImageType, CCImageType].New()
streamingFilter.SetInput(monitorFilter.GetOutput())
streamingFilter.SetNumberOfStreamDivisions(numberOfSplits)

# 實際執行
streamingFilter.Update()

# 輸出影像完整的 Region 資訊
print('The output LargestPossibleRegion is: ' +
      str(streamingFilter.GetOutput().GetLargestPossibleRegion()))

# 輸出 Streaming 的分批 Region 資訊
updatedRequestedRegions = monitorFilter.GetUpdatedRequestedRegions()
print("Updated RequestedRegion's:")
for r in range(len(updatedRequestedRegions)):
    print('  ' + str(updatedRequestedRegions[r]))
The output LargestPossibleRegion is: itkImageRegion3([0, 0, 0], [256, 256, 60])
Updated RequestedRegion's:
  itkImageRegion3([0, 0, 0], [256, 256, 15])
  itkImageRegion3([0, 0, 15], [256, 256, 15])
  itkImageRegion3([0, 0, 30], [256, 256, 15])
  itkImageRegion3([0, 0, 45], [256, 256, 15])
# 物件數量
print("Number of Object:", relabelFilter.GetNumberOfObjects())
Number of Object: 18
# 列出所有物件的大小
for i in range(1, relabelFilter.GetNumberOfObjects()+1):
    print("Label {}: Size = {}".format(i, relabelFilter.GetSizeOfObjectInPixels(i)))
Label 1: Size = 96923
Label 2: Size = 87725
Label 3: Size = 44710
Label 4: Size = 44152
Label 5: Size = 44129
Label 6: Size = 42240
Label 7: Size = 39144
Label 8: Size = 36027
Label 9: Size = 33964
Label 10: Size = 32491
Label 11: Size = 31588
Label 12: Size = 30674
Label 13: Size = 29314
Label 14: Size = 21026
Label 15: Size = 12549
Label 16: Size = 4779
Label 17: Size = 3656
Label 18: Size = 2733

參考資料

  • ITKExamples:Label Connect Components In Binary Image
  • ITKExamples:Extra Largest Connect Component From Binary Image
  • ITKExamples:Threshold An Image Using Binary Thresholding

分類:Python 標籤:ITK

主要資訊欄

搜尋

近期文章

  • Python 使用 PyAutoGUI 自動操作滑鼠與鍵盤
  • Ubuntu Linux 以 WireGuard 架設 VPN 伺服器教學與範例
  • Linux 網路設定 ip 指令用法教學與範例
  • Windows 使用 TPM 虛擬智慧卡保護 SSH 金鑰教學與範例
  • Linux 以 Shamir’s Secret Sharing 分割保存金鑰教學與範例
  • Linux 以 Cryptsetup、LUKS 加密 USB 隨身碟教學與範例
  • Linux 以 Cryptsetup 與 LUKS 加密磁碟教學與範例
  • Linux 使用 age 簡潔的加密、解密工具使用教學與範例

推薦網站

  • Udemy 線上教學課程
  • Coursera 線上教學課程

關注本站

  • 電子郵件
  • Facebook

公益

  • 家扶基金會
  • 台灣世界展望會
  • Yahoo 奇摩公益
  • igiving 公益網
  • 兒福聯盟

Copyright © 2021 · Office Guide