最近在寫一個聚類的專利。聚類是通過構建適合的函數,去找到大數據內部分佈結構特點的一種手段,通過不同的聚類算法構建的相似性度量標準,聚類算法的直接目的是將相似的數據歸爲同一簇。圖像數據包含了豐富的信息,單個樣本維度高。
做一個簡單的研究:
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
結果如下: