使用 K 均值聚类误差从 CT 灰度图像中进行肺分割

Posted

技术标签:

【中文标题】使用 K 均值聚类误差从 CT 灰度图像中进行肺分割【英文标题】:Lung Segmentation from CT grey sale image using K means clustering Error 【发布时间】:2021-06-04 20:40:24 【问题描述】:

我尝试在下面运行单独分割肺的代码,但结果图像如附件[.请帮忙。

import numpy as np
import cv2
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

X= cv2.imread('0070.png',0)
pixel_values = np.float32(X)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.2)
k = 3
ret, labels, (centers) = cv2.kmeans(pixel_values, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
centers = np.uint8(centers)
labelss = labels.flatten()
print(labelss)
segmented_image = centers[labelss]
segmented_image = segmented_image.reshape((X.shape))
plt.imshow(segmented_image)
plt.show()

【问题讨论】:

在 MATLAB 中进行肺分割要简单得多...如果您有兴趣... 【参考方案1】:

这适用于我在 Python/OpenCV 中使用 Sklearn/Skimage。

输入:

from skimage import io
from sklearn import cluster
import matplotlib.pyplot as plt

# read input and convert to range 0-1
image = io.imread('lung.png',as_gray=True)/255.0
h, w = image.shape

# reshape to 1D array
image_2d = image.reshape(h*w,1)

# set number of colors
numcolors = 3

# do kmeans processing
kmeans_cluster = cluster.KMeans(n_clusters=int(numcolors))
kmeans_cluster.fit(image_2d)
cluster_centers = kmeans_cluster.cluster_centers_
cluster_labels = kmeans_cluster.labels_

# need to scale result back to range 0-255
newimage = cluster_centers[cluster_labels].reshape(h, w)*255.0
newimage = newimage.astype('uint8')

# display result
io.imshow(newimage)
io.show()

# display result as color coded
plt.imshow(newimage)
plt.show() 

# save kmeans clustered image and layer 3
io.imsave('lung_kmeans.gif', newimage)

结果:

结果(颜色编码):

【讨论】:

如何修改代码以便只有两个肺作为分段输出。 我不明白。你有两个肺。你希望其他人发生什么?你想让所有其他的都是透明的吗? 感谢@fmw42先生的回复,我试图单独获得2个肺而忽略了外部部分 在您的上下文中“忽略”是什么意思?您希望其余部分是透明的还是黑色的或其他颜色,或者只是矩形裁剪到肺部区域? 肺部以外的所有区域都需要为黑色【参考方案2】:

这是一个修改后的版本,它使用 Python/OpenCV 仅获取肺部并让其余部分变黑。经过 kmeans 处理后,我们只有 3 个灰度级,我们想要的是中间的一个。所以我们阈值来提取它。然后我们得到轮廓和面积,只保留面积最大的两个轮廓。

输入:

from skimage import io
from sklearn import cluster
import matplotlib.pyplot as plt
import cv2
import numpy as np

# read input and convert to range 0-1
image = io.imread('lung.png',as_gray=True)/255.0
h, w = image.shape

# reshape to 1D array
image_2d = image.reshape(h*w,1)

# set number of colors
numcolors = 3

# do kmeans processing
kmeans_cluster = cluster.KMeans(n_clusters=int(numcolors))
kmeans_cluster.fit(image_2d)
cluster_centers = kmeans_cluster.cluster_centers_
cluster_labels = kmeans_cluster.labels_

# need to scale result back to range 0-255
newimage = cluster_centers[cluster_labels].reshape(h, w)*255.0
newimage = newimage.astype('uint8')

# threshold to keep only middle gray values
lower = (100)
upper = (200)
thresh = cv2.inRange(newimage, lower, upper)

# get contours and corresponding areas and indices
cntrs_info = []
contours = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
index=0
for cntr in contours:
    area = cv2.contourArea(cntr)
    cntrs_info.append((index,area))
    index = index + 1

# sort contours by area
def takeSecond(elem):
    return elem[1]
cntrs_info.sort(key=takeSecond, reverse=True)

# draw two largest contours as white filled on black background
result = np.zeros_like(newimage)
index_first = cntrs_info[0][0]
cv2.drawContours(result,[contours[index_first]],0,(255),-1)
index_second = cntrs_info[1][0]
cv2.drawContours(result,[contours[index_second]],0,(255),-1)

# display result
io.imshow(newimage)
io.show()
io.imshow(thresh)
io.show()
io.imshow(result)
io.show()

# save kmeans clustered image and layer 3
io.imsave('lung_kmeans.gif', newimage)
io.imsave('lung_kmeans_thresh.gif', thresh)
io.imsave('lung_kmeans_lungs.gif', result)
Kmeans结果:

阈值结果:

两个最大的区域:

【讨论】:

以上是关于使用 K 均值聚类误差从 CT 灰度图像中进行肺分割的主要内容,如果未能解决你的问题,请参考以下文章

在Python或C ++中为K均值聚类/删除背景蒙版

k均值聚类算法、c均值聚类算法、模糊的c均值聚类算法的区别

K-均值聚类算法

图像分割基于matlab GUI医学图像均值聚类+OUST+区域生长法图像分割含Matlab源码 2210期

图像分割基于matlab GUI医学图像均值聚类+OUST+区域生长法图像分割含Matlab源码 2210期

图像聚类-K均值聚类