Python计算机视觉

您所在的位置:网站首页 Python层次聚类分析图片很小怎么办 Python计算机视觉

Python计算机视觉

2024-07-13 15:31| 来源: 网络整理| 查看: 265

文章目录 引言6.1 K-means聚类6.1.1 SciPy聚类包6.1.2 图像聚类6.1.3 在主成分上可视化图像6.1.4 像素聚类 6.2 谱聚类

引言

本章将介绍聚类方法,用图像进行聚类,寻找相似的图像组。聚类可用于识别、划分图像数据集,组织与导航。此外,会对聚类后的图像进行相似性的可视化。

6.1 K-means聚类

K-means是一种将输入数据划分为K个簇的简单聚类算法,反复提炼初始评估的类中心,步骤如下:

随机方式初始化类中心 u i , i ∈ [ 1 , k ] u_i,i\in [1,k] ui​,i∈[1,k];将每个数据点归并到离它距离最近的类中心所属类 c i c_i ci​;对所有属于该类的数据点求平均,将平均值作为心的 u i u_i ui​;重复步骤2、3,直到收敛;

K-means聚类算法的意义在于试图使类内总方差最小:

V = ∑ i = 1 k ∑ x j ∈ c i ( x i − μ i ) 2 V = \sum _{i=1} ^{k} \sum_{x_j \in c_i} (x_i-\mu_i)^2 V=i=1∑k​xj​∈ci​∑​(xi​−μi​)2

注:

为了避免初始化类中心没选取好初值所造成的影响,该算法通常会初始化不同的类中心进行多次运算,然后选择方差最小的结果。K-means算法最大的缺陷使必须预先设定聚类数K,选择不恰当会导致聚类结果很差。 6.1.1 SciPy聚类包

SciPy包中有直接实现K-means的方法,下面的代码时实现过程:

生成二维正态分布数据(两类),用k=2进行聚类

from numpy import * from scipy.cluster.vq import * class1 = 1.5*random.randn(100,2) class2 = random.randn(100,2)+array([5,5]) features = vstack((class1,class2)) centroids,variance = kmeans(features,2)

但返回的方差并不是我们真正需要的,用SciPy包中的矢量量化函数对每个数据点进行归类。

code是分类号,K=2,所以被分为1和0,distance是点离类中心的距离。

code,distance = vq(features,centroids)

将其可视化,我们画出数据点和最终的聚类中心。

from pylab import * figure(figsize=(10,10)) ndx = where(code==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') axis('off') show()

在这里插入图片描述

6.1.2 图像聚类

用K-means对字体图像进行聚类,获取66幅字体数据集,并且利用之前计算过的pca主成分进行投影,用投影系数作为每幅图像的向量描述符,用下面的方法进行聚类。

import imtools import pickle from scipy.cluster.vq import * from PIL import Image from numpy import * from pylab import * # 获取 selected-fontimages 文件下图像文件名,并保存在列表中 imlist = imtools.get_imlist('selectedfontimages') imnbr = len(imlist) # 载入模型文件 with open('font_pca_modes.pkl','rb') as f: immean = pickle.load(f) V = pickle.load(f) # 创建矩阵,存储所有拉成一组形式后的图像 immatrix = array([array(Image.open(im)).flatten() for im in imlist],'f') immean=immean.flatten() # 投影系数 projected = array([dot(V[:40],immatrix[i]-immean) for i in range(imnbr)]) # 进行 k-means 聚类,作归一化处理 projected = whiten(projected) centroids,distortion = kmeans(projected,4) # 绘制聚类簇 for k in range(4): ind = where(code==k)[0] figure() gray() for i in range(minimum(len(ind),40)): subplot(4,10,i+1) imshow(immatrix[ind[i]].reshape((25,25))) axis('off') show()

第一行是第一类,第二行是第二类,第三行是第三类,之后是第四类。 在这里插入图片描述

6.1.3 在主成分上可视化图像

为了观察上面是如何利用主成分进行聚类的,在一对主成分方向的坐标上可视化这些图像,将图像投影到两个主成分上。

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

V[0,2]分别是第一个和第三个主成分。

使用PIL中的ImageDraw模块进行可视化

from PIL import Image, ImageDraw # 高和宽 h,w = 1200,1200 # 创建一幅白色背景图 img = Image.new('RGB',(w,h),(255,255,255)) draw = ImageDraw.Draw(img) # 绘制坐标轴 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) 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 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)))

在这里插入图片描述 成对主成分上投影的字体图像,第一个和第三个主成分,二维投影后相似的字体图像距离较近。

6.1.4 像素聚类

来看一个对单幅图像中的像素而非全部图像进行聚类的例子。将图像区域或像素合并成有意义的部分称为图像分割。现在,我们仅会在 RGB 三通道的像素值上运用 K-means 进行聚类。

用一个步长为 steps 的方形网格在图像中滑动,每滑一次对网格中图像区域像素求平均值,将其作为新生成的低分辨率图像对应位置 处的像素值,并用 K-means 进行聚类:

from scipy.cluster.vq import * from pylab import * from PIL import Image steps = 50 # 图像被划分成 steps×steps 的区域 im = array(Image.open('pic/empire.jpg')) dx = im.shape[0] // steps dy = im.shape[1] // steps # 计算每个区域的颜色特征 features = [] for x in range(steps): for y in range(steps): R = mean(im[x*dx:(x+1)*dx,y*dy:(y+1)*dy,0]) G = mean(im[x*dx:(x+1)*dx,y*dy:(y+1)*dy,1]) B = mean(im[x*dx:(x+1)*dx,y*dy:(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) figure() subplot(121) imshow(im) axis('off') subplot(122) imshow(codeim) axis('off') show()

50 × 50 , K = 3 50\times50, K=3 50×50,K=3 在这里插入图片描述 100 × 100 , K = 3 100\times100,K=3 100×100,K=3 在这里插入图片描述

6.2 谱聚类

谱聚类和K-means方法截然不同,对于n个元素(n幅图像),相似矩阵是一个 n × n n\times n n×n的矩阵,矩阵的两个元素表示两两之间的相似性分数,谱聚类是由于相似性矩阵的建谱矩阵而得名,对该谱矩阵进行特征分解得到的特征向量可以用于降维,然后聚类。

谱聚类的优点之一是仅需要输入相似性矩阵,采用任意度量方法构建该相似性矩阵,特征或描述子没有类别限制,只要有一个相似性或距离的概念即可。

给定 n × n n\times n n×n的相似矩阵S, s i j s_{ij} sij​为相似性分数(矩阵的元素),可以创建矩阵,称为拉普拉斯矩阵: L = I − D − 0.5 S D − 0.5 L=I-D^{-0.5}SD^{-0.5} L=I−D−0.5SD−0.5

I是单位矩阵,D是对角矩阵,对角元素是S对于应行元素之和, d i = ∑ j s i j d_i=\sum _{j} s_{ij} di​=∑j​sij​,我们要求相似性分数较小且大等于0。

计算L(拉普拉斯矩阵)的特征向量,并使用K个最大特征值对于的k个特征向量,构建出特征向量集,各列是由之前的k个特征向量构成,每一行可看作一个新的特征向量,长度为k(尺度k*k),而新的特征向量可以用K-means方法进行聚类,形成最终的聚类簇。

import imtools import pickle from scipy.cluster.vq import * from PIL import Image from numpy import * from pylab import * import math from scipy import linalg # 获取 selected-fontimages 文件下图像文件名,并保存在列表中 imlist = imtools.get_imlist('selectedfontimages') imnbr = len(imlist) # 载入模型文件 with open('font_pca_modes.pkl','rb') as f: immean = pickle.load(f) V = pickle.load(f) # 创建矩阵,存储所有拉成一组形式后的图像 immatrix = array([array(Image.open(im)).flatten() for im in imlist],'f') immean=immean.flatten() # 投影到前40个主成分上 immean = immean.flatten() projected = array([dot(V[:40], immatrix[i] - immean) for i in range(imnbr)]) n = len(projected) # 欧式距离 S = array([[ sqrt(sum((projected[i]-projected[j])**2)) for i in range(n) ] for j in range(n)], 'f') #拉普拉斯矩阵 # 应行元素之和 rowsum = sum(S,axis = 1) D = diag(1/sqrt(rowsum)) I = identity(n) L = I-dot(D,dot(S,D)) # 计算特征向量 U,sigma,V = linalg.svd(L) k = 5 # 前5个特征向量 features = array(V[:5].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)): im = Image.open(imlist[ind[i]]) subplot(4,10,i+1) imshow(array(im)) axis('equal') axis('off') show()

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3