我尝试运行下面的代码来单独分割肺部,但得到的结果图像如附件所示[
。请帮助我解决这个问题。
回答:
这里是一个修改版本,使用Python/OpenCV仅获取肺部并将其他部分设为黑色。在kmeans处理之后,我们只有三个灰度级别,我们想要的是中间的那个。所以我们通过阈值处理来提取它。然后我们获取轮廓和面积,并只保留面积最大的两个轮廓。
输入:
from skimage import iofrom sklearn import clusterimport matplotlib.pyplot as pltimport cv2import numpy as np# 读取输入并转换到0-1范围image = io.imread('lung.png',as_gray=True)/255.0h, w = image.shape# 重塑为1D数组image_2d = image.reshape(h*w,1)# 设置颜色数量numcolors = 3# 进行kmeans处理kmeans_cluster = cluster.KMeans(n_clusters=int(numcolors))kmeans_cluster.fit(image_2d)cluster_centers = kmeans_cluster.cluster_centers_cluster_labels = kmeans_cluster.labels_# 需要将结果重新缩放到0-255范围newimage = cluster_centers[cluster_labels].reshape(h, w)*255.0newimage = newimage.astype('uint8')# 阈值处理仅保留中间灰度值lower = (100)upper = (200)thresh = cv2.inRange(newimage, lower, upper)# 获取轮廓和相应的面积及索引cntrs_info = []contours = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)contours = contours[0] if len(contours) == 2 else contours[1]index=0for cntr in contours: area = cv2.contourArea(cntr) cntrs_info.append((index,area)) index = index + 1# 按面积排序轮廓def takeSecond(elem): return elem[1]cntrs_info.sort(key=takeSecond, reverse=True)# 在黑色背景上绘制两个最大的轮廓为白色填充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)# 显示结果io.imshow(newimage)io.show()io.imshow(thresh)io.show()io.imshow(result)io.show()# 保存kmeans聚类图像和第3层io.imsave('lung_kmeans.gif', newimage)io.imsave('lung_kmeans_thresh.gif', thresh)io.imsave('lung_kmeans_lungs.gif', result)
Kmeans结果:
阈值结果:
两个最大面积: