Reputation: 23
I tried to run below code for segmenting lung alone, but resulting image is as attached[
. Please help.
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()
Upvotes: 1
Views: 1518
Reputation: 53154
Here is a revised version that gets only the lungs and makes all the rest black using Python/OpenCV. After the kmeans processing, we only have 3 gray levels and the one we want is the middle one. So we threshold to extract that. Then we get the contour and areas and keep only the largest two contours by area.
Input:
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)
Threshold result:
Two largest areas:
Upvotes: 1
Reputation: 53154
This works for me in Python/OpenCV using Sklearn/Skimage.
Input:
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)
Result:
Result (color coded):
Upvotes: 1