基於PCA和SVM的人臉識別
原始碼上傳到了我的github上,大家可以去免費下載https://github.com/tongxiaobin?tab=repositories
本文所用的是ORL人臉庫,由英國劍橋實驗室拍攝,共有40人,每人不同角度不同表情拍攝了10張,所以共有400個樣本資料,圖片尺寸為112*92,格式為pgm。本文將每人的前5張作為訓練集,後5張作為測試集。ORL人臉庫可在該網址下載https://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html
一、讀取人臉資料(向量化人臉容器)
function [faceContainer,label]=ReadFace(n_persons,flag)
% 當flag為0時,表示讀取訓練集,flag為1時,表示讀取測試集
% n_persons為多少人,label是人臉的標籤
% faceContainer是一個向量化人臉容器,即將每一張圖片轉成一行向量放入其每行中
%先隨便讀入一張圖片,得到其大小
I = imread('ORL\orl_faces\s1\1.pgm');
[M,N] = size(I);
label=zeros(n_persons*5,1);
faceContainer=zeros(n_persons*5,M*N);
for i=1:n_persons
%函式num2str(i)說明:將數字轉化為字元
facepath=strcat('ORL\orl_faces\s',num2str(i),'\'); %路徑因不同情況而定
temppath=facepath;
for j=1:5
facepath=temppath;
if flag==0
facepath=strcat(facepath,num2str(j));
else
facepath=strcat(facepath,num2str(j+5));
end
label((i-1)*5+j)=i;
facepath=strcat(facepath,'.pgm');
img=imread(facepath);
faceContainer((i-1)*5+j,:)=img(:)';
end
end
save('ORL\faceContainer','faceContainer');%儲存讀取的資料
二、PCA降維(該演算法在我的上一篇部落格主成分分析(PCA)中有所講解)
讀取的資料是110304的向量,把每一個畫素點當做一維特徵,故每張圖片有10304維,現對其進行降維。
%A為樣本矩陣,將其降至k維後的矩陣為pcaA,V為主成分分量
function [pcaA ,V]=fastPCA(A,k)
[m,n]=size(A);
%樣本均值,計算各列的均值
meanVec=mean(A);
%計算協方差矩陣的轉置 covMatT
%樣本矩陣中心化,每一維度減去該維度的均值,使得每一維度的均值為0
%repmat:Replicate Matrix複製和平鋪矩陣
Z= ( A-repmat(meanVec,m,1) );
covMatT =Z*Z'; %快速PCA
%計算covMatT的前k個特徵值和特徵向量
[V, ~]=eigs(covMatT,k); %V為m*k, k個特徵向量
%得到協方差矩陣(covMatT')的特徵向量
V=Z'*V;
%特徵向量歸一化為得到單位特徵向量
for i=1:k
V(:,i)=V(:,i)/norm(V(:,i)); %norm 為範數,預設為2範數(各分量的平方和 再開根號)
end
%投影降維至k維
pcaA=Z*V;
%儲存變換矩陣V和平均矩陣meanVec
save('ORL/PCA.mat','V','meanVec');
三、資料歸一化
特徵資料歸一化 ,因為對於不同的特徵,如果不歸一化是不具有比較性的,兩者不在一個量級上,比如說A體重70kg,身高1.75,B體重69kg,身高1.50,C體重65kg,身高1.74,SVM是基於距離算的,所以會把A和B看成相似的,而實際上A和C比較相似。
一般歸一化到[-1,1],即lTarget = -1,uTarget = 1。
function [ scaledface] = scaling( faceMat,lTarget,uTarget )
%faceMat需要進行規範化的影象資料,
[m,n]=size(faceMat);
scaledface=zeros(m,n);
upVec=zeros(1,n); %所有資料中每個特徵的最大值
lowVec=zeros(1,n);%所有資料中每個特徵的最小值
for i=1:n
lowVec(i)=min( faceMat(:,i) );
upVec(i)=max( faceMat(:,i) );
scaledface(:,i)=(faceMat(:,i) - lowVec(i) )/( upVec(i)- lowVec(i))*(uTarget-lTarget)+lTarget;
end
save('ORL/scaling.mat','upVec','lowVec');
四、對樣本進行訓練(SVM模型)
我是利用libsvm工具箱,特別簡單方便(由臺灣林智仁開發),首先下載libsvm工具箱,下載地址https://www.csie.ntu.edu.tw/~cjlin/libsvm/,進入頁面後,點選下圖圈的zip檔案下載。
下載解壓後,會有c++,python,matlab不同的資料夾即libsvm針對不同語言封裝的不同介面。我用的是matlab,首先開啟matlab軟體,依次點選主頁->設定路徑->新增幷包含子資料夾,將剛才解壓的matlab資料夾新增進來,最後一步複製解壓後的matlab資料夾的路徑到matlab編輯器路徑,在命令列視窗輸入make然後回車等待編譯完成即大功告成。
%第一個引數為標籤,第二個為訓練資料,第三個是個命令集合,-t表示核函式,-c為懲罰係數,-v為交叉驗證數
%-t為0時線性核,1多項式核,2徑向基函式(高斯),3sigmod核函式
model = svmtrain(label,scaledface,'-t 0 -c 1');
五、對測試集進行預測
%輸出的三個引數分別為預測的標籤,準確率,評估值(非分類問題用著),
%輸入為測試資料的標籤(這個可與可無,如果沒有,那麼預測的準確率accuracy就沒有意義了,
%如果有,那麼就可以通過這個值與預測出來的那個型別值相比較得出準確率accuracy,
%但是要說明一點的是,無論這個值有沒有,在使用的時候都得加上,即使沒有,也要隨便加上一個型別值,
%反正你也不管它對不對,這是函式使用所規定的的
[predict_label,accuracy,prob_estimates]=svmpredict(label,scaledface,model);
注意測試資料降維是在訓練集的特徵向量中降維,即testDataPca = (testData - meanVec)*V,測試資料歸一化也是在訓練集中進行的。
測試資料歸一化:
function [ testscaledface] = testscaling( faceMat,lTargB,uTargB )
% lowvec原來影象資料中的最小值
% upvec原來影象資料中的最大值
[m,n] = size(faceMat);
testscaledface = zeros(m,n);
load ORL/scaling.mat
for i=1:n
testscaledface(:,i)=(faceMat(:,i) - lowVec(i) )/( upVec(i)- lowVec(i))*(uTargB-lTargB)+lTargB;
end
主函式:
disp('讀取訓練資料...')
disp('......')
[train_faceContainer,train_label] = ReadFace(41,0);
disp('訓練資料PCA降維...')
disp('......')
[pcaA ,V]=fastPCA(train_faceContainer,20);
disp('訓練資料歸一化...');
disp('.........')
[ scaledface] = scaling( pcaA,-1,1 );
disp('SVM樣本訓練...')
model = svmtrain(train_label,scaledface,'-t 0 ');
disp('讀取測試資料...')
[test_faceContainer,test_label]=ReadFace(40,1);
disp('測試資料pca降維...')
disp('.......')
load 'ORL/PCA.mat'
testData = (test_faceContainer - repmat(meanVec,200,1)) * V;
disp('測試資料歸一化...')
disp('.......')
scaled_testData = testscaling( testData,-1,1);
disp('SVM樣本分類預測...')
disp('......')
[predict_label,accuracy,prob_estimates]=svmpredict(test_label,scaled_testData,model);
補充一:顯示主成分臉
function visualize(V)
%顯示主成分臉(變換空間中的投影向量,即單位特徵向量),這裡顯示前20個主成分臉,即將原始資料降至20維
figure
img=zeros(112,92);
for i=1:20
img(:)=V(:,i);
subplot(4,5,i);
imshow(img,[])
end
補充二:基於主成分分量的人臉重建
%k為重建至多少維
function rebuid(y,k)
%匯入平均矩陣meanVec和主成分向量V
load ORL/PCA.mat
temp = meanVec;
for i = 1:k
xi = (y - meanVec) * V(:,i);%某人臉y在第i維的投影值
yi = xi * V(:,i)';%某人臉y在第i維的向量值
temp = temp + yi ;%對該人臉投影到所有維的向量進行一個向量相加,得到該人臉向量的一個近似值
end
%顯示重建人臉
I = zeros(112,92);
I(:) = temp';
imshow(I,[]);
以第一個人臉為例,分別基於前50,100,150,200維重建後的人臉如下,可見原來的10304維人臉用150維左右就可重建出來:
補充三:實時識別
首先自拍10張自己的臉,轉換成pgm格式,尺寸歸一化為112*92,在ORL人臉庫中新建資料夾s41,將這10張圖片放裡面,現在對這41個人臉重新進行訓練,得到訓練好的模型model。
%改變影象尺寸和格式並儲存
%將自己的人臉照片先放在桌面
temp = 'C:\Users\Administrator\Desktop\';
for i = 1:10
path1 = strcat(temp,num2str(i),'.jpg');
I = imread(path1);
I = rgb2gray(I);
I = imresize(I,[112,92]);%改變影象尺寸
%先儲存在D盤下,然後去D盤全部剪下到ORL人臉庫中
path2 = strcat('D:\',num2str(i),'.pgm');
imwrite(I,path2); %儲存成pgm格式
end
開啟matlab應用程式裡的imageAcquision,可以預覽開始捕捉停止捕捉,設定幀數等,其右下角會對應生成程式碼,複製出來直接用即可。
%初始化這部分程式碼可用imageAcquision應用程式生成:
%建立視訊物件
vid = videoinput('winvideo', 1, 'YUY2_160x120');
%設定屬性值,持續不斷獲取影象
vid.FramesPerTrigger = Inf;
%開啟攝像頭
start(vid);
[faceContainer,label]=ReadFace(41,0);
[pcaA ,V]=fastPCA(faceContainer,20);
[ scaledface] = scaling( pcaA,-1,1 );
model = svmtrain(label,scaledface,'-t 0 ');
load ORL\PCA.mat
container = zeros(1,112*92);%一定要和訓練時一樣先初始化定義一個人臉容器,使其資料型別一樣,而不能直接轉化成double型
while 1
frame = getsnapshot(vid);%抓取影象
I = ycbcr2rgb(frame);%ycbcr是色彩空間的一種,由於我的計算機獲取影象是這種格式所以先轉換為rgb再轉換為gray
I = rgb2gray(I);
I = imresize(I,[112,92]);%尺寸歸一化
imshow(I);
container(1,:) = I(:)';
faceData = (container - meanVec)*V;%在訓練資料的特徵向量中降維
faceData = testscaling( faceData,-1,1 );%測試資料歸一化
[predict_label,accuracy,prob_estimates]=svmpredict(41,faceData,model);
if predict_label == 41
disp('識別正確:童小彬')
else
disp('識別錯誤')
end
if strcmp(get(gcf,'SelectionType'),'alt')%右鍵滑鼠事件
break;
end
end
stop(vid);%關閉攝像頭
實時識別還是挺準的,現擷取某一時刻的結果如下圖所示:
:
相關文章
- 基於卷積神經網路和tensorflow實現的人臉識別卷積神經網路
- 基於DNN的人臉識別中的反欺騙機制DNN
- 帶你玩轉OpenHarmony AI:基於Seetaface2的人臉識別AI
- 基於深度神經網路的人臉識別相關問題神經網路
- 基於 SVM 和增強型 PCP 特徵的和絃識別特徵
- 金融級別的人臉識別支付?
- 基於深度學習的人臉性別識別系統(含UI介面,Python程式碼)深度學習UIPython
- opencv python 基於SVM的手寫體識別OpenCVPython
- 基於卷積神經網路的人臉表情識別應用--AR川劇變臉(一)卷積神經網路
- SAP官方提供的人臉識別APIAPI
- 知物由學 | 基於DNN的人臉識別中的反欺騙機制DNN
- 一個簡單的人臉識別庫
- python ubuntu人臉識別 -1 SVM binary 分類器PythonUbuntu
- 基於二哈實現多人人臉學習和識別
- 基於膚色模型的人臉識別FPGA實現,包含tb測試檔案和MATLAB輔助驗證模型FPGAMatlab
- 基於卷積神經網路的人臉識別專案_使用Tensorflow-gpu+dilib+sklearn卷積神經網路GPU
- 基於Android平臺實現人臉識別Android
- [OpenCV實戰]1 基於深度學習識別人臉性別和年齡OpenCV深度學習
- 利用opencv 做一個簡單的人臉識別OpenCV
- 機器學習實戰-SVM模型實現人臉識別機器學習模型
- 【opencv3】 svm實現手寫體與人臉識別OpenCV
- 基於TensorflowLite的人聲識別在端上的實現
- 【專案】Python人臉識別(GUI介面)—— 基於pyopencvPythonGUIOpenCV
- 基於Python的人臉檢測與分類Python
- 基於Java實現的人臉識別功能,一切都為了寵粉(附原始碼)Java原始碼
- 一種基於隨機動作指令的人臉活體檢測技術,有效避免人臉識別系統被破解隨機
- 直播美顏SDK的人臉識別技術進階知識
- 用於星系的人臉識別:人工智慧為天文學帶來新工具人工智慧
- .NET 開源的功能強大的人臉識別 APIAPI
- Java 基於ArcFace人臉識別2.0 服務端DemoJava服務端
- 基於Python的人臉自動戴口罩系統Python
- 計算機視覺—人臉識別(Hog特徵+SVM分類器)(8)計算機視覺HOG特徵
- 基於celeba資料集和pytorch框架實現dcgan的人臉影像生成PyTorch框架
- 弱電智慧化系統中的人臉識別技術
- HanLP-基於HMM-Viterbi的人名識別原理介紹HanLPHMMViterbi
- 基於開源模型搭建實時人臉識別系統(五):人臉跟蹤模型
- 基於開源模型搭建實時人臉識別系統(四):人臉質量模型
- 基於WOA-SVM的乳腺癌資料分類識別演算法matlab模擬,對比BP神經網路和SVM演算法Matlab神經網路