image
當(dāng)我們查看分割結(jié)果時(shí),會(huì)發(fā)現(xiàn)分割內(nèi)部偶爾會(huì)出現(xiàn)這種分割孔洞(hole)土童。
常識(shí)告訴我們诗茎,這個(gè)器官內(nèi)部是沒有孔洞的,因此娜扇,我們通過后處理的方法把它填上,可以提高分割準(zhǔn)確度错沃。
這種三維孔洞栅组,我們希望有一種便捷方法雀瓢,可以直接填補(bǔ)這種三維孔洞∮竦В可以使用 SITK 的二值孔洞填補(bǔ)方法刃麸。 sitk.BinaryFillhole
- sitk.BinaryFillhole
注意: 該函數(shù)只針對二值圖像(值為0或1)
import SimpleITK as sitk
import os
import glob
imglist= glob.glob('./*.nii.gz')
save_dir = './fillhole'
for img in imglist:
img_nii = sitk.ReadImage(img, outputPixelType=sitk.sitkUInt16)
img_fill = sitk.BinaryFillhole(img_nii)
img_savedir = os.path.join(save_dir, img.split('/')[-1])
sitk.WriteImage(img_fill, img_savedir)
該例子顯示了如何批量填補(bǔ)孔洞,并且保存下來司浪。
- 自寫一個(gè)泊业。
我是主張能用開源工具就用工具,畢竟這些工具都是大牛寫的啊易,值得信賴吁伺。
但是,我這里還是提供一個(gè)github上寫的算法租谈。
大致思路: 這個(gè)算法提供了三維填充和二維填充篮奄,二維填充是選擇一個(gè)面(如橫斷面或者冠狀面)進(jìn)行一層一層的填充捆愁。
from scipy.ndimage.morphology import binary_fill_holes
import numpy as np
from scipy import ndimage
import nibabel as nib
from skimage.measure import label
import matplotlib.pyplot as plt
def hole_filling(bw, hole_min, hole_max, fill_2d=True):
bw = bw > 0
if len(bw.shape) == 2:
background_lab = label(~bw, connectivity=1)
fill_out = np.copy(background_lab)
component_sizes = np.bincount(background_lab.ravel())
too_big = component_sizes > hole_max
too_big_mask = too_big[background_lab]
fill_out[too_big_mask] = 0
too_small = component_sizes < hole_min
too_small_mask = too_small[background_lab]
fill_out[too_small_mask] = 0
elif len(bw.shape) == 3:
if fill_2d:
fill_out = np.zeros_like(bw)
for zz in range(bw.shape[1]):
background_lab = label(~bw[:, zz, :], connectivity=1) # 1表示4連通, ~bw[zz, :, :]1變?yōu)?窟却, 0變?yōu)?
# 標(biāo)記背景和孔洞昼丑, target區(qū)域標(biāo)記為0
out = np.copy(background_lab)
# plt.imshow(bw[:, :, 87])
# plt.show()
component_sizes = np.bincount(background_lab.ravel())
# 求各個(gè)類別的個(gè)數(shù)
too_big = component_sizes > hole_max
too_big_mask = too_big[background_lab]
out[too_big_mask] = 0
too_small = component_sizes < hole_min
too_small_mask = too_small[background_lab]
out[too_small_mask] = 0
# 大于最大孔洞和小于最小孔洞的都標(biāo)記為0, 所以背景部分被標(biāo)記為0了夸赫。只剩下符合規(guī)則的孔洞
fill_out[:, zz, :] = out
# 只有符合規(guī)則的孔洞區(qū)域是1菩帝, 背景及target都是0
else:
background_lab = label(~bw, connectivity=1)
fill_out = np.copy(background_lab)
component_sizes = np.bincount(background_lab.ravel())
too_big = component_sizes > hole_max
too_big_mask = too_big[background_lab]
fill_out[too_big_mask] = 0
too_small = component_sizes < hole_min
too_small_mask = too_small[background_lab]
fill_out[too_small_mask] = 0
else:
print('error')
return
return np.logical_or(bw, fill_out) # 或運(yùn)算,孔洞的地方是1茬腿,原來target的地方也是1
參數(shù)簡介
- bw: array, 待填補(bǔ)的數(shù)組
- hole_min: 孔洞像素的個(gè)數(shù)最小值,一般為0
- hole_max: 孔洞像素的個(gè)數(shù)最大值呼奢。
- fill_2d: True:二維填充。False:三維填充
只有當(dāng)孔洞像素值個(gè)數(shù)在 [hole_min, hole_max] 才會(huì)被填補(bǔ)切平。
算法里面涉及了大量的與或非運(yùn)算控妻。
調(diào)用
filled = hole_filling(arr, 0, 100, fill_2d=True) # 通過改變bw[zz, :, :],選擇軸
你可以對比一下揭绑,這三種算法(第二個(gè)里面是2種算法)哪個(gè)更適合你弓候。
深度學(xué)習(xí),分割后處理之通過連通成分分析去除假陽性區(qū)域他匪,提高分割準(zhǔn)確度
常用的分割后處理方法就是 連通成分分析和填補(bǔ)孔洞菇存,你學(xué)會(huì)了嗎。
我是Tina, 我們下篇博客見~
白天工作晚上寫文邦蜜,嘔心瀝血
覺得寫的不錯(cuò)的話最后依鸥,求點(diǎn)贊,評論悼沈,收藏