目录
1.序言
2.python实现
3.分割算法的流程及结果如下
4.这是一个人的一次CT检查的序列,挑选部分作为展示
针对医疗领域中的病灶检测中,采用分割算法最为常见。但是,针对特定脏器内的病灶检测,一直存在一个特别易出现假阳性的地方,就是脏器外的误检测。
本文就主要针对CT肺部,对肺实质部分就行切割,去除掉除肺部之外的组织干扰,内容如下:PS,针对肺结节类型的分割前处理中,一般会引入肺实质分割,但是,该方法不能适用于所有的肺部分割中的前处理。因为针对较大的病灶范围,会使得病灶部分一同被切除掉,这是我们所不想看到的。
分割步骤见后面的分割结果图,相信你能看懂。
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()
注意:display=True
本人才疏学浅,本博客留作笔记之用。若恰巧也对你有所帮助,欢迎左侧关注微信公众号和支付宝赞赏。有一位专业知识传播者,等待你的喂养。谢谢
更多科技、数码、理财、生活交流,我们移步今日头条,欢迎关注“钱多多先森”。再见