python:将图片转化为向量并使用K-means进行聚类

最近在写一个聚类的专利。聚类是通过构建适合的函数,去找到大数据内部分布结构特点的一种手段,通过不同的聚类算法构建的相似性度量标准,聚类算法的直接目的是将相似的数据归为同一簇。图像数据包含了丰富的信息,单个样本维度高。

做一个简单的研究:

1.首先把图片直接转化为向量,用于聚类。相当于flatten操作。

2.尝试通过提取图像简单的梯度直方图特征、phash以及vgg16深度特征,用简单的K-means算法进行聚类。

下面是直接用图片进行聚类的代码:

  说明几点:

1.使用:修改路径,修改聚类类别数量、创建按聚类结果分开图像的文件夹并修改其路径。

我是放在了桌面上,设置3类别,创建文件夹的名字分别是1、2、3

2.聚类算法是K-means

3.聚类对象是数据集图片拉直为向量

4.对于输入进行尺寸统一,为50x50,可以自行修改。

#!/usr/bin/python
# coding=utf-8
'''
图片聚类实现
2019.3.1
nansbas
'''

import numpy as np
import os
from PIL import Image
#coding=utf-8
from numpy import *

def loadDataSet(fileName):
    dataMat = []
    fr = open(fileName)
    for line in fr.readlines():
        curLine = line.strip().split('\t')
        fltLine = map(float, curLine)
        dataMat.append(fltLine)
    return dataMat

def distEclud(vecA, vecB):
    return np.sqrt(sum(np.power(vecA - vecB, 2)))

    
def randCent(dataSet, k):
    n = np.shape(dataSet)[1]
    centroids = np.mat(np.zeros((k,n)))
    for j in range(n):
        minJ = min(dataSet[:,j])
        rangeJ = float(max(np.array(dataSet)[:,j]) - minJ)
        centroids[:,j] = minJ + rangeJ * np.random.rand(k,1)
    return centroids
    
def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
    m =np.shape(dataSet)[0]
    clusterAssment = np.mat(np.zeros((m,2)))#create mat to assign data points 
                                      #to a centroid, also holds SE of each point
    centroids = createCent(dataSet, k)
    clusterChanged = True
    while clusterChanged:
        clusterChanged = False
        for i in range(m):#for each data point assign it to the closest centroid
            minDist = np.inf
            minIndex = -1
            for j in range(k):
                distJI = distMeas(centroids[j,:],dataSet[i,:])
                if distJI < minDist:
                    minDist = distJI; minIndex = j
            if clusterAssment[i,0] != minIndex: 
                clusterChanged = True
            clusterAssment[i,:] = minIndex,minDist**2
        #print centroids
        for cent in range(k):#recalculate centroids
            ptsInClust = dataSet[nonzero(clusterAssment[:,0].A==cent)[0]]#get all the point in this cluster
            centroids[cent,:] = mean(ptsInClust, axis=0) #assign centroid to mean 
    return centroids, clusterAssment
    
def show(dataSet, k, centroids, clusterAssment):
    from matplotlib import pyplot as plt  
    numSamples, dim = dataSet.shape  
    mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']  
    for i in xrange(numSamples):  
        markIndex = int(clusterAssment[i, 0])  
        plt.plot(dataSet[i, 0], dataSet[i, 1], mark[markIndex])  
    mark = ['Dr', 'Db', 'Dg', 'Dk', '^b', '+b', 'sb', 'db', '<b', 'pb']  
    for i in range(k):  
        plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize = 12)  
    plt.show()
      
def main():
    dataMat = aa()
    myCentroids, clustAssing= kMeans(dataMat,3)
    show(dataMat, 3, myCentroids, clustAssing)
    print(clustAssing)
    path = 'C:/Users/nansbas/Desktop/julei/'
    imlist = os.listdir(path)
    for i, name in enumerate(imlist):
       print(path+name)
       im = Image.open(path+name)
       im.save('C:/Users/nansbas/Desktop/{}/{}.jpg'.format(int(clustAssing[i,0]),name))

def aa():
 path = 'C:/Users/nan/Desktop/julei/'
 imlist = [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.jpg')]
 # extract feature vector (8 bins per color channel)
 features = zeros([len(imlist), 7500])#特征长度512
 for i, f in enumerate(imlist):
     im = Image.open(f)#Image不是image包,是PIL里的Image模块
     # multi-dimensional histogram
     im = im.resize((50,50))
     im = array(im).flatten()
     features[i] = im.flatten()
 #data = np.loadtxt('K-means_data')
 return features
 
if __name__ == '__main__':
    main()

修改地址就可以使用。关于第2点思路,使用图像特征的聚类在下一篇博客给出了。

https://blog.csdn.net/gusui7202/article/details/88081259

结果如下:

猜你喜欢

转载自blog.csdn.net/gusui7202/article/details/88081072