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