原理介绍
K-L变换是模式识别中常用的一种特征提取方法,出发点是从一组特征中计算出一组按重要性从大到小排列的新特征,它们是原有特征的线性组合,并且相互之间是不相关的,实现数据的降维。
在人脸识别中,可以用K-L变换对人脸图像的原始空间进行转换,即构造人脸图像数据集的协方差矩阵,求出协方差矩阵的特征向量,再依据特征值的大小对这些特征向量进行排序,这些特征向量表示特征的一个集合,它们共同表示一个人脸图像。在人脸识别领域,人们常称这些特征向量为特征脸。每一个体人脸图像都可以确切地表示为一组特征脸的线性组合。
本实验首先下载ORL人脸数据集,构建人脸训练数据库和测试数据库,采用K-L变换进行特征脸提取,并使用K近邻算法实现人脸识别。
算法具体步骤
1、读入人脸数据库
读入时,将每个人脸图像转化为一维的列向量。本次实验参与训练的人脸图像有N个,每个图像大小为(R×L)。则训练图像可以表示为一个(R×L)×N的矩阵X。其中,第i个人脸可以表示为。
2、人脸数据K-L变换
计算所有人脸图像的平均值向量,选择数据的协方差矩阵作为K-L变换的产生矩阵 ,Σ的维数为。如果直接对样本进行降维,需要求解Σ的正交归一的特征向量,由于矩阵维数高,直接计算困难。
现考查由样本集构成的另一个矩阵,它的维数是。通常。矩阵S的特征方程是,两边同时左乘X,得,即,记,则上式变成,这就是的特征方程。
因此,维矩阵和维矩阵具有相同的特征值,特征向量的关系为。将的值从大到小排序,选取前Z个特征值,使其满足,,这里的α表示前Z个特征所能代表的样本间的差异信息占全部差异信息的比例。本次实验选取的α为97%。然后,计算,则组成了新的正交归一的特征空间,也就是原始特征空间向K-L变换后特征空间的投影矩阵。
投影
将每一幅人脸与平均脸μ的差值矢量投影到新的特征空间,得到第i个人脸的特征脸向量表示为:。
%======================================================
% KLFaceRecognition.m 基于KL变换的人脸识别
% Envirment:MATLAB R2017a
% DATE:2018/11/02
%======================================================
%======================================================
% 第一步:读入ORL人脸数据集
%======================================================
clear
close all;
clc
f1 = dir('ORL');
f2 = dir([f1(4).folder '\' f1(3).name]);
face = cell(1, 1);
AllData = zeros(2, 2);
LabelList = zeros(1, 1);
num = 0;
for i = 3 : length(f2)
fi = dir([f2(i).folder '\' f2(i).name]);
for j = 3 : length(fi)
num = num + 1;
face{i - 2, j - 2} = imread([fi(j).folder '\' fi(j).name]);
fileName = sprintf('f%d.png', j);
imwrite(face{i - 2, j - 2}, [fi(j).folder '\' fileName]);
if num == 1
[Len, Wid] = size(face{i - 2, j - 2});
end
AllData(1: Len * Wid, num) = reshape(face{i - 2, j - 2}, ...
[Len * Wid, 1]);
LabelList(1, num) = i-2;
% imshow(face{i - 2, j - 2});
end
end
[W, Y] = KLTransform(AllData' * AllData, 10000);
U = AllData * (Y .* (1./sqrt(W')));
for i = 1 : length(U)
I = reshape(U(:, i), [Len, Wid]);
figure(), imshow(I);
fileName = sprintf('p%d.png', i);
imwrite(I, fileName);
if sum(W(1: i)) / sum(W) > 0.97
break;
end
end
Acc = kFoldTest([AllData; LabelList], @FaceClassify, [2, 4, 6, 8, 10]);
Acc = cell2mat(Acc);
averAcc = sum(Acc, 2)/size(Acc, 2);
function [l, U] = KLTransform( OriginX, e )
%========================================================
% function [U, l] = KLTransform( OriginX ):K-L变换
% 输入参数:OriginX 进行K-L变化的矩阵,要为方阵
% e 变换后特征值占据的比例
% 输出参数:l 特征值向量
% U 特征值向量对应的特征矩阵
% 编程环境 MATLAB R2017a
% Date:2018/11/1
%========================================================
[UU, ll] = eig(OriginX);
ll = diag(ll)';
for i = 1 : length(ll)
for j = i+1 : length(ll)
if ll(i) < ll(j)
temp = ll(i);
ll(i) = ll(j);
ll(j) = temp;
temp = UU(:, i);
UU(:, i) = UU(:, j);
UU(:, j) = temp;
end
end
end
% for i = 1 : length(ll)
% if ~ (sum(ll(1: i)) / sum(ll) < e)
% l = ll(1: i);
% U = UU(:, 1: i);
% break;
% end
% end
l = ll;
U = UU;
end