数据分析实战 45 讲
陈旸
清华大学计算机博士
123928 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 49 讲
第二模块:数据分析算法篇 (20讲)
第四模块:数据分析工作篇 (2讲)
数据分析实战 45 讲
15
15
1.0x
00:00/00:00
登录|注册

27丨K-Means(下):如何使用K-Means对图像进行分割?

对应原图的显示
分割成16个部分的颜色设置
可视化聚类结果
使用K-Means进行聚类
数据加载与规范化
聚类流程
其他图像分割方法
聚类特性与图像分割的关系
利用图像信息进行划分
baby.jpg的分割
体会分享
图像尺寸对K-Means运行时间的影响
工具包比较
图像处理工具的使用
数据规范化工具
K-Means聚类工具
微信开屏封面分割
图像分割
对亚洲球队进行聚类
总结
聚类实战
原理
K-Means

该思维导图由 AI 生成,仅供参考

上节课,我讲解了 K-Means 的原理,并且用 K-Means 对 20 支亚洲球队进行了聚类,分成 3 个梯队。今天我们继续用 K-Means 进行聚类的实战。聚类的一个常用场景就是对图像进行分割。
图像分割就是利用图像自身的信息,比如颜色、纹理、形状等特征进行划分,将图像分割成不同的区域,划分出来的每个区域就相当于是对图像中的像素进行了聚类。单个区域内的像素之间的相似度大,不同区域间的像素差异性大。这个特性正好符合聚类的特性,所以你可以把图像分割看成是将图像中的信息进行聚类。当然聚类只是分割图像的一种方式,除了聚类,我们还可以基于图像颜色的阈值进行分割,或者基于图像边缘的信息进行分割等。

将微信开屏封面进行分割

上节课,我讲了 sklearn 工具包中的 K-Means 算法使用,我们现在用 K-Means 算法对微信页面进行分割。微信开屏图如下所示:
我们先设定下聚类的流程,聚类的流程和分类差不多,如图所示:
在准备阶段里,我们需要对数据进行加载。因为处理的是图像信息,我们除了要获取图像数据以外,还需要获取图像的尺寸和通道数,然后基于图像中每个通道的数值进行数据规范化。这里我们需要定义个函数 load_data,来帮我们进行图像加载和数据规范化。代码如下:
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文介绍了如何使用K-Means算法对图像进行分割。文章首先介绍了图像分割的概念,即利用图像的颜色、纹理、形状等特征进行划分,将图像分割成不同的区域,相当于对图像中的像素进行聚类。接着,详细介绍了对图像进行分割的实际操作步骤,包括加载图像、数据规范化以及使用K-Means算法进行聚类。文章还介绍了如何使用skimage工具包将聚类标识矩阵转化为不同颜色的矩阵,以及如何将每个簇的点的RGB值设置为该簇质心点的RGB值,从而得到对应的原图。通过这些操作,读者可以快速了解如何利用K-Means算法对图像进行分割,并对聚类结果进行可视化和原图像的还原。此外,文章还提到了K-Means聚类的缺陷和对图像进行读写的具体代码。总的来说,本文内容详实,操作步骤清晰,适合对图像分割感兴趣的读者阅读学习。文章中涉及的工具包较多,读者在练习时需要多加体会。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《数据分析实战 45 讲》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(19)

  • 最新
  • 精选
  • 淡魂
    请问老师。自己写Min-Max规范化公式的时候为什么不直接除以255,这样得到的数据也是在[0,1]之间,是因为那个值不可以为0吗?什么原因呢?

    编辑回复: 一个不错的问题,实际上都是一样的,只要能划分到[0,1]空间内,而且在变化的过程中不存在分母为0的情况即可。因为我们是缩放一个固定的尺寸,所以除以255,反变换的时候乘以255是没有问题的。你也可以自己修改运行下,同样可以得到结果。

    2019-02-13
    14
  • 深白浅黑
    老师下面函数中,最后的参数代表什么意思?手册上显示的是n_feature,但没说具体的意义,不是很明白。 c1 = kmeans.cluster_centers_[label[x, y], 2] c2 = kmeans.cluster_centers_[label[x, y], 1] c3 = kmeans.cluster_centers_[label[x, y], 0]

    编辑回复: 一个很好的问题,实际上label[x,y]是得到当前点的类别,kmeans.cluster_centers_可以得到某类别的数值,因为图像JPG是3个通道,所以通过kmeans.cluster_centers_[label[x, y], 0],kmeans.cluster_centers_[label[x, y], 1],kmeans.cluster_centers_[label[x, y], 2]可以获得这3个通道的数值,然后将这些数值作为当前点的数值。因为当前点已经被划分到了这个类别,所以数值是一致的。这样如果原来图像中有N种颜色,现在聚类数是16,相当于每个点的颜色值就变成了其中一个类别的颜色值,也就是变成了16种颜色,完成了聚类(降维)。

    2019-02-19
    2
    7
  • cua
    为什么会出现这个错误呢ValueError: too many values to unpack (expected 3)

    作者回复: 参数过多?

    2019-02-28
    4
    4
  • mickey
    # -*- coding: utf-8 -*- # 使用K-means对图像进行聚类,显示分割标识的可视化 import numpy as np import PIL.Image as image from sklearn.cluster import KMeans from sklearn import preprocessing from skimage import color # 加载图像,并对数据进行规范化 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): # 得到点(x,y)的三个通道值 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,以及图像尺寸 img, width, height = load_data('./baby2.jpg') # 用K-Means对图像进行16聚类 kmeans =KMeans(n_clusters=16) kmeans.fit(img) label = kmeans.predict(img) # 将图像聚类结果,转化成图像尺寸的矩阵 label = label.reshape([width, height]) # 将聚类标识矩阵转化为不同颜色的矩阵 label_color = (color.label2rgb(label)*255).astype(np.uint8) label_color = label_color.transpose(1,0,2) images = image.fromarray(label_color) images.save('baby_16.jpg')

    作者回复: Good Job

    2019-02-28
    2
  • third
    问题:已经使用mm进行数据拟合转换了,为何还要使用np.mat()转换呢?作用在哪里?方便后面使用np.uint8吗? 注意:实战的时候,保存图片为jpg格式 如果是png格式的话,会出现4个值,导致赋值错误,(R, G, B, A) import PIL.Image as image import numpy as np import pandas as pd #载入数据 def load_data(file): with open(file,'rb') as f: 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]) #进行mm规范化 from sklearn.preprocessing import MinMaxScaler mm=MinMaxScaler() data=mm.fit_transform(data) return np.mat(data),width,height data,width,height=load_data('./27/baby.jpg') #进行聚类 from sklearn.cluster import KMeans kmeans=KMeans(n_clusters=16) label=kmeans.fit_predict(data) #可视化 #转换成图像矩阵 label=label.reshape([width,height]) #生成一张新图片 # pic_1=image.new("L",(width,height)) # #把像素信息写入 # #方法1写入灰度值 # for x in range(width): # for y in range(height): # #按照分类确定灰度值 # pic_1.putpixel((x,y),int(label[x][y]*256/16)) # pic_1.save('./27/baby.jpg') # #方法2 # # 使用模组,将表示矩阵转换为各种颜色的矩阵 # #使用label2rgb(label)*255转化,再把矩阵转化为unit8类型,无符号整数 # from skimage import color # label_color=(color.label2rgb(label)*255).astype(np.uint8) # #似乎都需要进行颠倒处理 # label_color=label_color.transpose(1,0,2) # #使用fromarray把矩阵生成图片 # images=image.fromarray(label_color) # images.save('./27/baby_color_2.jpg') #方法3获取对应原图 #创建新的图片 imges1=image.new('RGB',(width,height)) #写入图片 for x in range(width): for y in range(height): #吧范围为0-255的数值投射到1-256 #获取第一列即r的值 c1=kmeans.cluster_centers_[label[x,y],0] c2 = kmeans.cluster_centers_[label[x, y], 1] c3 = kmeans.cluster_centers_[label[x, y], 2] imges1.putpixel((x,y),(int(c1*256)-1,int(c2*256)-1,int(c3*256)-1)) imges1.save('./27/baby_yasuo.jpg')

    编辑回复: 不用np.mat()也是OK的,jpg和png通道数确实需要注意。

    2019-02-19
    2
  • Ronnyz
    import numpy as np import PIL.Image as Image from sklearn import preprocessing from sklearn.cluster import KMeans from skimage import color #加载图片,并进行规范化 def load_data(filepath): #读图片 f=open(filepath,'rb') #获取图片像素 img=Image.open(f) #获取图片尺寸和像素矩阵 width,height =img.size data=[] for x in range(width): for y in range(height): #得到点(x,y)的R,G,B通道值 r,g,b=img.getpixel((x,y)) data.append([r,g,b]) f.close() #采用min-max规范化 mm=preprocessing.MinMaxScaler() print('原位置列表:') print(type(data)) print(len(data)) data=mm.fit_transform(data) return np.mat(data),width,height #加载图片,得到规范化结果 img,width,height = load_data('./kmeans-master/baby.jpg') print('\n规范化的像素矩阵:') print(type(img)) print(img.shape) #用K-Means进行16聚类 kmeans = KMeans(n_clusters=16) label=kmeans.fit_predict(img) #将图像结果,转化成图像尺寸矩阵 label=label.reshape([width,height]) #创建颜色表示矩阵图 label_color = (color.label2rgb(label)*255).astype(np.uint8) label_color=label_color.transpose(1,0,2) print('\n像素颜色矩阵:') print(label_color.shape) images=Image.fromarray(label_color) images.save('./kmeans-master/baby_mark.jpg') #创建新图像,保存聚类压缩之后的结果 img=Image.new('RGB',(width,height)) for x in range(width): for y in range(height): r1=kmeans.cluster_centers_[label[x, y],0] g1=kmeans.cluster_centers_[label[x, y], 1] b1=kmeans.cluster_centers_[label[x, y], 2] img.putpixel((x,y),(int(r1*256)-1,int(g1*256)-1,int(b1*256)-1)) img.save('./kmeans-master/baby_new.jpg')

    作者回复: 不错 加油Ronnyz

    2019-11-18
    1
  • §mc²ompleXWr
    为什么要用np.mat(data)?? 我用array()跑出来的结果完全是一样的啊。。

    作者回复: np.mat()函数是将输入解释为矩阵,指的是二维矩阵。 np.array()函数是创建一个数组,它可以是一维、二维或更高维。 当数组为二维时,和矩阵等价,所以你会觉得结果看起来一样。

    2020-07-12
  • 宋晓明
    极客时间 pc界面终于改了。。之前的界面找某篇文章费死个劲

    作者回复: 嗯嗯 加油~

    2019-03-12
  • Rickie
    老师好,想请问下您聚类后得到的那张灰度图像有其他的设置吗?我使用跟您一样的代码,最后生成的图尺寸非常小,且一些细节并没有分类正确...不知道是什么原因?

    编辑回复: 可以找运营加到微信群里,我帮你看看。

    2019-02-14
  • mickey
    import PIL.Image as image 导入的是pillow包,而非pil包。 pil包不支持64位,但是有pillow包代替用。
    2019-02-28
    1
    18
收起评论
显示
设置
留言
19
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部