[CT肺結節]基於KMean肺實質的分割python實現算法

目錄

1.序言

2.python實現

3.分割算法的流程及結果如下

4.這是一個人的一次CT檢查的序列,挑選部分作爲展示


1.序言

針對醫療領域中的病竈檢測中,採用分割算法最爲常見。但是,針對特定臟器內的病竈檢測,一直存在一個特別易出現假陽性的地方,就是臟器外的誤檢測。

本文就主要針對CT肺部,對肺實質部分就行切割,去除掉除肺部之外的組織干擾,內容如下:PS,針對肺結節類型的分割前處理中,一般會引入肺實質分割,但是,該方法不能適用於所有的肺部分割中的前處理。因爲針對較大的病竈範圍,會使得病竈部分一同被切除掉,這是我們所不想看到的。

分割步驟見後面的分割結果圖,相信你能看懂。

  1. 輸入是dicom轉過後的png圖像
  2. 輸出就是只留下肺實質的圖像

2.python實現

import pydicom
import numpy as np
import os
import matplotlib.pyplot as plt
from glob import glob
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import scipy.ndimage
from skimage import morphology
from skimage import measure
from skimage.transform import resize
from sklearn.cluster import KMeans

import cv2

# Standardize the pixel values
def make_lungmask(img, display=False):
    row_size = img.shape[0]
    col_size = img.shape[1]

    mean = np.mean(img)
    std = np.std(img)
    img = img - mean
    img = img / std
    # Find the average pixel value near the lungs
    # to renormalize washed out images
    middle = img[int(col_size / 5):int(col_size / 5 * 4), int(row_size / 5):int(row_size / 5 * 4)]
    mean = np.mean(middle)
    max = np.max(img)
    min = np.min(img)
    # To improve threshold finding, I'm moving the
    # underflow and overflow on the pixel spectrum
    img[img == max] = mean
    img[img == min] = mean
    #
    # Using Kmeans to separate foreground (soft tissue / bone) and background (lung/air)
    #
    kmeans = KMeans(n_clusters=2).fit(np.reshape(middle, [np.prod(middle.shape), 1]))
    centers = sorted(kmeans.cluster_centers_.flatten())
    threshold = np.mean(centers)
    thresh_img = np.where(img < threshold, 1.0, 0.0)  # threshold the image

    # First erode away the finer elements, then dilate to include some of the pixels surrounding the lung.
    # We don't want to accidentally clip the lung.

    eroded = morphology.erosion(thresh_img, np.ones([3, 3]))
    dilation = morphology.dilation(eroded, np.ones([8, 8]))

    labels = measure.label(dilation)  # Different labels are displayed in different colors
    label_vals = np.unique(labels)
    regions = measure.regionprops(labels)
    good_labels = []
    for prop in regions:
        B = prop.bbox
        if B[2] - B[0] < row_size / 10 * 9 and B[3] - B[1] < col_size / 10 * 9 and B[0] > row_size / 5 and B[
            2] < col_size / 5 * 4:
            good_labels.append(prop.label)
    mask = np.ndarray([row_size, col_size], dtype=np.int8)
    mask[:] = 0

    #
    #  After just the lungs are left, we do another large dilation
    #  in order to fill in and out the lung mask
    #
    for N in good_labels:
        mask = mask + np.where(labels == N, 1, 0)
    mask = morphology.dilation(mask, np.ones([10, 10]))  # one last dilation

    if (display):
        fig, ax = plt.subplots(3, 2, figsize=[12, 12])
        ax[0, 0].set_title("Original")
        ax[0, 0].imshow(img, cmap='gray')
        ax[0, 0].axis('off')
        ax[0, 1].set_title("Threshold")
        ax[0, 1].imshow(thresh_img, cmap='gray')
        ax[0, 1].axis('off')
        ax[1, 0].set_title("After Erosion and Dilation")
        ax[1, 0].imshow(dilation, cmap='gray')
        ax[1, 0].axis('off')
        ax[1, 1].set_title("Color Labels")
        ax[1, 1].imshow(labels)
        ax[1, 1].axis('off')
        ax[2, 0].set_title("Final Mask")
        ax[2, 0].imshow(mask, cmap='gray')
        ax[2, 0].axis('off')
        ax[2, 1].set_title("Apply Mask on Original")
        ax[2, 1].imshow(mask * img, cmap='gray')
        ax[2, 1].axis('off')

        plt.show()
    return mask

def raw2mask():
    int_path = r"E:\image_gen\image"
    i=0
    for root, dirs, files in os.walk(int_path):
        for filename in files:  # 遍歷所有文件
            i+=1
            print(filename)
            path = os.path.join(root,filename)
            img = cv2.imread(path)
            gray=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            #cv2.imshow("32",img)
            mask = make_lungmask(gray, display=False)
            Img = np.hstack((gray, mask*gray))
            cv2.imwrite(r"./results/" + filename, Img)


if __name__ == '__main__':

    raw2mask()

3.分割算法的流程及結果如下

注意:display=True

4.這是一個人的一次CT檢查的序列,挑選部分作爲展示

本人才疏學淺,本博客留作筆記之用。若恰巧也對你有所幫助,歡迎左側關注微信公衆號支付寶讚賞。有一位專業知識傳播者,等待你的餵養。謝謝

更多科技、數碼、理財、生活交流,我們移步今日頭條,歡迎關注“錢多多先森”。再見

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章