Python计算机视觉-第6章

本章将介绍几种聚类方法,并展示如何利用它们对图像进行聚类,从而寻找相似的 图像组。聚类可以用于识别、划分图像数据集,组织与导航。此外,我们还会对聚 类后的图像进行相似性可视化。

1、K-means聚类

K-means 是一种将输入数据划分成 k 个簇的简单的聚类算法。K-means 反复提炼初始评估的类中心,步骤如下:

(1) 以随机或猜测的方式初始化类中心 ui,i=1...k;
(2) 将每个数据点归并到离它距离最近的类中心所属的类 ci;
(3) 对所有属于该类的数据点求平均,将平均值作为新的类中心; (4) 重复步骤(2)和步骤(3)直到收敛。

K-means 试图使类内总方差最小:

 

xj 是输入数据,并且是矢量。

(1)SciPy聚类包

示例代码:

# coding=utf-8
"""
Function:  figure 6.1
    An example of k-means clustering of 2D points
"""
from pylab import *
from scipy.cluster.vq import *

# 添加中文字体支持
# from matplotlib.font_manager import FontProperties
# font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
# 添加中文字体支持
from matplotlib.font_manager import FontProperties
font = FontProperties(fname="/System/Library/Fonts/PingFang.ttc", size=14)

class1 = 1.5 * randn(100, 2)
class2 = randn(100, 2) + array([5, 5])
features = vstack((class1, class2))
centroids, variance = kmeans(features, 2)
code, distance = vq(features, centroids)
figure()
ndx = where(code == 0)[0]
plot(features[ndx, 0], features[ndx, 1], '*')
ndx = where(code == 1)[0]
plot(features[ndx, 0], features[ndx, 1], 'r.')
plot(centroids[:, 0], centroids[:, 1], 'go')

title(u'2维数据点聚类', fontproperties=font)
axis('off')
show()

运行结果:

(2)图像聚类

代码实现:

import imtools
import pickle
from PIL import Image
from scipy.cluster.vq import *
from pylab import *

# 获取 selected-fontimages 文件下图像文件名,并保存在列表中 
imlist = imtools.get_imlist('../data/fontimages/a_thumbs/')
imnbr = len(imlist)

# 载入模型文件
# with open('a_pca_modes.pkl','rb') as f:
with open('../data/fontimages/font_pca_modes.pkl','rb') as f:
	immean = pickle.load(f) 
	V = pickle.load(f)

# 创建矩阵,存储所有拉成一组形式后的图像
immatrix = array([array(Image.open(im)).flatten() for im in imlist],'f')

# 投影到前 40 个主成分上 
immean = immean.flatten()
projected = array([dot(V[:40],immatrix[i]-immean) for i in range(imnbr)])

# 进行 k-means 聚类
projected = whiten(projected) 
centroids,distortion = kmeans(projected,4)

code,distance = vq(projected,centroids)

# 绘制聚类簇
for k in range(4):
	ind = where(code==k)[0]
	figure()
	gray()
	for i in range(minimum(len(ind),40)):
		subplot(4,10,i+1) 
		imshow(immatrix[ind[i]].reshape((25,25))) 
		axis('off')
show()

运行结果:

 

(3)在主成分方向可视化图像

代码实现:

 # -*- coding: utf-8 -*-
# from PCV.tools import imtools, pca
import imtools, pca
from PIL import Image, ImageDraw
from pylab import *

imlist = imtools.get_imlist('../data/fontimages/a_thumbs')
imnbr = len(imlist)

# Load images, run PCA.
immatrix = array([array(Image.open(im)).flatten() for im in imlist], 'f')
V, S, immean = pca.pca(immatrix)

# Project on 2 PCs.
# projected = array([dot(V[[0, 1]], immatrix[i] - immean) for i in range(imnbr)])  # P142 Fig6-3左图
projected = array([dot(V[[1, 2]], immatrix[i] - immean) for i in range(imnbr)])  # P142 Fig6-3右图

# height and width
h, w = 1200, 1200

# create a new image with a white background
img = Image.new('RGB', (w, h), (255, 255, 255))
draw = ImageDraw.Draw(img)

# draw axis
draw.line((0, h/2, w, h/2), fill=(255, 0, 0))
draw.line((w/2, 0, w/2, h), fill=(255, 0, 0))

# scale coordinates to fit
scale = abs(projected).max(0)
scaled = floor(array([(p/scale) * (w/2 - 20, h/2 - 20) + (w/2, h/2) for p in projected])).astype(int)

# paste thumbnail of each image
for i in range(imnbr):
  nodeim = Image.open(imlist[i])
  nodeim.thumbnail((25, 25))
  ns = nodeim.size
  box = (scaled[i][0] - ns[0] // 2, scaled[i][1] - ns[1] // 2,
         scaled[i][0] + ns[0] // 2 + 1, scaled[i][1] + ns[1] // 2 + 1)
  img.paste(nodeim, box)

img.show()
img.save('../images/ch06/pca_font.png')

运行结果:

(4)像素聚类

代码实现:

# coding=utf-8
"""
Function: figure 6.4
    Clustering of pixels based on their color value using k-means.
"""
from scipy.cluster.vq import *
# from scipy.misc import imresize
from pylab import *
from PIL import Image

# 添加中文字体支持
from matplotlib.font_manager import FontProperties
# font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
font = FontProperties(fname="/System/Library/Fonts/PingFang.ttc", size=14)

def pix_cluster(infile,steps):
	# steps = 100  # image is divided in steps*steps region
	# infile = '../data/empire.jpg'
	im = array(Image.open(infile))
	dx = im.shape[0] // steps
	dy = im.shape[1] // steps
	# compute color features for each region
	features = []
	for x in range(steps):
	    for y in range(steps):
	        R = mean(im[x * dx:(x + 1) * dx, y * dy:(y + 1) * dy, 0])
	        G = mean(im[x * dx:(x + 1) * dx, y * dy:(y + 1) * dy, 1])
	        B = mean(im[x * dx:(x + 1) * dx, y * dy:(y + 1) * dy, 2])
	        features.append([R, G, B])
	features = array(features, 'f')     # make into array
	# cluster
	centroids, variance = kmeans(features, 3)
	code, distance = vq(features, centroids)
	# create image with cluster labels
	codeim = code.reshape(steps, steps)
	h,w = im.shape[:2]
	# codeim = imresize(codeim, im.shape[:2], 'nearest')
	codeim = array(Image.fromarray(codeim).resize((w,h),Image.NEAREST))

	return im,codeim


infile1 = '../data/empire.jpg'
infile2 = '../data/boy_on_hill.jpg'
steps1 = 50  # image is divided in steps*steps region
steps2 = 100  # image is divided in steps*steps region
im11,codeim11 =pix_cluster(infile1,steps1)
im12,codeim12 =pix_cluster(infile1,steps2)
im21,codeim21 =pix_cluster(infile2,steps1)
im22,codeim22 =pix_cluster(infile2,steps2)


figure()

subplot(231)
title(u'原图1', fontproperties=font)
#ax1.set_title('Image')
axis('off')
imshow(im11)

subplot(232)
title(u'50×50窗格聚类', fontproperties=font)
#ax2.set_title('Image after clustering')
axis('off')
imshow(codeim11)

subplot(233)
title(u'100×100窗格聚类', fontproperties=font)
#ax2.set_title('Image after clustering')
axis('off')
imshow(codeim12)

subplot(234)
title(u'原图2', fontproperties=font)
#ax1.set_title('Image')
axis('off')
imshow(im22)

subplot(235)
title(u'50×50窗格聚类', fontproperties=font)
#ax2.set_title('Image after clustering')
axis('off')
imshow(codeim21)

subplot(236)
title(u'100×100窗格聚类', fontproperties=font)
#ax2.set_title('Image after clustering')
axis('off')
imshow(codeim22)

show()

运行结果:

2、层次聚类

代码实现:

import os
# import Image
# from PCV.clustering import hcluster
from PIL import Image
import hcluster
# create a list of images
from matplotlib.pyplot import *
from numpy import *

# path = 'D:\\GitHub\\PCV-translation-to-Chinese\\data\\sunsets\\flickr-sunsets-small\\'
path = '../data/flickr-sunsets-small/'
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), 512])
for i, f in enumerate(imlist):
    im = array(Image.open(f))
    # multi-dimensional histogram
    h, edges = histogramdd(im.reshape(-1, 3), 8, normed=True, range=[(0, 255), (0, 255), (0, 255)])
    features[i] = h.flatten()
tree = hcluster.hcluster(features)

# visualize clusters with some (arbitrary) threshold
clusters = tree.extract_clusters(0.23 * tree.distance)
# plot images for clusters with more than 3 elements
for c in clusters:
    elements = c.get_cluster_elements()
    nbr_elements = len(elements)
    if nbr_elements > 3:
        figure()
        subplot(1,2,2)
        for p in range(minimum(nbr_elements,20)):
            subplot(4, 5, p + 1)
            im = array(Image.open(imlist[elements[p]]))
            imshow(im)
            axis('off')
show()

运行结果:

3、谱聚类

代码实现:

import imtools, pca
from PIL import Image
from pylab import *
from scipy.cluster.vq import * 

imlist = imtools.get_imlist('../data/fontimages/a_thumbs')
imnbr = len(imlist)

# Load images, run PCA.
immatrix = array([array(Image.open(im)).flatten() for im in imlist], 'f')
V, S, immean = pca.pca(immatrix)

# Project on 2 PCs.
# projected = array([dot(V[[0, 1]], immatrix[i] - immean) for i in range(imnbr)])  # P142 Fig6-3左图
projected = array([dot(V[[1, 2]], immatrix[i] - immean) for i in range(imnbr)])  # P142 Fig6-3右图
n = len(projected)

# 计算距离矩阵
S = array([[ sqrt(sum((projected[i]-projected[j])**2))
		for i in range(n) ] for j in range(n)], 'f')

# 创建拉普拉斯矩阵
rowsum = sum(S,axis=0)
D = diag(1 / sqrt(rowsum)) 
I = identity(n)
L = I - dot(D,dot(S,D))

# 计算矩阵 L 的特征向量 
U,sigma,V = linalg.svd(L)

k= 5

# 从矩阵 L 的前 k 个特征向量(eigenvector)中创建特征向量(feature vector) 
# 叠加特征向量作为数组的列

features = array(V[:k]).T

# k-means 聚类
features = whiten(features) 
centroids,distortion = kmeans(features,k) 
code,distance = vq(features,centroids)

# 绘制聚类簇
for c in range(k):
	ind = where(code==c)[0]
	figure()
	for i in range(minimum(len(ind),39)):
		im = Image.open(imlist[ind[i]]) 
		subplot(4,10,i+1)
		imshow(array(im))
		axis('equal')
		axis('off') 
show()

运行结果:

4、其他

已经调试过的源码和图片详见:

https://github.com/Abonaventure/pcv-book-code.git

https://gitlab.com/Abonaventure/pcv-book-code.git

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值