您的位置:首页 > 编程语言 > MATLAB

matlab实现人脸识别---PCA与最近邻法

2017-12-06 19:51 971 查看
目标:已知类别的人脸图像,待检类别图像,从待检测图像中识别与已知类别的图像中相同的图像。

已知类别:3479张

待检测类别:276张

PCA给样本矩阵降维

最近邻法识别

一共包括3个.m文件,train.m,test.m,recognition.m。

train.m文件实现将训练样本矩阵降维,并得到映射矩阵;test.m文件将测试样本矩阵降维;recognition.m文件实现识别过程。

train.m代码:

file_path='F:\课程\模式识别\Dataset\muct人脸图像\已知类别\';% 图像文件夹路径
img_path_list = dir(strcat(file_path,'*.jpg'));%获取该文件夹中所有jpg格式的图像
img_num = length(img_path_list);%获取图像总数量
imgTrain = [];
Q = [];%列矩阵,一副图像
trainFace = [];%降维后的训练样本的矩阵
% 读取每一幅图像
%转化为灰度图像 并将每一幅图像转化为列向量 然后合并为矩阵T
for j=1:img_num %逐一读取图像
image_name = img_path_list(j).name;%图像名
img = imread(strcat(file_path,image_name));
img = rgb2gray(img);%转为灰度
%img=histeq(img);%直方图均衡化
img=imadjust(img);%使得图像中 1% 的数据饱和至最低和最高亮度
img = imresize(img, 0.2, 'nearest');
[irow,icol] = size(img);%得到图片大小
%     for m=1:irow
%         for n=1:icol
%             img(m,n) = 10*img(m,n);
%         end
%     end
temp = reshape(img,irow*icol,1);%将二维图片转为一维向量
Q = [Q,temp]; % 每张图片的信息做为V的一列

imgTrain=[imgTrain,temp];

end

%  [L_eig_vec,A] = HSCalPCA(imgTrain);%调用PCA降维函数,得到映射矩阵

%得到均值矩阵
%并用T剪去均值矩阵  得到矩阵A
m = mean(imgTrain,2); % 平均图像/行平均(每一副图像的对应象素求平均)m=(1/P)*sum(Tj's) (j=1 : P)
Train_Number = size(imgTrain,2);%列数
%计算机每一张图片到均值图像的方差
A = [];
for i = 1 : Train_Number%对每一列
temp = double(imgTrain(:,i))-m; %每一张图与均值的差异
A = [A temp]; %差矩阵
end
%得到A的协方差矩阵并转置得到L
L = A'*A; % L是协方差矩阵C=A*A'的转置
%得到特征值与特征向量
[V D] = eig(L); %对角线上的元素是L|C的特征值.V:以特征向量为列的满秩矩阵,D:特征值对角矩阵。即L*V = V*D.
L_eig_vec = [];%特征值向量
max=0;
for i = 1 : size(V,2)%对每个特征向量
max=max+D(i,i);
end
sum=0;
for i = size(V,2):-1:size(V,2)-2%对每个特征向量
L_eig_vec = [L_eig_vec V(:,i)]*0;%集中对应的特征向量
sum=sum+D(i,i);
end
for i = size(V,2)-3:-1:size(V,2)-9%对每个特征向量
L_eig_vec = [L_eig_vec V(:,i)]*0.05;%集中对应的特征向量
sum=sum+D(i,i);
end
for i = size(V,2)-10:-1:1%对每个特征向量
L_eig_vec = [L_eig_vec V(:,i)];%集中对应的特征向量
sum=sum+D(i,i);
if(sum/max>0.99)
break;
end
end

% for i = 1:size(V,2)
%      if(D(i,i)>1)
% L_eig_vec = [L_eig_vec V(:,i)];
%     end
% end

Eigenfaces = A * L_eig_vec; % 计算机协方差矩阵C的特征向量,
%得到降维了的特征,A为每一张图像与均值图像的方差构成的矩阵,
TrainProjectedImages = [];%映射图像
for i = 1 : img_num%对于每一个训练特征
temp = Eigenfaces'*double(Q(:,i));
TrainProjectedImages = [TrainProjectedImages temp];  %得到 L_eig_vec;
end
save('D:\Program Files\MATLAB\R2016a\bin\projects\face1\TrainProjectedImages.mat','TrainProjectedImages');
save('D:\Program Files\MATLAB\R2016a\bin\projects\face1\Eigenfaces.mat','Eigenfaces');


test.m:

TrainProjectedImages=load('D:\Program Files\MATLAB\R2016a\bin\projects\face1\TrainProjectedImages.mat');
TrainProjectedImages=TrainProjectedImages.TrainProjectedImages;%训练数据集(降维后的)
Eigenfaces=load('D:\Program Files\MATLAB\R2016a\bin\projects\face1\Eigenfaces.mat');
Eigenfaces=Eigenfaces.Eigenfaces;%训练数据集(降维后的)
% imgTrain=load('D:\Program Files\MATLAB\R2016a\bin\projects\face1\imgTrain.mat');
% imgTrain=imgTrain.imgTrain;%训练数据集(降维后的)
file_path='F:\课程\模式识别\Dataset\muct人脸图像\待分类\';% 图像文件夹路径
img_path_list = dir(strcat(file_path,'*.jpg'));%获取该文件夹中所有jpg格式的图像
img_num = length(img_path_list);%获取图像总数量
imgTest = [];
Q = [];%列矩阵,一幅图像
testFace = [];%减去训练矩阵均值后的测试图像矩阵
%导入由训练数据集得到的  变换矩阵跟降维后的训练集

% 读取每一幅图像
%转化为灰度图像 并将每一幅图像转化为列向量 然后合并为矩阵T
for j=1:img_num %逐一读取图像
image_name = img_path_list(j).name;%图像名
img = imread(strcat(file_path,image_name));
img = rgb2gray(img);%转为灰度
%img=histeq(img);%直方图均衡化
img=imadjust(img);%使得图像中 1% 的数据饱和至最低和最高亮度
img = imresize(img, 0.2, 'nearest');%改变图像的大小,'nearest'(默认值)最近邻插值
[irow,icol] = size(img);%得到图片大小
%     for m=1:irow
%         for n=1:icol
%             img(m,n) = 10*img(m,n);
%         end
%     end
temp = reshape(img,irow*icol,1);%将二维图片转为一维向量
Q = [Q,temp]; % 每张图片的信息做为V的一列

imgTest = [imgTest,temp];

end
%     imgTrain = imgTrain';
%     mMiu = mean(imgTrain,2);%求各行的均值
%
%     mMiu = repmat(mMiu,1,icol);%复制成原有的行数N列的矩阵
%     testFace =double(imgTest')-mMiu;

TestProjectedImages = [];%测试集降维
for i = 1 : img_num%对于每一个训练特征
temp = Eigenfaces'*double(Q(:,i));
TestProjectedImages = [TestProjectedImages temp];  %得到 L_eig_vec;
end
% TsetProjectedImages1=trainFace*double(testFace' );
save('D:\Program Files\MATLAB\R2016a\bin\projects\face1\TestProjectedImages.mat','TestProjectedImages');
% save('D:\Program Files\MATLAB\R2016a\bin\projects\face\testFace.mat','testFace');


recognition.m:
clc;
clear;
m=0;
count=0;
% 加载降维后的样本和测试矩阵,进行最近邻法识别
TrainProjectedImages=load('D:\Program Files\MATLAB\R2016a\bin\projects\face1\TrainProjectedImages.mat');
TrainProjectedImages=TrainProjectedImages.TrainProjectedImages;%训练数据集(降维后的) *3479
TestProjectedImages=load('D:\Program Files\MATLAB\R2016a\bin\projects\face1\TestProjectedImages.mat');
TestProjectedImages=TestProjectedImages.TestProjectedImages;%测试数据集(降维后的)    *276
[Trainrows,Traincols] = size(TrainProjectedImages);%得到训练集的大小
[Testrows,Testcols] = size(TestProjectedImages);%得到测试集的大小
%将训练图片的名字存到以为矩阵里
img_name_train = [];
img_name_test = [];
file_path_train= 'F:\课程\模式识别\Dataset\muct人脸图像\已知类别\';
img_path_list_train = dir(strcat(file_path_train,'*.jpg'));
img_num_train = length(img_path_list_train);
% for k=1:img_num_train
% 	name2 = img_path_list_train(k).name;
%     img_name_train = [img_name_train,name2];
% end
%将测试图片的名字存到一维矩阵里
file_path_test= 'F:\课程\模式识别\Dataset\muct人脸图像\待分类\';
img_path_list_test = dir(strcat(file_path_test,'*.jpg'));
img_num_test = length(img_path_list_test);

% for g=1:img_num_test
% 	name1= img_path_list_test(g).name;
%     img_name_test = [img_name_test,name1];
% end
%循环,计算每张测试图片与训练图片的距离,找到距离最小的测试图,判断测试图片与训练图片名字是否一致,一致数量加一
for i=1:Testcols
mImgTestCur = TestProjectedImages(:,i);
vDisMin = 9999999999999;
vClassMin = -1;
for j=1:Traincols
mImgTrainCur = TrainProjectedImages(:,j);
mDis = mImgTestCur-mImgTrainCur;
mDis = mDis.^2;
vDis = sqrt(sum(mDis));
if vDis<vDisMin
vDisMin = vDis;
m=j;
end
end
name1=img_path_list_train(m).name;
name1 =name1(2:4);%取名字的第2到4位置的字符
name1=str2num(name1);
name2=img_path_list_test(i).name;
name2 =name2(2:4);
name2=str2num(name2);
if name2==name1
count=count+1;
end

end

vRatio = count/Testcols*100;
sprintf('正确率:%.1f%%',vRatio)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: