使用 K 均值聚类误差的 CT 灰度图像肺部分割
Lung Segmentation from CT grey sale image using K means clustering Error
我尝试 运行 下面的代码单独分割肺,但生成的图像如附件所示 [。请帮忙。
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()
这对我在 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)
结果:
结果(颜色编码):
这是一个修改后的版本,只得到肺部并使用 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)
K均值结果:
阈值结果:
两个最大的区域:
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()
这对我在 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)
结果:
结果(颜色编码):
这是一个修改后的版本,只得到肺部并使用 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)
K均值结果:
阈值结果:
两个最大的区域: