基于PCA和奇异值分解SVD的人脸识别
视频链接:https://pan.baidu.com/s/1pMCsJFl
录制的视频是算法底层原理讲解,底层代码实现,方便大家真正掌握算法实质,开发出更加出色的算法。录制视频的初衷是:避免读者朋友利用大把时间学习已有常见算法,本系列视频旨在让读者朋友快速深入了解这些常见算法原理,有更多的时间去研究更加高大上算法(价值)。
具体链接在halcom.cn论坛,联系人QQ:3283892722
该论坛是一个学习交流平台,我会逐一的和大家分享学习。
欢迎大家录制视频,并提交给我,我来设置视频,你可在论坛进行打赏分享。
视频专用播放器:http://halcom.cn/forum.php?mod=viewthread&tid=258&extra=page%3D1
运行环境:win7+32bit+matlab2014a
SVD分解提取图像的主要成分,主要根据图像的奇异值相关,一般根据图像的熵来进行选取SVD的奇异值个数,根据选择的奇异值k值个数,再进行PCA分析。 矩阵分解后较大的奇异值代表了原矩阵的主要信息,而较小的奇异值反映其细节信息,根据奇异值的这一性质,通过选取较大的k个奇异值组成新的成分集Skxk。就可以在误差允许范围内近似还原矩阵的主要信息:Imxn = Umxk* Skxk * Vkxn (1) 因为奇异值从大到小依次排列,所以选取的k个奇异值即为前k个奇异值。 据奇异值分解重建背景的具体步骤如下: 1)对原图像I的像素矩阵进行SVD处理,计算正交阵U和V、奇异值矩阵S; 2)保留S中选取的k个用于重建背景的有效奇异值,其余置零,得到新奇异值矩阵S; 3)根据得到的新奇异值矩阵S和式(1)进行背景重建,得到重建的背景。 4)原图像与背景图像的差则就是无效成分; 采用最大熵算法确定奇异值个数:
基于最大熵的有效奇异值分解算法,能够较好的滤除图像椒盐噪点,使得图像变得更加平滑。 - clc,clear,close all
- warning off
- path = './ORL92112/bmp/';
- if(exist('ORL92112.mat'))
- load('ORL92112.mat')
- else
- k1 = 1; k2=1;
- for i=1:40
- paths = [path, 's', num2str(i),'/'];
- for j=1:10
- im = imread([paths, num2str(j), '.BMP']);
- if(mod(j,2)) % train
- trainImages2D(:,:,k1) = im;
- trainImages1D(:,k1) = im(:);
- trainLabels(k1) = i;
- k1=k1+1;
- else % test
- testImages2D(:,:,k2) = im;
- testImages1D(:,k2) = im(:);
- testLabels(k2) = i;
- k2=k2+1;
- end
- end
- end
- save ORL92112.mat trainImages2D trainImages1D trainLabels testImages2D testImages1D testLabels
- end
- %% SVD图像分解计算
- % 测试一张图像
- TestImage = testImages2D(:,:,2); % 选择一张图像
- [U,S,V] = svd( double(TestImage) );
- k = 50; % 前k个奇异值
- for i=k:min(size(S,1), size(S,2))
- S(i,i) = 0;
- end
- SVDImage = uint8( U*S*V' );
- ErrImage = TestImage-SVDImage;
- % figure,
- % subplot(311), imshow(TestImage,[])
- % subplot(312), imshow(SVDImage,[])
- % subplot(313), imshow(ErrImage,[])
- %% 最大熵
- [U,S,V] = svd( double(TestImage) );
- lamda = diag(S); % 奇异值
- for k=1:min(size(S,1), size(S,2))-2
- pB= sum( lamda(1:k) ) ./ sum(lamda);
- pE = 1-pB;
- Xk = -pB*log(pB+eps);
- Yk = -pE*log(pE+eps);
- Hk(k) = (Xk+Yk)./(Xk.^2+Yk.^2+eps);
- end
- % 首尾两点直线
- x1 = 1; y1 = Hk(1);
- x2 = length(Hk); y2 = Hk(end);
- kline = (y2-y1)./(x2-x1+eps);
- for i=1:length(Hk)
- dist(i) = abs( kline*(i-x1)+y1-Hk(i) )./ sqrt(kline^2+1);
- end
- [indexa,indexb] = max(dist);
- figure,
- plot(Hk,'b.-','linewidth',2)
- hold on
- plot([x1,x2],[y1,y2],'r-');
- plot(indexb, Hk(indexb), 'ro')
- hold off;
- xlabel('奇异值个数'); ylabel('熵值');
- % 测试一张图像
- TestImage = testImages2D(:,:,2); % 选择一张图像
- [U,S,V] = svd( double(TestImage) );
- k = indexb; % 前k个奇异值
- for i=k:min(size(S,1), size(S,2))
- S(i,i) = 0;
- end
- SVDImage = uint8( U*S*V' );
- ErrImage = TestImage-SVDImage;
- figure,
- subplot(311), imshow(TestImage,[])
- subplot(312), imshow(SVDImage,[])
- subplot(313), imshow(ErrImage,[])
- %% SVD+PCA
- for i=1:size(trainImages2D, 3)
- im = trainImages2D(:,:,i);
- [SVDImage, ErrImage] = SVD_entropy(im);
- trainImages1D_SVD(:,i) = SVDImage(:);
- end
- %% 特征脸计算
- numEigs = 199; % 特征向量个数
- [meanFace, WhiteFace, Eigenfaces] = EigenfaceCore(trainImages1D_SVD, numEigs);
- %% 测试图像
- TestImage = testImages2D(:,:, 3); % 选择一张图像
- [TestImage_SVD, ErrImage] = SVD_entropy(TestImage);
- Recognized_index = Face_Recognition(TestImage_SVD, meanFace, WhiteFace, Eigenfaces);
- SelectedImage = trainImages2D(:,:,Recognized_index);
- figure,
- subplot(121),imshow(TestImage,[]); title('测试图像')
- subplot(122),imshow(SelectedImage,[]); title('识别匹配图像')
- %% 遍历
- for i=1:size(testImages2D,3)
- TestImage = testImages2D(:,:, i); % 选择一张图像
- [TestImage_SVD, ErrImage] = SVD_entropy(TestImage);
- Recognized_index = Face_Recognition(TestImage_SVD, meanFace, WhiteFace, Eigenfaces);
- testSimu(1,i) = Recognized_index;
- end
- accuracy = AccCompute( testSimu, testLabels );
- disp(['测试精度: ',num2str(accuracy)])
复制代码 程序识别精度:0.9
|