基于主成分分析(PCA)的人脸识别 (完整Matlab代码) (有GUI界面) 本设计会将彩色图片直接转化为黑白图像,自带数据库,图片重建效果好很多!自己的图片可能会差一些,效果如下图所示:
先看数据预处理部分。自带数据库里的图片都是统一尺寸的,这点很重要:
function faces = load_faces(directory) files = dir(fullfile(directory, '*.jpg')); faces = []; for i = 1:length(files) img = imread(fullfile(directory, files(i).name)); gray_img = rgb2gray(img); % 强制转灰度 vec = double(gray_img(:)); % 压成向量 faces = [faces vec]; % 横向拼接 end end这里有个坑——很多新手会忽略图像向量化的操作。那个冒号操作(:)把二维矩阵压成一维列向量,之后所有脸都变成矩阵里的一列,这种数据结构才是PCA能处理的。
核心的PCA实现反而简单得离谱:
[coeff, score, latent] = pca(faces'); mean_face = mean(faces, 2); % 平均脸是关键MATLAB自带的pca函数直接搞定协方差矩阵计算和特征分解。不过要注意的是,pca函数默认对行做处理,所以要把人脸矩阵转置后再喂进去。平均脸的计算用mean函数按列取平均,这个平均脸后续重建时会用到。
图像重建才是最好玩的部分:
k = 50; % 选前50个主成分 projection = score(:,1:k) * coeff(:,1:k)'; reconstructed = projection' + mean_face; // 别漏了加回平均脸这里有个经典错误——忘记加回平均脸会导致重建图像像鬼片。系数矩阵和特征脸做矩阵乘法得到投影后,必须把之前减去的平均脸加回来,否则亮度会完全不对。
GUI界面里最麻烦的是实时显示效果:
function update_slider(hObject, ~) k = round(get(hObject, 'Value')); set(findobj('Tag','text_k'), 'String', num2str(k)); % 从handles结构体里拿之前算好的PCA参数 projection = handles.score(:,1:k) * handles.coeff(:,1:k)'; reconstructed = projection' + handles.mean_face; % 显示在axes里 axes(handles.axes_reconstruct); imshow(reshape(reconstructed(:,1), [img_h, img_w]), []); end滑动条回调函数里要注意数据传递,所有PCA计算结果必须存在handles结构体里。reshape操作是把一维向量恢复成二维图像,这里图像尺寸必须和原始尺寸完全一致,否则直接崩给你看。
实测发现用ORL数据库(自带的人脸库)重建效果超好,但用自己的照片就糊得像马赛克。原因可能有两点:一是自带照片都是标准光照和正脸,二是用户自己照片尺寸不匹配导致reshape出错。建议自拍时用白墙当背景,用PS统一裁剪到和数据库相同的像素尺寸。
最后吐槽下MATLAB的内存管理——当处理100张112x92的人脸时,数据矩阵大小是10304x100,这时候要是开太多主成分,GUI可能会卡成PPT。解决方案是在pca函数里加个'Economy',true参数,或者直接上专业版MATLAB(但学生党谁买得起啊)。