为什么第一主成分在我的 PCA 中显示的差异最小?
Why does the first principal component show least difference in my PCA?
我在 MatLab 中对一组面部图像使用 PCA。
创建普通面孔并随机化其他面孔效果很好。
在我的函数 vectorComparison 中,我想查看使用标准差时每个主成分向量的差异。但是当我使用 eig_face_index = 1 时,我发现与使用 2 或 3 等时相比差异较小
更高的索引似乎也增加了更多的颜色,这可能是由于特征脸中的噪声,因为我使用的是 RGB space。
为什么我的初始向量显示的差异最小。不应该反过来吗?
这是我使用的所有代码:
main.m
clear;clc;close all;
[imvecs,img] = loadImages();
meanval = meanValue(imvecs);
[T, D] = covarianceMatrix(imvecs, meanval);
[eigvecs, eigvals] = findEigVecs(imvecs, T, D);
eigenfaces = createEigenFaces(eigvecs, imvecs, img);
%%
[mean_image] = createAverageFace(meanval, img);
%%
[stdev_vec] = createRandomFace(eigvals, eigvecs, imvecs, meanval, img);
%%
vectorComparison(meanval, eigvecs, stdev_vec, img, mean_image);
loadImages.m
function [imvecs,img] = loadImages()
images = dir('D:My\Path\*.png');
imgPath = 'D:My\Path\';
img=imread([imgPath images(1).name]);
n=length(images);
for i = 1:n
img = imread([imgPath images(i).name]);
imvecs{i} = double(img(:));
end
return
meanValue.m
function meanval = meanValue(imvecs, imageNr)
%Creates the mean value from our images.
sumvec=imvecs{1};
for i = 2:(size(imvecs,2))
sumvec = sumvec + imvecs{i};
end
meanval = sumvec ./(size(imvecs,2));
return
covarianceMatrix.m
function [T, D] = covarianceMatrix(imvecs, meanval)
D = [];
for i = 1:size(imvecs,2),
diff = imvecs{i} - meanval;
D = [D, diff];
end
%Dimensionality reduction
T = (D' * D) ./ (size(imvecs,2));
return
findEigVecs.m
function [eigvecs, eigvals] = findEigVecs(imvecs, T, D)
[U,eigvals,V] = svd( T );
eigvecs = [];
for i = 1:size(imvecs,2),
eigvec = D * U(:,i);
eigvec = eigvec ./ sum(eigvec);
eigvecs = [eigvecs, eigvec];
end
return
createEigenFaces.m
function [eigenfaces] = createEigenFaces(eigvecs, imvecs, img)
for i = 1:size(imvecs,2),
eigface = reshape(eigvecs( : , i), size(img));
eigface = eigface - min(min(min((eigface))));
eigface = eigface ./ max(max(max((eigface))));
eigenfaces{i}=eigface;
%figure;imagesc(eigface);
end
return
createAverageFace.m
function [mean_image] = createAverageFace(meanval, img)
mean_image = reshape(meanval, size(img));
figure;imagesc(mean_image./255);
title('Average Face')
return
createRandomFace.m
function [stdev_vec] = createRandomFace(eigvals, eigvecs, imvecs, meanval, img)
stdev_vec = sqrt(diag(eigvals));
t = (100 * rand(size(imvecs,2),1) - 50) .* stdev_vec;
new_face1 = meanval + (eigvecs * t);
new_face1 = reshape(new_face1, size(img));
figure;imagesc(new_face1./255);
title('Random Face')
return
vectorComparison.m
function [] = vectorComparison(meanval, eigvecs, stdev_vec, img, mean_image)
t = zeros(17,1);
eig_face_index = 1;
t(eig_face_index) = 1000;
t = t.*stdev_vec;
new_face1 = meanval + (eigvecs * t);
new_face1 = reshape(new_face1, size(img));
new_face2 = meanval - (eigvecs * t);
new_face2 = reshape(new_face2, size(img));
figure;
title('PCA Comparison')
subplot(3,1,1), subimage(new_face1./255)
subplot(3,1,2), subimage(mean_image./255)
subplot(3,1,3), subimage(new_face2./255)
return
我发现这里出了什么问题。
在我的函数 findEigVals 中,我通过除以 sum 使每个向量成为一个单位向量(长度为 1)矢量本身。只要向量的内容范围为正条目,这是可能的。
然而,由于我们不知道我们是否有正方向或负方向的向量(两者同样有效),我们不能在这里使用 sum。
相反,我们需要将其替换为 norm,matlab 的规范化方式。
function [eigvecs, eigvals] = findEigVecs(imvecs, T, D)
[U,eigvals,V] = svd( T );
eigvecs = [];
for i = 1:size(imvecs,2),
eigvec = D * U(:,i);
eigvec = eigvec ./ norm(eigvec);
eigvecs = [eigvecs, eigvec];
end
return
如果有人使用上述代码的某个版本,请注意随机面部函数会在 rgb-space 中给出太强的值。
将 createRandomFace 替换为以下内容:
stdev_vec = sqrt(diag(eigvals));
min_range = 0;
max_range = 2;
t = ((max_range - min_range)*rand(n,1)) .* stdev_vec + min_range;
new_face1 = meanval + (eigvecs * t);
new_face1 = reshape(new_face1, size(img));
figure;imagesc(new_face1./255);
我在 MatLab 中对一组面部图像使用 PCA。 创建普通面孔并随机化其他面孔效果很好。
在我的函数 vectorComparison 中,我想查看使用标准差时每个主成分向量的差异。但是当我使用 eig_face_index = 1 时,我发现与使用 2 或 3 等时相比差异较小
更高的索引似乎也增加了更多的颜色,这可能是由于特征脸中的噪声,因为我使用的是 RGB space。
为什么我的初始向量显示的差异最小。不应该反过来吗?
这是我使用的所有代码:
main.m
clear;clc;close all;
[imvecs,img] = loadImages();
meanval = meanValue(imvecs);
[T, D] = covarianceMatrix(imvecs, meanval);
[eigvecs, eigvals] = findEigVecs(imvecs, T, D);
eigenfaces = createEigenFaces(eigvecs, imvecs, img);
%%
[mean_image] = createAverageFace(meanval, img);
%%
[stdev_vec] = createRandomFace(eigvals, eigvecs, imvecs, meanval, img);
%%
vectorComparison(meanval, eigvecs, stdev_vec, img, mean_image);
loadImages.m
function [imvecs,img] = loadImages()
images = dir('D:My\Path\*.png');
imgPath = 'D:My\Path\';
img=imread([imgPath images(1).name]);
n=length(images);
for i = 1:n
img = imread([imgPath images(i).name]);
imvecs{i} = double(img(:));
end
return
meanValue.m
function meanval = meanValue(imvecs, imageNr)
%Creates the mean value from our images.
sumvec=imvecs{1};
for i = 2:(size(imvecs,2))
sumvec = sumvec + imvecs{i};
end
meanval = sumvec ./(size(imvecs,2));
return
covarianceMatrix.m
function [T, D] = covarianceMatrix(imvecs, meanval)
D = [];
for i = 1:size(imvecs,2),
diff = imvecs{i} - meanval;
D = [D, diff];
end
%Dimensionality reduction
T = (D' * D) ./ (size(imvecs,2));
return
findEigVecs.m
function [eigvecs, eigvals] = findEigVecs(imvecs, T, D)
[U,eigvals,V] = svd( T );
eigvecs = [];
for i = 1:size(imvecs,2),
eigvec = D * U(:,i);
eigvec = eigvec ./ sum(eigvec);
eigvecs = [eigvecs, eigvec];
end
return
createEigenFaces.m
function [eigenfaces] = createEigenFaces(eigvecs, imvecs, img)
for i = 1:size(imvecs,2),
eigface = reshape(eigvecs( : , i), size(img));
eigface = eigface - min(min(min((eigface))));
eigface = eigface ./ max(max(max((eigface))));
eigenfaces{i}=eigface;
%figure;imagesc(eigface);
end
return
createAverageFace.m
function [mean_image] = createAverageFace(meanval, img)
mean_image = reshape(meanval, size(img));
figure;imagesc(mean_image./255);
title('Average Face')
return
createRandomFace.m
function [stdev_vec] = createRandomFace(eigvals, eigvecs, imvecs, meanval, img)
stdev_vec = sqrt(diag(eigvals));
t = (100 * rand(size(imvecs,2),1) - 50) .* stdev_vec;
new_face1 = meanval + (eigvecs * t);
new_face1 = reshape(new_face1, size(img));
figure;imagesc(new_face1./255);
title('Random Face')
return
vectorComparison.m
function [] = vectorComparison(meanval, eigvecs, stdev_vec, img, mean_image)
t = zeros(17,1);
eig_face_index = 1;
t(eig_face_index) = 1000;
t = t.*stdev_vec;
new_face1 = meanval + (eigvecs * t);
new_face1 = reshape(new_face1, size(img));
new_face2 = meanval - (eigvecs * t);
new_face2 = reshape(new_face2, size(img));
figure;
title('PCA Comparison')
subplot(3,1,1), subimage(new_face1./255)
subplot(3,1,2), subimage(mean_image./255)
subplot(3,1,3), subimage(new_face2./255)
return
我发现这里出了什么问题。 在我的函数 findEigVals 中,我通过除以 sum 使每个向量成为一个单位向量(长度为 1)矢量本身。只要向量的内容范围为正条目,这是可能的。 然而,由于我们不知道我们是否有正方向或负方向的向量(两者同样有效),我们不能在这里使用 sum。
相反,我们需要将其替换为 norm,matlab 的规范化方式。
function [eigvecs, eigvals] = findEigVecs(imvecs, T, D)
[U,eigvals,V] = svd( T );
eigvecs = [];
for i = 1:size(imvecs,2),
eigvec = D * U(:,i);
eigvec = eigvec ./ norm(eigvec);
eigvecs = [eigvecs, eigvec];
end
return
如果有人使用上述代码的某个版本,请注意随机面部函数会在 rgb-space 中给出太强的值。 将 createRandomFace 替换为以下内容:
stdev_vec = sqrt(diag(eigvals));
min_range = 0;
max_range = 2;
t = ((max_range - min_range)*rand(n,1)) .* stdev_vec + min_range;
new_face1 = meanval + (eigvecs * t);
new_face1 = reshape(new_face1, size(img));
figure;imagesc(new_face1./255);