Matlab 用奇异值分解代替协方差矩阵计算特征面

Matlab 用奇异值分解代替协方差矩阵计算特征面,matlab,image-processing,computer-vision,svd,Matlab,Image Processing,Computer Vision,Svd,我使用AT&T()中的n=40个面来尝试通过SVD生成特征面 首先,我计算平均向量: 然后,我从训练集中的每个向量中减去它,将新向量重新塑造成一个n×n(p*q)矩阵x的1×n(p*q)列向量,并计算一个矩阵x,使得x=(1/sqrt(n))*x。(这里的问题是:我在X中的所有结果都被四舍五入为0,从而产生了如下所示的eigenface的黑色图像结果) 然后我计算这个矩阵X的奇异值分解(SVD),并通过将酉矩阵的第一列重塑为p×q矩阵,尝试得到它的第一个特征面 然而,这是我的结果: 有人能在

我使用AT&T()中的n=40个面来尝试通过SVD生成特征面

首先,我计算平均向量:

然后,我从训练集中的每个向量中减去它,将新向量重新塑造成一个n×n(p*q)矩阵x的1×n(p*q)列向量,并计算一个矩阵x,使得
x=(1/sqrt(n))*x
。(这里的问题是:我在X中的所有结果都被四舍五入为0,从而产生了如下所示的eigenface的黑色图像结果)

然后我计算这个矩阵X的奇异值分解(SVD),并通过将酉矩阵的第一列重塑为p×q矩阵,尝试得到它的第一个特征面

然而,这是我的结果:

有人能在下面的代码中发现我的错误吗?任何答案都将不胜感激

n = 40;
%read images
A = double(imread('faces_training/1.pgm'));
f(:, :, 1) = A;
for j = 2:n
    f(:, :, j) = double(imread(['faces_training/',num2str(j),'.pgm']));
    A = A + f(:, :, j);
end
%calculate average
a = (1/n)*A;
%imshow(uint8(a))
for i = 1:n
%subtract from images
    x_vector(:, i) = reshape(f(:, :, i) - a, [], 1);
end
X = (1/sqrt(n))*x_vector;
%svd
[U S V] = svd(X);
B = reshape(U(:, 1), [size(a, 1) size(a, 2)]);
imshow(uint8(B))

做同样的事情,也有同样的问题。简单的回答是你必须规范化你的特征向量以得到一个好的图像。在规格化之前,您会注意到向量值非常接近0(可能是因为svd是如何完成的),这可能意味着它们接近黑色

不管怎样,在要变换的特征向量上使用这个方程:
newpixel[i,j]=(oldpoixel[i,j]-min(oldpoixel[:,j])/(max(oldpoixel[:,j])--min(oldpoixel[:,j])

它是否与
imshow(B)
一起工作,而不是
imshow(uint8(B))
?不,因为B基本上只是一个双倍数组<1,因此,如果它是一个介于0和1之间的双精度数组,则不应应用
uint8
,因为会得到所有零。无论是
imshow(B)
还是
imshow(uint8(255*B))
如果有效,我都应该指定。每个双精度都明显小于1(事实上,整个向量中的最大值为0.0271),因此它们最终都为0。我再次尝试了你的两个代码片段,只是为了确定,是的,它们都是黑色的。那么在计算
B
时,这可能是一个规范化问题。我已经添加了图像处理标签,因此您可以获得更多帮助谢谢!我模模糊糊地记得这也是我发现的问题——像素值太接近于0,所以我不得不在事后对它们进行变换。谢谢你简洁明了的回答!(欢迎来到SO:)