matlab PCA-SVD简单地实现特征脸方法(Eigenface)

来源:互联网 发布:侠盗飞车3罪恶都市mac 编辑:程序博客网 时间:2024/04/30 19:20

本人大三机械专业,自学图像处理,在学习过程中CSDN里的文章让我收益颇丰。这是我第一次写博客文章有可能存在很多漏洞,希望大家包涵。

这两天在学习PCA在人脸识别里的作用,并试图用matlab实现,在做到eigenface的时候由于对线性代数和SVD分解的半知不解,所以一直不能实现图像的正确匹配。网上的文章没有直接解决我遇到的困难,所以写一篇文章,希望给后来者一些提示,以此少走一些弯路。

在其他很多文章里都详细介绍了PCA和SVD的原理,我这里就不在赘述,而是直接解释怎么用matlab代码实现这个步骤。

(1)、假设我们现在有待匹配数据的集合rawFaceMatrix,其中假设size(rawFaceMatrix)= 12000*90,rawFaceMatrix的每一列都是一张unroll的图片,有90行代表有90张图片。现在我们要求出这个矩阵的平均值即为平均脸,并且将数据减去这个平均值(This will prevent PCA from representing patterns that are the same in every image.)


    meanFace = zeros(size(rawFaceMatrix,1),1);    meanFace = mean(rawFaceMatrix,2);    A = zeros(size(rawFaceMatrix));    A = rawFaceMatrix - repmat(meanFace,1,size(rawFaceMatrix,2));

获得的A矩阵就是减去平均脸后的矩阵,这也是我们后续要比对的数据库了。

(2)、给定一张相同大小的图片testImg,size(testImg)= 100*120,我们现在把它由一行变成一列,同样的减去平均脸。

   

    unroll_img = testImg(:);    testImg = unroll_img - meanFace;

(3)、对A矩阵即为数据库进行SVD分解以压缩数据,我这里给出一个matlab的子程序doPCA.m。


function [prinComponents, weightCols] = doPCA(A, numComponentsToKeep)    weightCols = zeros(numComponentsToKeep, size(A,2));    prinComponents = zeros(size(A,1), numComponentsToKeep);    [U,S,V] = svd(A,'econ'); %it is much more efficient when we only need the top few components, as we do here.    U = U(:,1:numComponentsToKeep);    S = S(1:numComponentsToKeep,1:numComponentsToKeep);    V = V(:,1:numComponentsToKeep);    prinComponents = U;    weightCols = S*V';end


输入A和需要取的特征值个数numComponentsToKeep,返回prinComponents(基底)和weightCols(在基底上投影的权重矩阵)。相关线性代数内容不再赘述。

(4)、求出我们需要对比的图片在上述基底上的投影,这样我们就能将其与数据库里的图像进行对比(也就是跟weightCols进行对比)。


test_prinComponents = prinComponents\testImg;

test_prinComponents即为对比图像在上述基底上的投影,注意我们在这里用了matlab里特有的\运算,大大简化了求解过程,这是其他语言所不能比拟的。

(5)、现在我们已经将待对比图片和数据库都进行了简化处理,它们之间可以直接求欧氏距离,我们取最小值就能得到最优解。这里给一个子程序求欧氏距离跟对应的index。


function [minDist, indexOfClosest] = indexOfClosestColumn(A, testColumn)    n = size(A,2);    minDist = Inf;    for i = 1 : n        temp = sum((A(:,i)-testColumn).^2);        dist = sqrt(temp);        if dist < minDist            minDist = dist;            indexOfClosest = i;        end    end    end

现在我们用一条简单的语句就能得到最优解的index了。


[minDist, indexOfClosestMatch] = indexOfClosestColumn(weightCols, test_prinComponents);

再配合一条显示语句就能显示最优解的图片:

viewFace( rawFaceMatrix(:,indexOfClosestMatch), imgHeight); 


以下为viewFace.m。


function viewFace( faceColumn, imgHeight)    imshow(reshape(faceColumn,imgHeight, []),[0 255]);end


至此简单的matlab代码实现主成分分析在人脸识别中的应用就完成了。(将其中doPCA替换成相应的Fisherface代码就能实现Fisherface的功能)


0 0