matlab自带的人脸分类器,基于MATLAB,运用PCA+SVM的特征脸方法人脸识别
概述:
此文章將要描述一種基于MATLAB平臺,運(yùn)用PCA主成分分析方法對圖片數(shù)據(jù)進(jìn)行降維,運(yùn)用SVM支持向量機(jī)分類器對降維后的圖片數(shù)據(jù)進(jìn)行分類處理,從而達(dá)到人臉識別的目的。
首先要感謝以下幾篇文章的作者(后面引用會標(biāo)識文章標(biāo)號)
2.
PCA (主成分分析)詳解 (寫給初學(xué)者) 結(jié)合matlab(F),E篇列出了具體的數(shù)據(jù)供大家檢驗(yàn),大家可以根據(jù)數(shù)據(jù)來驗(yàn)證數(shù)學(xué)過程,簡單易懂。F篇與前篇有點(diǎn)相似,對初學(xué)者很有幫助。
4.淺談協(xié)方差矩陣(G)此篇文章對于大家了解協(xié)方差矩陣以及matlab實(shí)現(xiàn)很有作用。
準(zhǔn)備:
1.編程平臺:MATLAB。
首先你得保證你的機(jī)器上安裝有matlab,建議較高的版本。
2.libsvm工具箱。
本人在對第一篇文章中代碼關(guān)于SVM分類的部分沒有運(yùn)行成功,所以運(yùn)用了libsvm工具箱對樣本訓(xùn)練,測試,并沒有運(yùn)用第一篇文章的代碼,如果你能成功可忽略,但建議安裝此工具箱,其對SVM分類有很大幫助。如果你一樣沒有成功,這里推薦一個(gè)鏈接,有關(guān)于libsvm工具箱的安裝配置的視頻。
3.數(shù)據(jù):ORL人臉庫。
這個(gè)數(shù)據(jù)為已經(jīng)預(yù)處理的數(shù)據(jù),格式為pgm,屬于Linux格式,windows環(huán)境下無法直接打開,可以在matlab中打開,打開方式imshow(imread('圖片路徑'));數(shù)據(jù)是400張人臉圖片,屬于40個(gè)人,每個(gè)人10張,每張大小112*92像素,數(shù)據(jù)下載地址在第一篇文章中有,這里也給個(gè)鏈接,第四段兩個(gè)鏈接都可下載。
4.主成分分析法PCA。
主成分分析法是一種降維的方法,上面給出了幾個(gè)有用的鏈接,本文只給出代碼,以及代碼說明,關(guān)于原理,大家盡可參照上面幾個(gè)鏈接,寫得非常詳細(xì)也非常通俗。
5.SVM支持向量機(jī)分類器。
SVM支持向量機(jī)是一個(gè)二類分類器,但是本次人臉識別不僅只是分出兩類,而是需要分出40個(gè)類別。本人以前有過一點(diǎn)機(jī)器學(xué)習(xí)基礎(chǔ),所以在支持向量機(jī)原理的理解上沒有多大問題,如果讀者沒有SVM基礎(chǔ),可參考SVM入門(H),以及寫的非常給力的帖子,SVM三層境界(I)。
注:也許很多初學(xué)者看到這么多的資料,鏈接都已經(jīng)暈了,失去了學(xué)習(xí)的動力。先別灰心,稍后我會把代碼以及代碼運(yùn)行的結(jié)果和過程展示給大家,當(dāng)大家看到這些圖像的變換的美妙,就會有學(xué)習(xí)的興趣。
編程實(shí)現(xiàn):
以下將要展示的是幾個(gè).m文件的代碼,.m文件即是能在matlab上面打開運(yùn)行的代碼文件,可以在其中定義函數(shù),如果matlab的當(dāng)前路徑指定在含有這些.m文件的文件夾中,運(yùn)行時(shí)就可以調(diào)用這些文件中定義的函數(shù)。
首先展示第一個(gè).m文件,便是圖片數(shù)據(jù)讀取函數(shù)ReadFace.m
function?[f_matrix,realclass]=ReadFace(n_persons,flag)
%ORL人臉庫。pgm格式的圖片。40人,每人10幅圖,圖像大小為112*92像素。
%每個(gè)人有10幅照片,前5幅當(dāng)作訓(xùn)練集,后5幅當(dāng)作測試集
%
%輸入變量flag:
%???flag是一個(gè)標(biāo)識變量
%???當(dāng)flag為0時(shí),表示輸入為訓(xùn)練集,flag為1時(shí),表示輸入為測試集
%
%輸入變量n_persons:
%???n_persons標(biāo)志著你想要識別的人臉個(gè)數(shù)
%
%輸出變量realclass:
%???realclass是一個(gè)n_person*5行,1列的列向量。
%???realclass即是數(shù)據(jù)的標(biāo)簽,無論訓(xùn)練集測試集都進(jìn)行了標(biāo)簽處理
%
%輸出變量f_matrix:
%???f_matrix是一個(gè)n_person*5行,112*92列的矩陣
%???每一行便是每一張圖片的灰度數(shù)據(jù)
%???將每一張圖片列向量排成一個(gè)列向量后轉(zhuǎn)置得到放入f_matrix各行當(dāng)中
imgrow=112;imgcol=92;
global?imgrow;???%載入圖片行數(shù)
global?imgcol;????%載入圖片列數(shù)
realclass=zeros(n_persons*5,1);
f_matrix=zeros(n_persons*5,imgrow*imgcol);
for?i=1:n_persons
%路徑設(shè)置
%函數(shù)num2str(i)說明:將數(shù)字轉(zhuǎn)化為字符
facepath=strcat('F:\MATLAB人臉識別\Face\facedata\s',num2str(i),'\');??%路徑因不同情況而定
cachepath=facepath;
for?j=1:5
facepath=cachepath;
if?flag==0
%函數(shù)strcat(a,b,...)說明:將輸入字符a,b...連接成單個(gè)字符
facepath=strcat(facepath,num2str(j));
else
facepath=strcat(facepath,num2str(j+5));
end
realclass((i-1)*5+j)=i;
facepath=strcat(facepath,'.pgm');
%函數(shù)imread說明:讀取輸入路徑的圖片,將每個(gè)像素灰度值保存在輸出的矩陣中
img=imread(facepath);
f_matrix((i-1)*5+j,:)=img(:)';
end
end
end
代碼當(dāng)中有著詳細(xì)的注釋,代碼與第一篇文章中提供的代碼大同小異,根據(jù)本人情況修改了一點(diǎn)路徑的代碼,以及增加了對訓(xùn)練集標(biāo)簽的標(biāo)識,且增加了注釋。現(xiàn)在對代碼進(jìn)行一些說明。
代碼第一行有對函數(shù)的申明,function []=ReadFace(),中括號為函數(shù)的輸出,小括號為函數(shù)的輸入,函數(shù)名與文件名一致,一個(gè).m文件當(dāng)中可以有多個(gè)函數(shù)申明,但當(dāng)外面的函數(shù)想要調(diào)用這個(gè)文件中的函數(shù)時(shí),只能調(diào)用與文件名一致的函數(shù)。所以這個(gè)文件叫ReadFace.m。
何為訓(xùn)練集以及測試集?
在機(jī)器學(xué)習(xí)方法當(dāng)中,分為監(jiān)督學(xué)習(xí),非監(jiān)督學(xué)習(xí),強(qiáng)化學(xué)習(xí)。而SVM支持向量機(jī)是一種監(jiān)督學(xué)習(xí)的算法。所謂監(jiān)督學(xué)習(xí),就是給予機(jī)器一套題目并附上標(biāo)準(zhǔn)答案,讓它去做題,自己總結(jié)了一套做題的方法(這些方法就是建立的模型),它在根據(jù)已經(jīng)學(xué)習(xí)好的方法來做一套新的題目,把題目做對,盡可能打高分。
訓(xùn)練集就是給予機(jī)器的一套題目及標(biāo)準(zhǔn)答案,測試集就是給它的一套新題。而訓(xùn)練集有標(biāo)簽和數(shù)據(jù)之分,標(biāo)簽就是標(biāo)準(zhǔn)答案,標(biāo)簽有著1和0,就表示這些訓(xùn)練集中有兩類,像我們的人臉數(shù)據(jù)有40種人臉,我們就用1到40來表示。數(shù)據(jù)就是有著多維的表征一個(gè)事物的數(shù)據(jù),就是給機(jī)器的第一套題目。測試集也有數(shù)據(jù),就是后面給機(jī)器測試的題目,如果測試集原本含有標(biāo)簽,這些標(biāo)簽就可以作為標(biāo)準(zhǔn)給機(jī)器前面訓(xùn)練總結(jié)的方法(模型)打分,查看準(zhǔn)確率。
在這個(gè)人臉庫中,每個(gè)人有10張圖,我們將前5張作為訓(xùn)練集,就有200張圖。用一個(gè)矩陣來表示這200張圖,就形成了一個(gè)200*10304的矩陣。后5張圖用來當(dāng)測試集,可以看代碼中的說明。
當(dāng)flag為0時(shí),找出訓(xùn)練集的標(biāo)簽realclass(200*1的矩陣)與數(shù)據(jù)f_matrix(200*10304的矩陣).
當(dāng)flag為1時(shí),就是找出測試集來測試分類效果,得出準(zhǔn)確率。
SVM訓(xùn)練的目的就是利用訓(xùn)練集找到這么一個(gè)分類函數(shù)(模型),再在測試集中檢測。關(guān)于SVM的具體原理查看上面的H和I篇。
--------------------------------分割線---------------------------------------
第二個(gè).m文件的文件名為fastPCA.m,用于將樣本進(jìn)行降維處理,參考上面主成分分析PCA文章D,E,F篇,上面有通俗且具體的闡述。
function?[?pcaA,V]?=?fastPCA(?A,k,mA)
%快速PCA,主成份分析
%輸入:A-樣本矩陣,每行是一個(gè)樣本,列是樣本的維數(shù)
%????????????k-降至k維
%???????????mA-圖像矩陣f_matrix每一列的均值排成一個(gè)行向量,即mean(f_matrix)
%輸出:pacA-降維后,訓(xùn)練樣本在低維空間中的系數(shù)坐標(biāo)表示
%????????????V-主成分分量,即低維空間當(dāng)中的基
%
m=size(A,1);??%m為讀取圖片的張數(shù)
Z=(A-repmat(mA,m,1));??%中心化樣本矩陣
%一般用中心化的矩陣代替原矩陣。為什么?因?yàn)閷?shù)據(jù)集的均值歸零(預(yù)處理),也就是只取數(shù)據(jù)的偏差部分
T=Z*Z';
[V1,D]=eigs(T,k);%計(jì)算T的最大的k個(gè)特征值和特征向量
V=Z'*V1;?????????%協(xié)方差矩陣的特征向量
%這一點(diǎn)是關(guān)鍵步驟,很可能很多初學(xué)者無法理解:
%按理來講,協(xié)方差矩陣的計(jì)算公式為(假設(shè)上面中心化的Z已經(jīng)求出):
%V?=?(Z'*Z)./(size(Z,1)-1)(先不管單位化,V=Z'*Z)(這里是一行為一個(gè)樣本,一列為一個(gè)維數(shù)的情況)
%協(xié)方差矩陣是N*N的方陣,維數(shù)N應(yīng)該與原圖片f_matrix(200*10304)維數(shù)相等
%f_matrix中行數(shù)200為圖片個(gè)數(shù),列數(shù)10304為維數(shù)
%那為什么這里是T=Z*Z',再求T的K個(gè)最大特征值和特征向量V1,再用V=Z'*V1來求協(xié)方差矩陣特征向量呢?
%因?yàn)槲覀內(nèi)绻骎=Z'*Z這個(gè)V就是一個(gè)10304*10304的矩陣,MATLAB奔潰了,太復(fù)雜
%我們可以這樣看P^-1*(Z*Z')*P=S等價(jià)于P^-1*(Z')^-1*Z'*Z*Z'*P=S等價(jià)于(Z'*P)^-1*(Z'*Z)*(Z'*P)=S
%注:P^-1是P的逆矩陣,(Z')^-1為Z'的逆矩陣,類推,建議大家寫在紙上
%最后一個(gè)式子可以看出Z'*Z的特征向量矩陣為Z'*P,而Z*Z'的特征向量矩陣為P,即為程序中的V1
%這是一種簡便方法,為的就是避免像V=Z'*Z這種維數(shù)太高的計(jì)算。
%可查看C篇文章步驟4
for?i=1:k???????%特征向量單位化
l=norm(V(:,i));
V(:,i)=V(:,i)/l;
end
%單位化后的V才能是真正的低維空間的基,需要滿足正交化單位化兩個(gè)條件
%具體原因參考D篇文章
pcaA=Z*V;???????%線性變換,降至k維??,將中心化的矩陣投影到低維空間的基中,V就是低維空間的基
%pcaA為低維空間的坐標(biāo)表示,即一個(gè)圖像的判斷依據(jù)
end
代碼與第一篇文章代碼沒有不同,只是多加了注釋,便于大家理解。
下面貼出原圖,均值臉以及兩者的差值圖:
-------------------------------------------------分割線---------------------------------------------------------
第三個(gè)文件為scaling.m文件,其中的代碼與原作者代碼無二。略加注釋。function?[?scaledface]?=?scaling(?faceMat,lowvec,upvec?)
%特征數(shù)據(jù)規(guī)范化
%即是將同一個(gè)樣本中的不同維度歸一化
%因?yàn)橐驗(yàn)閷τ诓煌膶傩?#xff0c;如果不歸一化是不具有比較性的,兩者不在一個(gè)量級上
%輸入——faceMat需要進(jìn)行規(guī)范化的圖像數(shù)據(jù),
%????????????????lowvec原來圖像數(shù)據(jù)中的最小值
%????????????????upvec原來圖像數(shù)據(jù)中的最大值
upnew=1;
lownew=-1;
[m,n]=size(faceMat);
scaledface=zeros(m,n);
for?i=1:m
scaledface(i,:)=lownew+(faceMat(i,:)-lowvec)./(upvec-lowvec)*(upnew-lownew);
%將圖像數(shù)據(jù)中一個(gè)樣本的不同維度的值,最小值和最大值規(guī)范到-1和1,其他值按比例規(guī)范到(-1,1)
end
end
-----------------------------------------------------分割線-----------------------------------------------------
第四個(gè)文件visualize.m中為顯示特征臉的代碼,比較簡單,并附上顯示結(jié)果。function?visualize(?B?)
%顯示特征臉(變換空間中的基向量,即單位特征向量)
%輸入:B——每列是個(gè)主成分分量,顯示的就是低維中每個(gè)基組成的圖像
%?????k——主成分的維數(shù)
global?imgrow;
global?imgcol;
figure
img=zeros(imgrow,imgcol);
for?i=1:20
img(:)=B(:,i);
subplot(4,5,i);
imshow(img,[])
end
end
因?yàn)榻抵?0維,所以其在低維中的基便是這20張?zhí)卣髂?#xff0c;其他所有的經(jīng)過了降維的臉都可以由這20張?zhí)卣髂樉€性表示,即我們要進(jìn)行臉部識別時(shí),把選擇要識別的臉進(jìn)行降維處理后,再右乘這些基(特征臉)所構(gòu)成的矩陣,就能得到這些臉在低維中的線性表示。這些表示就是識別的依據(jù)。
特征臉截圖:
-------------------------------------------------分割線---------------------------------------------------------
第五個(gè)文件recognition.m中的代碼,在A篇文章當(dāng)中沒有,是我自己編寫的臉部識別的小程序,比較簡單,沒有像A篇文章中一樣做GUI界面。function?recognition(mA,V,model)
%函數(shù)作用:人臉識別模塊,利用已經(jīng)建好的模型,重新找一個(gè)樣本進(jìn)行識別
%輸入:
%???????????mA-均值
%???????????V-協(xié)方差矩陣特征向量
%???????????model-通過SVM對訓(xùn)練集訓(xùn)練得出的已經(jīng)建立好的模型
%%
global?imgrow;
global?imgcol;
%%
%彈出輸入框,選擇要識別的圖片
select_person_num=str2double(cell2mat(inputdlg('請輸入想要識別的人的編號(總共40個(gè)人):')));%總共40個(gè)人
select_img_num=str2double(cell2mat(inputdlg('請輸入此人圖片的編號(總共10張):')));%總共10張圖
%%
%對圖片信息進(jìn)行處理,化為1*10304的行向量
disp('讀取選擇的圖片...')
select_facepath=strcat('F:\MATLAB人臉識別\Face\facedata\s',num2str(select_person_num),'\',num2str(select_img_num),'.pgm');
select_img=imread(select_facepath);
select_matrix=zeros(1,imgrow*imgcol);
select_matrix(1,:)=select_img(:)';
select_matrix=(select_matrix-mA)*V;%PCA降維后的低維表示
%%
%圖形歸一化
disp('規(guī)范化選擇的圖片...')
select_matrix?=?scaling(?select_matrix,min(select_matrix),max(select_matrix));
%%
%測試選擇的圖片,accuracy只有兩個(gè)值,100%表示匹配正確,0%表示匹配錯(cuò)誤
disp('測試選擇的圖片...')
[select_predict_label,accuracy,decision_values]=svmpredict(select_person_num,select_matrix,model);
%%
%顯示原有圖片和匹配圖片進(jìn)行比較
disp('顯示選擇的圖片...')
figure(2);
subplot(1,2,1);imshow(select_img);title('你選擇的圖片');
subplot(1,2,2);
imshow(imread(strcat('F:\MATLAB人臉識別\Face\facedata\s',num2str(select_predict_label),'\',num2str(1),'.pgm')));
title('匹配的圖片');
程序運(yùn)行到此會彈出輸入框,讓用戶選擇想要識別的圖片,當(dāng)Accuracy=100%表示識別正確,如果Accuracy=0%表示識別錯(cuò)誤。
? ? ? ? ??
? ? ? ? ??
輸入編碼后選擇的圖片,以及匹配到的圖片對比。
-------------------------------------------------分割線---------------------------------------------------------
第六個(gè)文件face.m中的代碼為主程序。讀者想要看到整個(gè)效果,只需要將此文件中的程序全部選中按F9即可運(yùn)行。
注:我的SVM分類器是用libsvm工具箱當(dāng)中的函數(shù)實(shí)現(xiàn)的兩個(gè)關(guān)鍵函數(shù)便是svmtrain和svmpredict,核函數(shù)選用線性核函數(shù)。
以上暫時(shí)是初稿,肯定還有很多需要修改的地方,如果讀者有什么疑問或是看到什么錯(cuò)誤,希望能留言,我會加以請教。大家相互學(xué)習(xí),相互進(jìn)步。
轉(zhuǎn)自:http://blog.csdn.net/yb536/article/details/40586695
總結(jié)
以上是生活随笔為你收集整理的matlab自带的人脸分类器,基于MATLAB,运用PCA+SVM的特征脸方法人脸识别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android tag 快捷_Andro
- 下一篇: linux c fifo阻塞写和非阻塞写