深度學(xué)習(xí),分割后處理之通過填補(bǔ)孔洞,提高分割準(zhǔn)確度

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

  1. sitk.BinaryFillhole

注意: 該函數(shù)只針對(duì)二值圖像(值為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ǔ)孔洞,并且保存下來。

  1. 自寫一個(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ù)簡(jiǎn)介

  • 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, :, :],選擇軸

你可以對(duì)比一下,這三種算法(第二個(gè)里面是2種算法)哪個(gè)更適合你。

深度學(xué)習(xí),分割后處理之通過連通成分分析去除假陽性區(qū)域,提高分割準(zhǔn)確度

常用的分割后處理方法就是 連通成分分析和填補(bǔ)孔洞,你學(xué)會(huì)了嗎。

我是Tina, 我們下篇博客見~

白天工作晚上寫文,嘔心瀝血

覺得寫的不錯(cuò)的話最后,求點(diǎn)贊,評(píng)論,收藏

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容