使用K-Means做图像分割

前面我们介绍过了K-Means,知道在机器学习中经常使用它做聚类。那么在计算机视觉中,也有使用这个算法的应用,那就是图像分割。
所谓的图像分割,就是算法根据图像的颜色、形状、纹理来进行划分区域,也就是对图像的像素进行聚类。如果一个区域内的像素差异小,那么它们的相似度就高;反之,也一样的道理。因此,就利用这一特性来做图像的分割。

这里我们先使用2聚类来模拟生成灰度化后的图。方法很简单,就是当聚类的结果为0则为255,当聚类结果为1时则为127.

import numpy as np
import PIL.Image as image
from sklearn.cluster import KMeans
from sklearn import preprocessing

def load_data(filePath):
    f = open(filePath,'rb')
    data = []
    img = image.open(f)
    width, height = img.size
    for x in range(width):
        for y in range(height):
            c1, c2, c3 = img.getpixel((x, y))
            data.append([c1, c2, c3])
    f.close()
    # 采用Min-Max规范化
    mm = preprocessing.MinMaxScaler()
    data = mm.fit_transform(data)
    return np.mat(data), width, height

img, width, height = load_data('./test.jpg')

# 进行2聚类
kmeans =KMeans(n_clusters=2)
kmeans.fit(img)
label = kmeans.predict(img)
# 将图像聚类结果,转化成图像尺寸的矩阵
label = label.reshape([width, height])
# 创建个新图像pic_mark,用来保存图像聚类的结果,并设置不同的灰度值
pic_mark = image.new("L", (width, height))
for x in range(width):
    for y in range(height):
        # 根据类别设置图像灰度, 类别0 灰度值为255, 类别1 灰度值为127
        pic_mark.putpixel((x, y), int(256/(label[x][y]+1))-1)
pic_mark.save("result.jpg", "JPEG")

那么,如果我们想进增加多几个聚类标识,那么只需要多增加聚类的数目就行了。那么之后根据label对图像的颜色做变换,就可以分割出多姿多彩的图片。

import numpy as np
import PIL.Image as image
from sklearn.cluster import KMeans
from sklearn import preprocessing
import matplotlib.image as mpimg

def load_data(filePath):
    f = open(filePath,'rb')
    data = []
    img = image.open(f)
    
    width, height = img.size
    for x in range(width):
        for y in range(height):
            c1, c2, c3 = img.getpixel((x, y))
            data.append([(c1+1)/256.0, (c2+1)/256.0, (c3+1)/256.0])
    f.close()
    return np.mat(data), width, height

img, width, height = load_data('./test.jpg')
#进行16个聚类
kmeans =KMeans(n_clusters=16)
label = kmeans.fit_predict(img)

label = label.reshape([width, height])
# 创建个新图像img,用来保存图像聚类压缩后的结果
img=image.new('RGB', (width, height))
for x in range(width):
    for y in range(height):
        c1 = kmeans.cluster_centers_[label[x, y], 0]
        c2 = kmeans.cluster_centers_[label[x, y], 1]
        c3 = kmeans.cluster_centers_[label[x, y], 2]
        img.putpixel((x, y), (int(c1*256)-1, int(c2*256)-1, int(c3*256)-1))
img.save('result.jpg')

可以看到,我们这里使用了自己的方法
更改RGB三个通道的数值:+1 / 256,这样数值就会处于0-1之间,对其进行规范化。这样进行规范化后,在后续也可以进行反变换来实现色彩的还原。

你可能感兴趣的:(Python,机器学习,机器学习,python,计算机视觉)