【python计算机视觉编程——图像聚类】

news2024/12/23 19:53:01

python计算机视觉编程——图像聚类

  • 6.图像聚类
      • 6.1 K-means聚类
      • 6.1.2 图像聚类
      • 6.1.3 在主成分上可视化图像
      • 6.1.4 像素聚类
    • 6.2 层次聚类
    • 6.3 谱聚类

6.图像聚类

6.1 K-means聚类

from scipy.cluster.vq import *
import numpy as np
from pylab import *
matplotlib.rcParams['font.family'] = 'sans-serif'
matplotlib.rcParams['font.sans-serif'] = ['SimHei']  # 黑体字体
matplotlib.rcParams['axes.unicode_minus'] =False  # 显示负号
class1 = 1.5 * np.random.randn(100,2)  # 生成一个100x2的数组,每个元素都是从均值为0、标准差为1.5的正态分布中抽取的。
class2 = np.random.randn(100,2)+np.array([5,5])  # 生成一个100x2的数组,每个元素都是从均值为5、标准差为1的正态分布中抽取的,并且整体上移[5, 5]。
features=np.vstack((class1,class2))  # 将这两个生成的类别数据合并成一个200x2的数组。
# 对features数据集进行k-均值聚类,指定为2个簇。返回簇的质心和每个簇的方差。
# 是一个形状为(2, 2)的数组,其中每一行表示一个簇的质心(中心点)。由于指定了2个簇,centroids会有2行,每行包含2个值(对应每个簇的二维坐标)。
# variance:表示数据点到其对应簇的质心的总方差。方差越小,说明数据点与质心的距离越近,聚类效果越好。
centroids,variance=kmeans(features,2)

在这里插入图片描述

# 将每个数据点分配给离其最近的质心,并计算每个点到其分配的质心的距离。code包含簇的分配信息,distance包含距离。
code,distance=vq(features,centroids)
figure()
ndx=where(code==0)[0]  #找到被分配到簇 0 的数据点的索引。
plot(features[ndx,0],features[ndx,1],'*')
ndx=where(code==1)[0]
plot(features[ndx,0],features[ndx,1],'r.')
plot(centroids[:,0],centroids[:,1],'go')
show()

在这里插入图片描述

6.1.2 图像聚类

import pickle
from scipy.cluster.vq import *
import os
from PIL import Image
from pylab import *
def get_imlist(path):        
    return [os.path.join(path,f) for f in os.listdir(path) if f.endswith('.jpg')]
imlist=get_imlist(r'D:\pyFile\Python计算机视觉编程\data\selectedfontimages\a_selected_thumbs')
imnbr=len(imlist)

with open('a_pca_modes.pkl','rb') as f:
    immean=pickle.load(f,encoding='iso-8859-1')  # 从文件中加载图像的均值向量
    V=pickle.load(f,encoding='iso-8859-1')  # 从文件中加载PCA变换的特征向量(主成分)

    
# 将每个图像打开并展平为一维向量,然后将这些向量堆叠成一个矩阵。每行代表一张图像的特征向量
immatrix=np.array([array(Image.open(im)).flatten()
                  for im in imlist],'f')


# 将图像均值向量展平为一维向量
immean=immean.flatten()
# 将每张图像从原始空间投影到PCA空间。V[:40](取前40行)表示使用前40个主成分来进行投影
# dot(V[:40],immatrix[i]-immean).shape  :  (40,)
# imnbr:66
projected=np.array([dot(V[:40],immatrix[i]-immean) for i in range(imnbr)])
# projected.shape:(66, 40)


# 白化处理是一种数据预处理技术,旨在将数据的特征转换为具有相同方差的标准正态分布(均值为0,方差为1)
projected=whiten(projected)  # 对投影后的数据进行白化处理,使得每个特征的方差为1
centroids,distortion=kmeans(projected,4)

code,distance=vq(projected,centroids)
for k in range(4):
    ind=where(code==k)[0]
    figure()
    gray()
    for i in range(minimum(len(ind),40)): # 对簇中的前 40 张图像进行迭代(如果簇中的图像少于 40 张,则显示所有图像)
        subplot(4,10,i+1)
        imshow(immatrix[ind[i]].reshape((25,25)))
        axis('off')
show()

类1

在这里插入图片描述

类2

在这里插入图片描述

类3

在这里插入图片描述

类4

在这里插入图片描述

6.1.3 在主成分上可视化图像

上述代码中的一句修改如下,将图像投影到两个主成分上,使用 PCA 的前两个主成分(V[[0,2]])将每张图像从原始空间投影到降维后的空间。每个图像的投影是减去均值后的特征向量与主成分的点积。

projected=np.array([dot(V[:2],immatrix[i]-immean) for i in range(imnbr)])

类1
在这里插入图片描述

类2

在这里插入图片描述

类3

在这里插入图片描述

类4

在这里插入图片描述

from PIL import Image,ImageDraw
h,w=1200,1200  # 定义背景图像的高度和宽度为 1200 像素

img=Image.new('RGB',(w,h),(255,255,255))  # 创建一个新的 RGB 图像,背景颜色为白色
draw=ImageDraw.Draw(img)  #创建一个可以在图像上绘制的 ImageDraw 对象

draw.line((0,h/2,w,h/2),fill=(255,0,0))  # 在图像的中间绘制一条水平红线
draw.line((w/2,0,w/2,h),fill=(255,0,0))  # 在图像的中间绘制一条垂直红线

scale=abs(projected).max(0)  # 计算 PCA 投影数据的绝对值的最大值,以用于数据的缩放
# 将 PCA 投影数据按比例缩放,并将其平移到图像的中心。floor 函数将坐标值向下取整,以便图像能正确地绘制在整数像素上
scaled=floor(array([(p/scale)*(w/2-20,h/2-20)+(w/2,h/2) for p in projected]))

for i in range(imnbr):
    nodeim=Image.open(imlist[i])
    nodeim.thumbnail((25,25))
    ns=nodeim.size
    
#    将图像粘贴到背景图的指定位置。位置根据图像的缩放和 PCA 投影位置计算得出
    img.paste(nodeim,(int(scaled[i][0]-ns[0]//2),int(scaled[i][1]-ns[1]//2),
                      int(scaled[i][0]+ns[0]//2+1),int(scaled[i][1]+ns[1]//2+1)))

imshow(img)
img.save('pca_font.jpg')

在这里插入图片描述

6.1.4 像素聚类

from scipy.cluster.vq import *
steps=50
im=array(Image.open('sun.jpg'))
figure()
subplot(121)
imshow(im)
dx=im.shape[0]/steps
dy=im.shape[1]/steps

features=[]
for x in range(steps):
    for y in range(steps):
        R=mean(im[int(x*dx):int((x+1)*dx),int(y*dy):int((y+1)*dy),0])
        G=mean(im[int(x*dx):int((x+1)*dx),int(y*dy):int((y+1)*dy),1])
        B=mean(im[int(x*dx):int((x+1)*dx),int(y*dy):int((y+1)*dy),2])
        features.append([R,G,B])
features=array(features,'f')

centroids,variance=kmeans(features,3)
code,distance=vq(features,centroids)

codeim=code.reshape(steps,steps)
codeim=np.array(Image.fromarray(codeim).resize(im.shape[:2]))

subplot(122)
imshow(codeim)
show()

在这里插入图片描述

6.2 层次聚类

from itertools import combinations
import numpy as np
class ClusterNode(object):
    def __init__(self,vec,left,right,distance=0.0,count=1):
        self.left=left
        self.right=right
        self.vec=vec
        self.distance=distance
        self.count=count
    def extract_clusters(self,dist):
        """ 从层次聚类树中提取距离小于 dist 的子树簇群列表 """
        if self.distance < dist: 
            return [self]
        return self.left.extract_clusters(dist) + self.right.extract_clusters(dist)
    def get_cluster_elements(self):
        """ 在聚类子树中返回元素的 id """
        return self.left.get_cluster_elements() + self.right.get_cluster_elements()
    def get_height(self):
        """ 返回节点的高度,高度是各分支的和 """
        return self.left.get_height() + self.right.get_height()
    def get_depth(self):
        """ 返回节点的深度,深度是每个子节点取最大再加上它的自身距离 """
        return max(self.left.get_depth(), self.right.get_depth()) + self.distance
class ClusterLeafNode(object):
    def __init__(self,vec,id):
        self.vec = vec
        self.id = id
    def extract_clusters(self,dist):
        return [self]
    def get_cluster_elements(self):
        return [self.id]
    def get_height(self):
        return 1
    def get_depth(self):
        return 0
    def L2dist(v1,v2):
        return np.sqrt(sum((v1-v2)**2))
    def L1dist(v1,v2):
        return sum(abs(v1-v2))
    def hcluster(features,distfcn=L2dist):
        """ 用层次聚类对行特征进行聚类 """
        # 用于保存计算出的距离
        distances = {}
        # 每行初始化为一个簇
        node = [ClusterLeafNode(np.array(f),id=i) for i,f in enumerate(features)]
        while len(node)>1:
            closest = float('Inf')
            # 遍历每对,寻找最小距离
            for ni,nj in combinations(node,2):
                if (ni,nj) not in distances:
                    distances[ni,nj] = distfcn(ni.vec,nj.vec)
                d = distances[ni,nj]
                if d<closest:
                    closest = d
                    lowestpair = (ni,nj)
            ni,nj = lowestpair
            # 对两个簇求平均
            new_vec = (ni.vec + nj.vec) / 2.0
            # 创建新的节点
            new_node = ClusterNode(new_vec,left=ni,right=nj,distance=closest)
            node.remove(ni)
            node.remove(nj)
            node.append(new_node)
        return node[0]
class1=1.5*np.random.randn(100,2)
class2=np.random.randn(100,2)+np.array([5,5])
features=np.vstack((class1,class2))
tree=ClusterLeafNode.hcluster(features)
clusters=tree.extract_clusters(5)
print('number of clusters',len(clusters))
for c in clusters:
    print(c.get_cluster_elements())

在这里插入图片描述

import os
from PIL import Image,ImageDraw
from pylab import *
path=r'D:\pyFile\Python计算机视觉编程\data\sunsets\flickr-sunsets-small'
imlist=[os.path.join(path,f) for f in os.listdir(path) if f.endswith('.jpg')]

features=np.zeros([len(imlist),512])
for i,f in enumerate(imlist):
    im=np.array(Image.open(f))
    
    h,edges=np.histogramdd(im.reshape(-1,3),8,density=True,range=[(0,255),(0,255),(0,255)])
    features[i]=h.flatten()
tree=ClusterLeafNode.hcluster(features)
def draw_dendrogram(node,imlist,filename='clusters.jpg'):
    rows=node.get_height()*20
    cols=1200
    s=float(cols-150)/node.get_depth()
    
    im=Image.new('RGB',(cols,rows),(255,255,255))
    draw =ImageDraw.Draw(im)
    
    draw.line((0,rows/2,20,rows/2),fill=(0,0,0))
    
    node.draw(draw,20,(rows/2),s,imlist,im)
    im.save(filename)
    im.show()

添加draw函数到ClusterNode类中

    def draw(self,draw,x,y,s,imlist,im):
        h1=int(self.left.get_height()*20/2)
        h2=int(self.right.get_height()*20/2)
        top=y-(h1+h2)
        bottom=y+(h1+h2)

        draw.line((x,top+h1,x,bottom-h2),fill=(0,0,0))

        l1=self.distance*s
        draw.line((x,top+h1,x+l1,top+h1),fill=(0,0,0))
        draw.line((x,bottom-h2,x+l1,bottom-h2),fill=(0,0,0))

        self.left.draw(draw,x+l1,top+h1,s,imlist,im)
        self.right.draw(draw,x+l1,bottom-h2,s,imlist,im)

添加draw函数到ClusterLeafNode中

    def draw(self,draw,x,y,s,imlist,im):
        nodeim=Image.open(imlist[self.id])
        nodeim.thumbnail([20,20])
        ns=nodeim.size
        im.paste(nodeim,[int(x),int(y-ns[1]//2),int(x+ns[0]),int(y+ns[1]-ns[1]//2)])
draw_dendrogram(tree,imlist,filename='sunset.pdf')

在这里插入图片描述

clusters=tree.extract_clusters(0.23*tree.distance)

for c in clusters:
    elements=c.get_cluster_elements()
    nbr_elements=len(elements)
    if nbr_elements>3:
        figure()
        for p in range(minimum(nbr_elements,20)):
            subplot(4,5,p+1)
            im=array(Image.open(imlist[elements[p]]))
            imshow(im)
            axis('off')
show()

在这里插入图片描述

在这里插入图片描述

6.3 谱聚类

from scipy.cluster.vq import *
import pickle
import os
from PIL import Image
from pylab import *
imlist=get_imlist(r'D:\pyFile\Python计算机视觉编程\data\selectedfontimages\a_selected_thumbs')
imnbr=len(imlist)

with open('a_pca_modes.pkl','rb') as f:
    immean=pickle.load(f,encoding='iso-8859-1')
    V=pickle.load(f,encoding='iso-8859-1')

immatrix=np.array([array(Image.open(im)).flatten()
                  for im in imlist],'f')

immean=immean.flatten()
projected=np.array([dot(V[:40],immatrix[i]-immean) for i in range(imnbr)])

projected=whiten(projected)
centroids,distortion=kmeans(projected,4)

code,distance=vq(projected,centroids)
n=len(projected)
S=array([[np.sqrt(sum((projected[i]-projected[j])**2))
         for i in range(n)] for j in range(n)],'f')
rowsum=sum(S,axis=0)
D=diag(1/sqrt(rowsum))
I=identity(n)
L=I-dot(D,dot(S,D))

U,sigma,V=linalg.svd(L)

k=5

features=array(V[:k]).T
features=whiten(features)
centroids,distortion=kmeans(features,k)
code,distance=vq(features,centroids)

for c in range(k):
    ind=where(code==c)[0]
    figure()
    for i in range(minimum(len(ind),39)):
#         print(imlist[ind[i]])
        im=Image.open(imlist[ind[i]])
        subplot(4,10,i+1)
        imshow(array(im))
        axis('equal')
        axis('off')
show()

类1

在这里插入图片描述

类2

在这里插入图片描述

类3

在这里插入图片描述

类4

在这里插入图片描述

类5

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2095096.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第二篇——勾股定理:为什么在西方教毕达哥拉斯定理?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 数学大厦的建立以及与自然科学的逻辑关系&#xff0c;以及他们的边界在这…

sql-libs第三关详细解答

首先看看and 12会不会正常显示 结果正常显示&#xff0c;说明存在引号闭合 加了一个引号&#xff0c;发现报错信息中还存在括号&#xff0c;说明sql语句中有括号&#xff0c;那我们还要闭合括号 现在就好了&#xff0c;and 11正常&#xff0c;and 12不正常&#xff0c;那就开始…

常用高性能架构模式

《从0开始学架构》里讲述了常用的高性能架构模式&#xff0c;这里面很多大家可能也都用过了&#xff0c;我应该也写过相关的技术文章。正好按照书里的思路重新梳理一次。 一、读写分离 读写分离的基本原理是将数据库读写操作分散到不同的节点上 感想&#xff1a; 读写分离应…

Go入门:gin框架极速搭建图书管理系统

Go入门:gin框架极速搭建图书管理系统 前言 本项目适合 Golang 初学者,通过简单的项目实践来加深对 Golang 的基本语法和 Web 开发的理解。 项目源码请私信,欢迎前往博主博客torna.top免费查看。 项目结构 D:. ├─ go.mod ├─ go.sum │ ├─ cmd │ └─ main │ …

Jenkins配置使用LDAP的用户和密码登录

# 检查配置文件是否正确 [rootlocalhost schema]# slaptest -u 62c6aafe ldif_read_file: checksum error on "/etc/openldap/slapd.d/cnconfig/olcDatabase{1}monitor.ldif" 62c6aafe ldif_read_file: checksum error on "/etc/openldap/slapd.d/cnconfig/olcD…

Java注解和JDK新特性

1. 注解 1.1. 认识注解 Annotation&#xff1a;JDK1.5新提供的技术 编译检查&#xff1a;比如SuppressWarnings, Deprecated和Override都具有编译检查的作用替代配置文件&#xff1a;使用反射来读取注解的信息 注解就是代码里的特殊标记&#xff0c;用于替代配置文件&#…

四大集合之Set

一、Set基础知识 1. Set集合 1.1 HashSet Set集合区别于其他三大集合的重要特性就是元素具有唯一性&#xff0c;南友们记不住这个特性的话&#xff0c;有个易记的方法。Set集合为什么要叫Set呢&#xff1f;因为Set集合的命名取自于我们小学数学里的集合论&#xff08;Set Th…

SPI(硬件协议)

1 SPI硬件外设协议 2 SPI框图 3 硬件SPI数据收发流程 1 发送数据&#xff0c;同时接收数据&#xff0c;相互配合&#xff0c;可以实现数据流不间断 2 全双工SPI&#xff0c;发送和接收数据寄存器分开&#xff0c;可以同时进行 4 spi传输框图 1 速度快 2 速度慢&#xff0c;容…

软考中项拿证利器:系统集成项目管理工程师(第3版)一站通关

指尖疯编著的《系统集成项目管理工程师&#xff08;适用第3版大纲&#xff09;一站通关》目前现货已经上线各大电商平台&#xff0c;您可以在任一电商搜索《系统集成项目管理工程师&#xff08;适用第3版大纲&#xff09;一站通关》即刻找到。 出版中项一站通关完全是机缘巧合&…

Nginx: 性能优化之提升CPU效率以及TCP的三次握手和四次挥手

提升利用CPU的效率 1 &#xff09;CPU的调度机制 现在来看下 linux中 CPU的一个调度机制 假设现在系统上有只有一颗CPU&#xff0c;而linux系统是一个多任务的一个操作系统 它允许我们各个不同的用户允许在同一个操作系统上执行很多个进程 单核CPU肯定不可能同时去执行这样一…

5.图论.题目2

5.图论.题目2 题目8.字符串接龙9.有向图的完全可达性10.岛屿的周长11.寻找存在的路径12.冗余连接113.冗余连接214.寻宝 题目 8.字符串接龙 题目链接 本题的直观思路如下图所示&#xff1b;但该题有两个问题&#xff1a;1.图中的线是如何连接起来的 2.如何确定起点到终点的最…

《JavaEE进阶》----4.<SpringMVC①简介、基本操作(各种postman请求)>

本篇博客讲解 MVC思想、及Spring MVC&#xff08;是对MVC思想的一种实现&#xff09;。 Spring MVC的基本操作、学习了六个注解 RestController注解 RequestMappering注解 RequestParam注解 RequestBody注解 PathVariable注解 RequestPart注解 MVC View(视图) 指在应⽤程序中…

数据同步的艺术:探索PostgreSQL和Redis的一致性策略

作者&#xff1a;后端小肥肠 &#x1f347; 我写过的文章中的相关代码放到了gitee&#xff0c;地址&#xff1a;xfc-fdw-cloud: 公共解决方案 &#x1f34a; 有疑问可私信或评论区联系我。 &#x1f951; 创作不易未经允许严禁转载。 1. 前言 在当今高度数字化的世界中,应用程…

ACL学习笔记

1.ACL快速配置 需求&#xff1a;拒绝PC 1访问PC 3 &#xff08;1&#xff09;配置PC PC 1: PC 2: PC 3: &#xff08;2&#xff09;配置R1的接口IP信息 sys sysname R1 undo info-center enable interface GigabitEthernet0/0/0 ip address 192.168.1.1 255.255.255.0 qui…

超声波智能水表多少钱一个?

超声波智能水表的价格因品牌、功能、规格等因素而异&#xff0c;就拿深圳合众致达科技有限公司智能水电表厂家的超声波智能水表DN15口径产品举例&#xff0c;价格为399元起。具体价格需根据实际需求来确定。 一、影响价格的主要因素 -技术含量&#xff1a;具备远程数据传输、…

DSOJ-id12

1.保留几位小数 #include <iostream>#include <iomanip> //必须包含这个头文件using namespace std;void main( ){ double a 3.141596;cout<<fixed<<setprecision(3)<<a<<endl; //输出小数点后3位 2. 使用了未初始化的局部变量 Point* …

如何使用小乌龟清除认证缓存、还原版本、定位及常用开发工具集成

&#x1f600;前言 本篇博文是关于如何使用小乌龟清除认证缓存、还原版本、定位及常用开发工具集成&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大…

openGuass之CTE Reuse

一. 前言 ​ CTE 是指with的公共表达式&#xff0c;如下所示是个CTE样例&#xff1a; ​ CTE表达式往往在同一条sql中多次被重复引用&#xff0c;如上图所示的cte被引用了两次&#xff08;c1 和 c2&#xff09;&#xff0c;我们称为2个CTE实例。 ​ 本文只要…

Windows系统Nginx下载安装配置 运行错误处理

Nginx是一款轻量级的web 服务器/反向代理 服务器。本篇文章主要是nginx的下载安装&#xff0c;处理运行中遇到的问题&#xff0c;配置反向代理。主要分为两部分&#xff1a;下载安装和配置。 目录 1.下载安装 2.nginx配置反向代理 1.下载安装 nginx官网&#xff1a;nginx: …

新160个crackme -044-tsrh-crackme

运行分析 提示去除NAG 不去除NAG也能进入主窗口&#xff0c;需要破解Name和Serial PE分析 ASM程序&#xff0c;32位&#xff0c;壳未知 去除NAG ida搜索字符串&#xff0c;发现NAG弹窗标题字符串&#xff0c;双击进入函数 找到了messagebox&#xff0c;即NAG位置00401079 打开x…