最近看了k-means算法,網上這個算法很多都是用來分割二維圖片的,所以想嘗試用這個算法做一下三維圖片的分割。
那麼我們先來介紹一下二維圖片的分割:
原理是這樣的,我們把二維圖片中的每一個像素點的值作爲一個特徵值,如果是彩色圖片,那麼一個像素點就可以由3個特徵值組成,因爲有三個顏色通道。
代碼:
from scipy.cluster.vq import *
from scipy.misc import imresize
from pylab import *
from PIL import Image
import pdb
steps = 40 # image is divided in steps*steps region
infile = 'E:\dataset\ORI_dataset\ADNI-slice3\cMCI\\278_brain\\46_278_brain.jpg'
im = array(Image.open(infile))
dx = int(im.shape[0] / steps)
dy = int(im.shape[1] / steps)
# compute color features for each region
features = []
#pdb.set_trace()
for x in range(steps):
for y in range(steps):
R = mean(im[x * dx:(x + 1) * dx, y * dy:(y + 1) * dy]) #彩色圖片進行三次
#R = mean(im[x * dx:(x + 1) * dx, y * dy:(y + 1) * dy, 0])
#G = mean(im[x * dx:(x + 1) * dx, y * dy:(y + 1) * dy, 1])
#B = mean(im[x * dx:(x + 1) * dx, y * dy:(y + 1) * dy, 2])
#features.append([R, G, B])
features.append(R)
features = array(features, 'f') # make into array
# cluster
centroids, variance = kmeans(features, 2)
code, distance = vq(features, centroids)
# create image with cluster labels
codeim = code.reshape(steps, steps)
codeim = imresize(codeim, im.shape[:2], 'nearest')
figure()
ax1 = subplot(121)
ax1.set_title('Image')
axis('off')
imshow(im)
ax2 = subplot(122)
ax2.set_title('Image after clustering')
axis('off')
imshow(codeim)
show()
結果:
我們的重點是對三維磁共振圖片進行分割,那麼其實原理和二維的差不多,也是將圖片中的像素值作爲特徵值進行劃分。
from scipy.cluster.vq import *
from scipy.misc import imresize
from pylab import *
from PIL import Image
import pdb
import nibabel as nib
from skimage import transform
steps = 182 # image is divided in steps*steps region
infile = 'E:\dataset\ORI_dataset\ADNI-teacher\AD\AD_001.nii\\AD_001.nii'
img=nib.load(infile)
ref_affine = img.affine
img=img.get_data()
img= np.array(img) / 1
#img= transform.resize(img, (32, 40, 32), mode='constant')
dx = int(img.shape[0] / steps)
dy = int(img.shape[2] / steps)
# compute color features for each region
#len(img.shape[1])
all=[]
#pdb.set_trace()
features = []
for i in range(218):
im= img[:, i, :] # 取出一張圖像
dic2 = []
for a in im:
dic1 = []
for b in a:
aa=int(b)
dic1.append(aa)
dic2.append(dic1)
im=np.array(dic2)
for x in range(steps):
for y in range(steps):
R = im[x ,y]
features.append([R])
features = array(features, 'f') # make into array
# cluster
centroids, variance = kmeans(features, 2)
code, distance = vq(features, centroids)
# create image with cluster labels
codeim = code.reshape(218,steps,steps)
#codeim = codeim.reshape(steps,40,steps)
heng5 = nib.Nifti1Image(codeim , ref_affine)
nib.save(heng5, 'E:\dataset\ORI_dataset\ADNI-teacher\AD\AD_001.nii\\112.nii')
一定要注意像素點重新分配的位置,因爲我的圖片是(182,218,182),我的像素點讀取相當於是用(182,182)大小的圖片進行了218次堆疊,每次先遍歷一張圖片,一共遍歷218次,所以最後reshape回來就是(218,182,182)。如果你的reshape是(182,218,182),那麼結果就三維展示會是這樣:
正確結果:右邊爲原始圖像,左邊爲分割之後的圖像,只是這時候像素點位置出現變化。