使用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之间,对其进行规范化。这样进行规范化后,在后续也可以进行反变换来实现色彩的还原。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值