这是一个修改后的版本,它只获得了肺部,并使用 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结果:

阈值结果:

最大的两个区域:
