K-means聚类算法第8关:图像分割

任务描述

本关任务:编写一个程序对图像进行分割。

原图如下:

分割图像如下:

相关知识

为了完成本关任务,你需要掌握:

  • 聚类与图像分割;

  • 图像的基础操作;

  • 如何使用 GaussianMixture。

聚类与图像分割

图像分割非常好理解,如上面的图所示,就是将图像划分成若干个不同的部分(分割结果可以看出将原图划分成了 3 个部分:道路、树林、天空)。

那么图像分割怎样和聚类扯上关系呢?很简单,我们知道一副彩色图像是由多个像素点组成的。若把每个像素点看成是一个样本的话,我们就可以通过聚类的方式给每个像素点打上簇标记(比如 0,1,2)。然后再根据簇标记将像素点设置成想要的颜色(比如簇标记为 0 的设置成黄色,簇标记为 1 的设置成绿色,簇标记为 2 的设置成蓝色),然后可视化出来就能得到图像分割的效果。

那么怎样将一副图像转换成我们通常想要的类似表格的数据呢?也很简单,一副彩色图像是由多个像素点组成的,而一个像素点一般是由 R,G,B 三个通道组成的。那么我们可以把每一个像素点看成是数据集中的一个样本,每个样本包含 3 个特征( RGB 三个通道的值)。所以如果一副彩色图的高是 200,宽是 300。则该图可以看成是一个 60000 行,3 列的数据集。有了我们喜闻乐见的表格数据后,就可以将数据传递给聚类算法进行聚类了。

如果你对数字图像处理中的阈值化感兴趣,可以 点这里 学习怎样用另一种思来实现图像分割。

图像的基础操作

我们可以使用 PIL 来对图像进行操作。如果你想读取一幅图或者保存一副图,代码如下:

  1. from PIL import Image
  2. # 读取road.jpg到im变量中
  3. im = Image.open('road.jpg')
  4. # 将im保存为new_road.jpg
  5. im.save('new_road.jpg')

值得注意的是,当使用 open 函数读取到图像后,我们不能直接将图像传给 sklearn 的聚类算法接口。因为此时的 im 不是 ndarray 或者 list ,而且 im 的形状不是喜闻乐见的表格的形状。所以需要进行转换,代码如下:

  1. import numpy as np
  2. # 将im转换成ndarray
  3. img = np.array(im)
  4. # 将img变形为[-1, 3]的shape,并保存至img_reshape
  5. img_reshape = img.reshape(-1, 3)

当聚类算法给出结果后,我们需要根据聚类结果给图像上色,代码如下:

  1. # pred为聚类算法的预测结果,将簇为0的点设置成红色,簇为1的点设置成蓝色
  2. img[pred == 0, :] = [255, 0, 0]
  3. img[pred == 1, :] = [0, 0, 255]

由于 img 为 ndarray,我们需要将其转成 Image 类型才能使用 save 函数实现保存图片的功能。转换代码如下:

  1. im = Image.fromarray(img.astype('uint8'))

如何使用 GaussianMixture

GaussianMixture 是 sklearn 提供的高斯混合聚类的一个类,该类的构造函数中可以根据实际需要设置很多参数。但常用的参数是 n_components 和 max_iter。其中:

  • n_components :想要聚成几个簇,类型为 int;
  • max_iter :迭代次数,类型为 int。

使用 GaussianMixture 进行聚类很简单,fit-predict 大法就完事了。代码如下:

  1. # 实例化一个将数据聚成2个簇的高斯混合聚类器
  2. gmm = GaussianMixture(2)
  3. # 将数据传给fit函数,fit函数会计算出各个高斯分布的参数和响应系数
  4. gmm.fit(img_reshape)
  5. # 对数据进行聚类,簇标记为0或1(因为gmm对象想要聚成2个簇)
  6. pred = gmm.predict(img_reshape)
  7. # 图省事可以这样,相当于调用了fit之后调用predict
  8. pred = gmm.fit_predict(img_reshape)

编程要求

在右侧编辑器的 begin-end 之间补充代码,你所需要完成的功能是:

  • 读取./step3/image/test.jpg

  • 将读取到的图像分割成 3 个部分。其中簇标记为 0 的部分用黄色表示;簇标记为 1 的部分用蓝色表示;簇标记为 2 的部分用绿色表示;

  • 将分割后的图像保存至./step3/dump/result.jpg

测试说明

只需将分割后的图像保存到正确的位置即可,平台内部会计算你的结果与正确答案的差异程度,差异程度小于 10 视为过关。

预期输出:你的分割结果与正确答案的差异度小于 10!


开始你的任务吧,祝你成功!

from PIL import Image
import numpy as np
from sklearn.mixture import GaussianMixture

#******** Begin *********#
im = Image.open('./step3/image/test.jpg')
img = np.array(im)
img_reshape = img.reshape(-1,3)
gmm = GaussianMixture(n_components=3,covariance_type='full')
gmm.fit(img_reshape)
pred = gmm.predict(img_reshape)
img_reshape[pred==0,:] = [255,255,0]
img_reshape[pred==1,:] = [0,0,255]
img_reshape[pred==2,:] = [0,255,0]
im = Image.fromarray(img.astype('uint8'))
im.save('./step3/dump/result.jpg')
#********* End *********#

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
运用K-means算法进行图像分割, K-means算法是很典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。 k个初始类聚类中心点的选取对聚类结果具有较大的 公式 公式 影响,因为在该算法第一步中是随机的选取任意k个对象作为初始聚类的中心,初始地代表一个簇。该算法在每次迭代中对数据集中剩余的每个对象,根据其与各个簇中心的距离将每个对象重新赋给最近的簇。当考察完所有数据对象后,一次迭代运算完成,新的聚类中心被计算出来。如果在一次迭代前后,J的值没有发生变化,说明算法已经收敛。 算法过程如下: 1)从N个文档随机选取K个文档作为质心 2)对剩余的每个文档测量其到每个质心的距离,并把它归到最近的质心的类 3)重新计算已经得到的各个类的质心 4)迭代2~3步直至新的质心与原质心相等或小于指定阈值,算法结束 具体如下: 输入:k, data[n]; (1) 选择k个初始中心点,例如c[0]=data[0],…c[k-1]=data[k-1]; (2) 对于data[0]….data[n],分别与c[0]…c[k-1]比较,假定与c[i]差值最少,就标记为i; (3) 对于所有标记为i点,重新计算c[i]={ 所有标记为i的data[j]之和}/标记为i的个数; (4) 重复(2)(3),直到所有c[i]值的变化小于给定阈值。 折叠工作原理 K-MEANS算法的工作原理及流程 K-MEANS算法 输入:聚类个数k,以及包含 n个数据对象的数据库。 输出:满足方差最小标准的k个聚类

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

畜牧当道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值