python——k聚类 图片(图像)聚类程序 + 每类结果保存到对应文件夹

本文介绍了一种改进的图片聚类方法,解决了大数据集下聚类结果难以直观展示的问题。通过将聚类后的图片重塑并保存到对应文件夹,便于进一步处理和观察。适用于大规模图片数据集的机器学习预处理。
  • 前情提要:

    最近由于做机器学习不想手动标签,所以想用聚类的方法让机器自己学习,在网站上找到了很多博主的程序,有其效果但是最后都是将每一类的图片用plot显示出来,把所有的子图拼接在一个界面上。这样在尝试大约800张图片的数据集的时候还凑活,通过加一行程序调整子图之间的宽度和高度,勉强能看清图片内容,以观察聚类的效果。但是一般机器学习的数据集都更大,聚类完想要对每类图片再进行处理的话,原本的程序就不太方便。因此在找到的程序基础上进行了一些变动,以达到其他效果。

  • 具体描述

在这个程序中,主体部分和网上多数的图片聚类程序一致,略有不同的地方是在结尾部分,把flatten后的数组reshape并还原,然后保存为图片格式,每个类别(cluster)都存到一个文件夹内。其中文件夹的生成是用了另外一个小程序(见上篇博文),结尾的保存部分也偷懒没有用循环写(主要是用到的类别少,就直接elif了)

因为看了好多K聚类的程序,不知道我用的主要程序是哪位原创的然后我做了改动,如果有原作者能够认领的话欢迎留言,我会在文章开头补充著名出处的!

整体属于学习过程中的小尝试,有问题还请指出,多交流~

  • 具体代码
# -*- coding: utf-8 -*-
import pickle
import os
import cv2
from pylab import *
from PIL import Image
from scipy.cluster.vq import *
from PCV.tools import pca, imtools
from matplotlib import pyplot as plt

下面是输入部分,主要是路径,手动输入想要的簇数,以及图片尺寸(图片尺寸一定要对,因为我用的图片是单通道而不是RGB三通道的,如果是三通道的话,最后reshape的位置要写三个参数,要不然最后reshape的时候会有无法映射的问题)

PCA_MODE = 'pca_mode.pkl'  # 保存的PCA文件
IMG_TRAIN_LIST = r'E:/d15/frame/try/'  # 用于计算PCA的图片列表
IMG_CLUSTER_LIST = r'E:/d15/frame/try/'  # 用于聚类的图片列表
CLUSTER = 10 # 簇数
IMG_WIDTH, IMG_HEIGHT = 240, 320  # 图片尺寸
print("the number of cluster is:", CLUSTER)
print("****************************************")
# 获取训练图像列表
imlist = imtools.get_imlist(IMG_TRAIN_LIST)     #imlist 为图像路径('E:/d15/frame/try2/1.jpg')构成的列表
namelist = len(imlist)*['']      #使namelist有对应长度

这下面一点本来是想在输出的时候用文件原名输出来着,所以做了个name的分离,但是最后也并没这么搞,直接重命名了。。但是也一起把代码放上来了。。。

for i in range(0,len(imlist)):
    namelist[i]=imlist[i].strip('E:/d15/frame/try2')
# namelist为列表内文件的文件名(加了后缀,如'x_1.jpg')
im = array(Image.open(imlist[0]))  # 打开任意一张图片
# #im为图对应的矩阵

接主要部分:

m, n = im.shape[:2]  # 图片尺寸(要都统一)  #m=240 ,n=320
imnbr = len(imlist)  # 图片数量
print('The number of training images is {}'.format(imnbr))
immatrix = array([array(Image.open(imname)).flatten() for imname in imlist], 'f')  # 拼接所有图片
# 保存均值和主成分
print('Training...')
V, S, immean = pca.pca(immatrix)  # PCA降维
f = open(PCA_MODE, 'wb')
pickle.dump(immean, f)
pickle.dump(V, f)
f.close()
print('{} had saved'.format(PCA_MODE))

# 获取聚类图像列表
imlist = imtools.get_imlist(IMG_CLUSTER_LIST)
imnbr = len(imlist)
print('The number of clustering images is {}'.format(imnbr)
# 加载主成分
with open(PCA_MODE, 'rb') as f:
    immean = pickle.load(f)
    V = pickle.load(f)
print('{} had loaded'.format(PCA_MODE))

接下来是我做了改动的主要部分:
原程序在这个部分是reshape后加了图的坐标、大小、像素,子图的参数,然后show()
由于我最近一次用了9000张图片做了聚类,这样显示之后每一张都是看不清的,所以输出到文件夹内。
其中,在输出部分往下三四行的这句:

array2=(immatrix[ind[i]].reshape((240,320)))

要注意,我这里为了顺手就直接把240,320的图片尺寸敲上去了,原本程序可以直接在开头改,开头有:IMG_WIDTH, IMG_HEIGHT = 240, 320 # 图片尺寸 就是这里的两个尺寸;另外,如果是RGB的话,应该改为array2=(immatrix[ind[i]].reshape((240,320,3))),这里“3”表示RGB是颜色三通道

# 使用主成分进行k-means聚类
immatrix = array([array(Image.open(im)).flatten() for im in imlist], 'f')  # 拼接所有图片
#对imlist中的所有图片转换为数组array,并进行扁平化flatten
#再对上一步的数组再转化为数组
immean = immean.flatten()
projected = array([dot(V[:CLUSTER *4], immatrix[i] - immean) for i in range(imnbr)])  # 前4×CLUSTER个主成分
projected = whiten(projected)
centroids, distortion = kmeans(projected, CLUSTER)
code, distance = vq(projected, centroids)

#输出部分
for k in range(CLUSTER):
    print('\n')  #换行
    ind = where(code == k)[0]
    print('cluster:', k + 1)    #输出类别序号
    for i in range(minimum(len(ind), imnbr)):
        array2=(immatrix[ind[i]].reshape((240,320)))    #将拼接的图片reshape成原来的图片
        image1=Image.fromarray(array2)
        path1 = 'E:/d15/frame/try1/'
        #下面两行是由于图片格式有不同,所以做一下具体转换。如果是RGB的话请查一下对应表述蛤,印象中就是把"L"改成"RGB"就好了
        if image1.mode == "F":             # F: 32位浮点型像素
            image1 = image1.convert('L')   # L: 8位黑白像素
            
#把对应簇的照片保存在对应路径的文件夹下  #文件夹有规律的话可以改成循环,但文件夹要提前生成
	if (k+1)==1:
            image1.save('E:/d15/frame/try1/cluster1/' + 'cluster1_'+str(i+1) + '.jpg')
        elif (k+1)==2:
            image1.save('E:/d15/frame/try1/cluster2/' + 'cluster2_'+str(i+1) + '.jpg')
        elif (k + 1) == 3:
            image1.save('E:/d15/frame/try1/cluster3/' + 'cluster3_'+ str(i+1) + '.jpg')
        elif (k + 1) == 4:
            image1.save('E:/d15/frame/try1/cluster4/' + 'cluster4_'+str(i+1) + '.jpg')
        elif (k + 1) == 5:
            image1.save('E:/d15/frame/try1/cluster5/' + 'cluster5_'+str(i+1) + '.jpg')
        elif (k + 1) == 6:
            image1.save('E:/d15/frame/try1/cluster6/' + 'cluster6_'+str(i+1) + '.jpg')
        elif (k + 1) == 7:
            image1.save('E:/d15/frame/try1/cluster7/' + 'cluster7_'+str(i+1) + '.jpg')
        elif (k + 1) == 8:
            image1.save('E:/d15/frame/try1/cluster8/' + 'cluster8_'+str(i+1) + '.jpg')
        elif (k + 1) == 9:
            image1.save('E:/d15/frame/try1/cluster9/' + 'cluster9_'+str(i+1) + '.jpg')
        elif (k + 1) == 10:
            image1.save('E:/d15/frame/try1/cluster10/' + 'cluster10_' + str(i + 1) + '.jpg')
        else:
            print("error")
    print ("number of pictures in this cluster:---",i+1,'---')  #输出每一类照片的个数
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值