目錄
1.序言
針對醫療領域中的病竈檢測中,採用分割算法最爲常見。但是,針對特定臟器內的病竈檢測,一直存在一個特別易出現假陽性的地方,就是臟器外的誤檢測。
本文就主要針對CT肺部,對肺實質部分就行切割,去除掉除肺部之外的組織干擾,內容如下:PS,針對肺結節類型的分割前處理中,一般會引入肺實質分割,但是,該方法不能適用於所有的肺部分割中的前處理。因爲針對較大的病竈範圍,會使得病竈部分一同被切除掉,這是我們所不想看到的。
分割步驟見後面的分割結果圖,相信你能看懂。
- 輸入是dicom轉過後的png圖像
- 輸出就是只留下肺實質的圖像
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檢查的序列,挑選部分作爲展示
本人才疏學淺,本博客留作筆記之用。若恰巧也對你有所幫助,歡迎左側關注微信公衆號和支付寶讚賞。有一位專業知識傳播者,等待你的餵養。謝謝
更多科技、數碼、理財、生活交流,我們移步今日頭條,歡迎關注“錢多多先森”。再見