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

結果如下:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章