PCA的应用示例(转载)



PCA的应用示例

在 PCA 详细算法介绍 (http://blog.csdn.net/watkinsong/article/details/38536463) 中, 因为篇幅问题 没有给出详细的代码示例, 这里给出代码示例。

通过对人脸图像进行降维深入了解PCA算得使用。

首先看一下数据集, 我们有12张人脸图像, 用10张人脸训练PCA降维矩阵, 剩下的两张可以用作测试。 

   

   

   

需要特别注意: 只能使用训练集样本进行所有的PCA训练过程。

这里所有的代码都采用 octave实现, 跟matlab应该是一致的。


1. 加载图像


 
 
  1. %% Initialization
  2. clear ; close all; clc
  3. fprintf( 'this code will load 12 images and do PCA for each face.\n');
  4. fprintf( '10 images are used to train PCA and the other 2 images are used to test PCA.\n');
  5. trainset = zeros( 10, 32 * 32); % image size is : 32 * 32
  6. m = 10; % number of samples
  7. for i = 1 : m
  8. img = imread(strcat(int2str(i), '.bmp'));
  9. img = double(img);
  10. trainset(i, :) = img(:);
  11. end

2. 特征向量做 normalization



 
 
  1. %% before training PCA, do feature normalization
  2. mu = mean(trainset);
  3. trainset_norm = bsxfun(@minus, trainset, mu);
  4. sigma = std(trainset_norm);
  5. trainset_norm = bsxfun(@rdivide, trainset_norm, sigma);

3. 在做特征向量归一化的过程中, 我们为了以后使用归一化参数, 需要保存这些归一化参数。

比如这里可能需要保存mu 和 sigma, 这里我们已 mean face 的方式保存 mu, 因为本示例比较小, 所以没有保存 sigma, 这里保存mu 的目的也仅仅是 为了让大家看一下平均脸的样子。 如果在做项目的过程中, 可能训练PCA是分开进行的, 以后需要进行降维, 那么就需要保存这两个归一化参数。 


 
 
  1. %% we could save the mean face mu to take a look the mean face
  2. imwrite( uint8(reshape(mu, 32, 32)), 'mf.bmp');

看一下由10张人脸生成的平均脸:


是不是比较丑?  因为人脸太少了, 再来看看由5000个人脸图像生成的平均脸: 



4. 计算降维矩阵



 
 
  1. %% compute reduce matrix
  2. X = trainset_norm; % just for convience
  3. [ m, n] = size(X);
  4. U = zeros(n);
  5. S = zeros(n);
  6. Cov = 1 / m * X ' * X;
  7. [U, S, V] = svd(Cov);
  8. fprintf('compute cov done.\n ');

5.  查看特征脸


降维矩阵U中的特征向量, 在关于人脸的降维中,又被称为特征脸,  U 中的每个特征向量相当于找到的降维空间的一个方向。 利用U可以将特征映射到这个空间中。


这里我们把的U中的前几个特征向量保存下来,  看一下特征脸。 U 中的特征向量是按照特征值进行由大到小排序的, 这个排序的顺序也决定了对于降维的影响最大的向量放在最前面。 


       

这里的 eigen face 和人脸的相似性比较高, 因为我们的样本数量比较少, 就10个样本。。。所以会出现这种相似度比较高的情况。


补充: 给出几张用5000张人脸图像训练得到的eigen face, 如下所示:

     


6. 降维


 
 
  1. %% dimension reduction
  2. k = 100; % reduce to 100 dimension
  3. test = zeros( 2, 32 * 32);
  4. for i = 1: 2
  5. img = imread(strcat(int2str(i + 10), '.bmp'));
  6. img = double(img);
  7. test(i, :) = img(:);
  8. end
  9. % test set need to do normalization
  10. test_norm = bsxfun(@minus, test, mu);
  11. test_norm = bsxfun(@rdivide, test_norm, sigma);
  12. % reduction
  13. Uk = U(:, 1:k);
  14. Z = test_norm * Uk;
  15. fprintf( 'reduce done.\n');

7. 还原特征(Reconstruction)



 
 
  1. %% reconstruction
  2. %% for the test set images, we only minus the mean face,
  3. % so in the reconstruct process, we need add the mean face back
  4. Xp = Z * Uk ';
  5. % show reconstructed face
  6. for i = 1:5
  7. face = Xp(i, :) + mu;
  8. face = reshape((face), 32, 32);
  9. imwrite(uint8(face), strcat('./reconstruct/ ', int2str(4000 + i), '.bmp '));
  10. end
  11. %% for the train set reconstruction, we minus the mean face and divide by standard deviation during the train
  12. % so in the reconstruction process, we need to multiby standard deviation first,
  13. % and then add the mean face back
  14. trainset_re = trainset_norm * Uk; % reduction
  15. trainset_re = trainset_re * Uk'; % reconstruction
  16. for i = 1: 5
  17. train = trainset_re(i, :);
  18. train = train .* sigma;
  19. train = train + mu;
  20. train = reshape(train, 32, 32);
  21. imwrite(uint8(train), strcat( './reconstruct/', int2str(i), 'train.bmp'));
  22. end



注: 这里我使用了训练样本为4000张, 因为样本数量太少还原的效果很差。 

看一下特征还原的效果: 左边为原始图像, 右边为还原的图像

对于测试样本还原, 测试样本在降维之前减去了mean face, 所以在还原之后还要加上mean face才是真正的还原的图像。

 

 

 

 


对于训练样本还原, 因为训练样本即减去了mean face 还除以了 standard deviation, 所以在计算得到还原的样本特征后, 还首先要将特征 按元素乘上 standard deviation, 也就是 .* ,  然后再加上mean face才是最后得到的真实的还原的数据。 

看以下几个关于训练样本的还原: 同样左边为原始图像, 右边为还原之后的图像

  

  

  

  



整个工程的全部代码: 



 
 
  1. %% Initialization
  2. clear ; close all; clc
  3. fprintf( 'this code will load 12 images and do PCA for each face.\n');
  4. fprintf( '10 images are used to train PCA and the other 2 images are used to test PCA.\n');
  5. m = 4000; % number of samples
  6. trainset = zeros(m, 32 * 32); % image size is : 32 * 32
  7. for i = 1 : m
  8. img = imread(strcat( './img/', int2str(i), '.bmp'));
  9. img = double(img);
  10. trainset(i, :) = img(:);
  11. end
  12. %% before training PCA, do feature normalization
  13. mu = mean(trainset);
  14. trainset_norm = bsxfun(@minus, trainset, mu);
  15. sigma = std(trainset_norm);
  16. trainset_norm = bsxfun(@rdivide, trainset_norm, sigma);
  17. %% we could save the mean face mu to take a look the mean face
  18. imwrite( uint8(reshape(mu, 32, 32)), 'meanface.bmp');
  19. fprintf( 'mean face saved. paused\n');
  20. pause;
  21. %% compute reduce matrix
  22. X = trainset_norm; % just for convience
  23. [ m, n] = size(X);
  24. U = zeros(n);
  25. S = zeros(n);
  26. Cov = 1 / m * X ' * X;
  27. [U, S, V] = svd(Cov);
  28. fprintf('compute cov done.\n ');
  29. %% save eigen face
  30. for i = 1:10
  31. ef = U(:, i)';
  32. img = ef;
  33. minVal = min(img);
  34. img = img - minVal;
  35. max_val = max(abs(img));
  36. img = img / max_val;
  37. img = reshape(img, 32, 32);
  38. imwrite(img, strcat( 'eigenface', int2str(i), '.bmp'));
  39. end
  40. fprintf( 'eigen face saved, paused.\n');
  41. pause;
  42. %% dimension reduction
  43. k = 100; % reduce to 100 dimension
  44. test = zeros( 10, 32 * 32);
  45. for i = 4001: 4010
  46. img = imread(strcat( './img/', int2str(i), '.bmp'));
  47. img = double(img);
  48. test(i - 4000, :) = img(:);
  49. end
  50. % test set need to do normalization
  51. test = bsxfun(@minus, test, mu);
  52. % reduction
  53. Uk = U(:, 1:k);
  54. Z = test * Uk;
  55. fprintf( 'reduce done.\n');
  56. %% reconstruction
  57. %% for the test set images, we only minus the mean face,
  58. % so in the reconstruct process, we need add the mean face back
  59. Xp = Z * Uk ';
  60. % show reconstructed face
  61. for i = 1:5
  62. face = Xp(i, :) + mu;
  63. face = reshape((face), 32, 32);
  64. imwrite(uint8(face), strcat('./reconstruct/ ', int2str(4000 + i), '.bmp '));
  65. end
  66. %% for the train set reconstruction, we minus the mean face and divide by standard deviation during the train
  67. % so in the reconstruction process, we need to multiby standard deviation first,
  68. % and then add the mean face back
  69. trainset_re = trainset_norm * Uk; % reduction
  70. trainset_re = trainset_re * Uk'; % reconstruction
  71. for i = 1: 5
  72. train = trainset_re(i, :);
  73. train = train .* sigma;
  74. train = train + mu;
  75. train = reshape(train, 32, 32);
  76. imwrite(uint8(train), strcat( './reconstruct/', int2str(i), 'train.bmp'));
  77. end
  78. fprintf( 'job done.\n');



        版权声明:本文为博主原创文章,未经博主允许不得转载。          https://blog.csdn.net/weixingstudio/article/details/38539289        
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值