人臉識別之特徵臉方法(Eigenface)

2021-02-18 機器視覺

限時乾貨下載:關注我們「機器視覺」,回復「資料」獲取獲取機器視覺教程,行業報告等資源,百度盤群組分享連結更新時間:2016-10-12,失效請在文末留言,不要在後臺留言

 轉自:http://blog.csdn.net/zouxy09,zouxy09@qq.com

      因為需要,花了一點時間寫了下經典的基於特徵臉(EigenFace)的人臉識別方法的Matlab代碼。這裡僅把該代碼分享出來。其實,在較新版本的OpenCV中已經提供了FaceRecognizer這一個類,裡面不僅包含了特徵臉EigenFace,還有FisherFace和LBPHFace這三種人臉識別方法,有興趣的可以參考OpenCV的API手冊,裡面都有很詳細的使用例程了。

 

一、特徵臉

      特徵臉EigenFace從思想上其實挺簡單。就相當於把人臉從像素空間變換到另一個空間,在另一個空間中做相似性的計算。這麼說,其實圖像識別的基本思想都是一樣的,首先選擇一個合適的子空間,將所有的圖像變換到這個子空間上,然後再在這個子空間上衡量相似性或者進行分類學習。那為什麼要變換到另一個空間呢?當然是為了更好的做識別或者分類了。那為什麼變換到一個空間就好識別或者分類了呢?因為變換到另一個空間,同一個類別的圖像會聚到一起,不同類別的圖像會距離比較遠,或者在原像素空間中不同類別的圖像在分布上很難用個簡單的線或者面把他們切分開,然後如果變換到另一個空間,就可以很好的把他們分開了。

有時候,線性(分類器)就可以很容易的把他們分開了。那既然人類看起來同類的圖像本來就是相似的,不同類的圖像就不太相似,那為什麼在原始的像素空間他們同類不會很近,不同類不會很遠,或者他們為什麼不好分開呢?因為圖像各種因素的影響,包括光照、視角、背景和形狀等等不同,會造成同一個目標的圖像都存在很大的視覺信息上的不同。如下圖所示。

       世界上沒有存在任何兩片完全相同的葉子,雖然他們都是葉子。萬千世界,同一類事物都存在共性,也存在個性,這就是這個世界多彩的原因。那怎麼辦呢?很自然,只要在我們想要的粒度上把同一類目標的共性找出來就好了,而且這個共性最好和我們要區分的類是不一樣的。什麼叫我們想要的粒度?我理解和我們的任務相關的。例如我們要區分人和車,那人的共性就是有臉、有手、有腳等等。但如果我們要區分亞洲人和非洲人,那麼亞洲人的共性就是黃色皮膚等等。

      可以試著想像,上帝把世界萬物組織成一個樹狀結構,樹的根就是萬物之源,下一層可以分成生物和非生物,再下一層將生物分為……(囧,想像不到),直到最底層,萬物,你我,為樹的一片普通得再普通的葉子。樹越往下,粒度越小,分類越細(哈哈,自己亂扯的)。停!廢話多了點,跑題了,回到剛才的問題,重頭戲來了,要變換到什麼空間,才具備上述這種良好類內相似、類間區分的效果?到這,我就只能say sorry了。計算機視覺領域發展了幾十年,就為了這一個問題傾注了無數研究者的智慧與心血。當然了,也誕生和孕育了很多經典和有效的解答。(個人理解,上述說的實際上就是特徵提取)。從一開始的顏色特徵(顏色直方圖)、紋理特徵(Harr、LBP、HOG、SIFT等)、形狀特徵等到視覺表達Bag of Words,再到特徵學習Deep Learning,技術的發展總能帶給人希望,曙光也越來越清晰,但路還很遠,是不?      

       扯太多了,嚴重離題了。上面說到,特徵臉EigenFace的思想是把人臉從像素空間變換到另一個空間,在另一個空間中做相似性的計算。EigenFace選擇的空間變換方法是PCA,也就是大名鼎鼎的主成分分析。它廣泛的被用於預處理中以消去樣本特徵維度之間的相關性。當然了,這裡不是說這個。EigenFace方法利用PCA得到人臉分布的主要成分,具體實現是對訓練集中所有人臉圖像的協方差矩陣進行本徵值分解,得對對應的本徵向量,這些本徵向量(特徵向量)就是「特徵臉」。每個特徵向量或者特徵臉相當於捕捉或者描述人臉之間的一種變化或者特性。這就意味著每個人臉都可以表示為這些特徵臉的線性組合。實際上,空間變換就等同於「搞基」,原始像素空間的基就是單位「基」,經過PCA後空間就是以每一個特徵臉或者特徵向量為基,在這個空間(或者坐標軸)下,每個人臉就是一個點,這個點的坐標就是這個人臉在每個特徵基下的投影坐標。哦噢,說得有點繞。

      下面就直接給出基於特徵臉的人臉識別實現過程:

1)將訓練集的每一個人臉圖像都拉長一列,將他們組合在一起形成一個大矩陣A。假設每個人臉圖像是MxM大小,那麼拉成一列後每個人臉樣本的維度就是d=MxM大小了。假設有N個人臉圖像,那麼樣本矩陣A的維度就是dxN了。

2)將所有的N個人臉在對應維度上加起來,然後求個平均,就得到了一個「平均臉」。你把這個臉顯示出來的話,還挺帥的哦。

3)將N個圖像都減去那個平均臉圖像,得到差值圖像的數據矩陣Φ。

4)計算協方差矩陣C=ΦΦT。再對其進行特徵值分解。就可以得到想要的特徵向量(特徵臉)了。

5)將訓練集圖像和測試集的圖像都投影到這些特徵向量上了,再對測試集的每個圖像找到訓練集中的最近鄰或者k近鄰啥的,進行分類即可。

      算法說明白了都是不明白的,所以還是得去看具體實現。因此,可以對照下面的代碼來弄清楚這些步驟。

      另外,對於步驟4),涉及到求特徵值分解。如果人臉的特徵維度d很大,例如256x256的人臉圖像,d就是65536了。那麼協方差矩陣C的維度就是dxd=65536x65536。對這個大矩陣求解特徵值分解是很費力的。那怎麼辦呢?如果人臉的樣本不多,也就是N不大的話,我們可以通過求解C』=ΦTΦ矩陣來獲得同樣的特徵向量。可以看到這個C』=ΦTΦ只有NxN的大小哦。如果N遠遠小於d的話,那麼這個力氣就省得很值了。那為什麼求解C』=ΦTΦ矩陣的特徵向量可以獲得C=ΦΦT的特徵向量?萬眾矚目時刻,數學以完美舞姿登上舞臺。證明如下:

      其中,ei是C』=ΦTΦ的第i個特徵向量,vi是C=ΦΦT的第i個特徵向量,由證明可以看到,vi=Φei。所以通過求解C』=ΦTΦ的特徵值分解得到ei,再左乘Φ就得到C=ΦΦT的特徵向量vi了。也就是我們想要的特徵臉。

 

二、Matlab實現

      下面的代碼主要是在著名的人臉識別資料庫YaleB(http://lib.csdn.net/base/mysql)中進行實現。用的是裁切後的人臉資料庫,可以點擊CroppedYale(http://vision.ucsd.edu/extyaleb/CroppedYaleBZip/CroppedYale.zip)下載。共有38個人的人臉,人臉是在不同的光照下採集的,每個人臉圖像是32x32個像素。實驗在每一個的人臉圖像中隨機取5個作為訓練圖像,剩下的作為測試圖像。當然了,實際過程中這個過程需要重複多次,然後得到多次準確率的均值和方差才有參考意義,但下面的demo就不做這個處理了。計算相似性用的是歐氏距離,但編程實現的時候為了加速,用的是簡化版,至於如何簡化的,考驗你的時候到了。

[cpp] view plain

% Face recognition using eigenfaces  

  

close all, clear, clc;  

  

%% 20 random splits  

num_trainImg = 5;  

showEigenfaces = true;  

  

%% load data  

disp('loading data...');  

dataDir = './CroppedYale';  

datafile = 'Yale.mat';  

if ~exist(datafile, 'file')  

    readYaleDataset(dataDir, datafile);  

end  

load(datafile);  

  

%% Five images per class are randomly chosen as the training  

%% dataset and remaining images are used as the test dataset  

disp('get training and testing data...');  

num_class = size(unique(labels), 2);  

trainIdx = [];  

testIdx = [];  

for i=1:num_class  

    label = find(labels == i);  

    indice = randperm(numel(label));  

    trainIdx = [trainIdx label(indice(1:num_trainImg))];  

    testIdx = [testIdx label(indice(num_trainImg+1:end))];  

end  

  

%% get train and test data  

train_x = double(data(:, trainIdx));  

train_y = labels(trainIdx);  

test_x = double(data(:, testIdx));  

test_y = labels(testIdx);  

  

%% computing eigenfaces using PCA  

disp('computing eigenfaces...');  

tic;  

[num_dim, num_imgs] = size(train_x);   %% A: #dim x #images  

avg_face = mean(train_x, 2);             %% computing the average face  

X = bsxfun(@minus, train_x, avg_face); %% computing the difference images  

  

%% PCA  

if num_dim <= num_imgs   

    C = X * X';  

    [V, D] = eig(C);  

else  

    C = X' * X;   

    [U, D] = eig(C);  

    V = X * U;  

end  

eigenfaces = V;  

eigenfaces = eigenfaces ./ (ones(size(eigenfaces,1),1) * sqrt(sum(eigenfaces.*eigenfaces)));  

toc;  

  

%% visualize the average face  

P = sqrt(numel(avg_face));  

Q = numel(avg_face) / P;  

imagesc(reshape(avg_face, P, Q)); title('Mean face');  

colormap('gray');  

  

%% visualize some eigenfaces  

figure;  

num_eigenfaces_show = 9;  

for i = 1:num_eigenfaces_show  

    subplot(3, 3, i)  

    imagesc(reshape(eigenfaces(:, end-i+1), P, Q));  

    title(['Eigenfaces ' num2str(i)]);  

end  

colormap('gray');  

  

%% transform all training images to eigen space (each column for each image)  

disp('transform data to eigen space...');  

X = bsxfun(@minus, train_x, avg_face);  

T = eigenfaces' * X;  

  

%% transform the test image to eigen space  

X_t = bsxfun(@minus, test_x, avg_face);  

T_t = eigenfaces' * X_t;  

  

%% find the best match using Euclidean distance  

disp('find the best match...');  

AB = -2 * T_t' * T;       % N x M  

BB = sum(T .* T);         % 1 x M  

distance = bsxfun(@plus, AB, BB);        % N x M  

[score, index] = min(distance, [], 2);   % N x 1  

  

%% compute accuracy  

matchCount = 0;  

for i=1:numel(index)  

    predict = train_y(index(i));  

    if predict == test_y(i)  

        matchCount = matchCount + 1;  

    end  

end  

  

fprintf('**************************************\n');  

fprintf('accuracy: %0.3f%% \n', 100 * matchCount / numel(index));  

fprintf('**************************************\n');  

      下面是將CroppedYale的圖像讀入matlab的代碼。

[cpp] view plain

function readYaleDataset(dataDir, saveName)  

    dirs = dir(dataDir);  

    data = [];  

    labels = [];  

    for i = 3:numel(dirs)  

        imgDir = dirs(i).name;  

        imgDir = fullfile(dataDir, imgDir);  

        imgList = dir(fullfile(imgDir, '*.pgm'));  

        for j = 1:numel(imgList)  

            imgName = imgList(j).name;  

            if strcmp('Ambient.pgm',  imgName(end-10:end))  

                continue;  

            end  

            im = imread(fullfile(imgDir, imgName));  

            if size(im, 3) ==3  

                im = rgb2gray(im);  

            end  

            im = imresize(im, [32 32]);  

            im = reshape(im, 32*32, 1);  

            data = [data im];  

        end  

        labels = [labels ones(1, numel(imgList)-1) * (i-2)];  

    end  

    save(saveName, 'data', 'labels');  

end  

 

三、實驗結果

      首先來個帥帥的平均臉:

      然後來9個帥帥的特徵臉:

      在本實驗中,實驗結果是30.126%左右。如果加上了某些預處理,這個結果就可以跑到62%左右。只是這個預處理我有點解析不通,所以就沒放在demo上了。

      本文如果有什麼不對的地方,還望大家指正。


限時乾貨下載:關注我們「機器視覺」,回復「資料」獲取機器視覺教程,行業報告等資源。持續更新中。。。

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >

如何分享到朋友圈點擊右上角「...」 三個點,在彈出菜單選擇「分享到朋友圈」機器視覺--訂閱號』機器視覺『公眾號:機器視覺,工業自動化,機器人,圖像處理技術等領域新媒體信息平臺。
熱門文章推薦

回復下面數字,獲取相關文章:

001:計算機視覺領域研究資源及期刊、會議介紹

002:德國kuka機器人與世界冠軍桌球對決

003:人臉檢測的C/C++原始碼

004:人工智慧眼中的世界,竟然如此詭(魔)異(性)?!

005:機器人視覺中的物體表達問題-攝像機標定-視覺計算理論

006:三維計算機視覺技術

007:無奈與迷茫-30歲以上電子工程師請進

008:逆天科技小製作 自製迷你「磁懸浮列車」玩具方法圖解,快動手給孩子做一個

009:Google 以圖搜圖 - 相似圖片搜索原理 - Java實現

010:關於機器學習中的一些數學方法

011:雙遠心工業鏡頭的原理簡述

012:哥們花20萬從德國帶回來一工具箱,亮瞎了!!全鋁頭盔一次成型!!

013:工業相機在汽車零部件檢測中的應用

相關焦點

  • dlib應用之人臉識別
    一win10環境安裝使用dlib庫進行人臉識別,首先要安裝dlib。dlib庫的安裝有依賴庫,包括VS和Cmake。,使用shape_predictor_68_face_landmarks.dat特徵數據預測人臉特徵數值,開啟筆記本自帶的攝像頭cap。
  • 人臉識別算法分析原理
    基於這種考慮,Atick提出基於局部特徵的人臉特徵提取與識別方法。這種方法在實際應用取得了很好的效果,它構成了FaceIt人臉識別軟體的基礎。人臉識別算法分析3. 特徵臉方法(Eigenface或PCA)
  • 使用Python+OpenCV+Dlib實現人臉檢測與人臉特徵關鍵點識別
    我們可以將這些信息作為一個預處理步驟來完成,例如捕捉照片中人物的人臉(手動或通過機器學習),創建效果來「增強」我們的圖像(類似於Snapchat等應用程式中的效果),對人臉進行情感分析等等。今天我們將通過引入DLib和從圖像中提取面部特徵來將其提升到一個新的水平。
  • 【附完整代碼:AI實戰】動手編寫人臉識別
    人臉識別在現實生活中有非常廣泛的應用,例如iPhone X的識別人臉解鎖屏幕、人臉識別考勤機、人臉識別開門禁、刷臉坐高鐵,還有識別人臉虛擬化妝
  • 人臉識別簡介(使用Python代碼)
    人臉識別已經在我們的生活中處處可見——無論是政府布置在大街小巷的「天眼」,還是手機軟體中用於驗證用戶個人身份的確認手段,刷臉解鎖、刷臉支付……每個人與生俱來的這張「獨一無二」的臉正在取代數字密碼,成為虛擬世界中的身份證明。
  • 硬核科普人臉識別,讓你看的清清楚楚明明白白
    「刷臉」,顧名思義,背後是一項關鍵技術:人臉識別。別看這兩年因為在智慧型手機上的使用而大熱,其實人臉識別技術最早的研究還要追溯到20世紀50年代,當時已經有科學家在研究人臉輪廓的提取方法,但受限於技術水平,這項技術的相關研究一度停滯,直到20世紀80年代,人臉識別的方法才有了新的突破,神經生理學、腦神經學、視覺等相關知識被引入,人臉識別進入了新的發展階段。
  • 人臉識別:原理與應用
    近年來,人臉識別被廣泛用於金融、社保、電商、安防等領域。
  • 10行代碼實現python人臉識別
    ↑ 關注 + 星標 ~ 有趣的不像個技術號什麼是人臉識別人臉識別,是基於人的臉部特徵信息進行身份識別的一種生物識別技術。用攝像機或攝像頭採集含有人臉的圖像或視頻流,並自動在圖像中檢測和跟蹤人臉,進而對檢測到的人臉進行臉部識別的一系列相關技術,通常也叫做人像識別、面部識別。目前的人臉識別技術已經非常成熟了,還發展成3D人臉識別。
  • 人臉識別之Haar特徵
    簡介當下的人臉檢測主要為以下兩種方法:基於「知識」的檢測方法
  • 人臉識別日益普及 你的臉刷明白了嗎
    原標題:人臉識別日益普及 你的臉刷明白了嗎最近,隨著「94歲老人被抱起做人臉識別」「為躲人臉識別戴頭盔看房」等事件的發生,讓人臉識別頻上熱搜,技術濫用問題引發廣泛關注。隨之,一些傳言也「悄然出動」:人臉識別系統任何機構想裝就能裝?戴口罩就無法進行人臉識別?
  • 前端機器學習:識別人臉,並在臉頰上畫草莓
    當然,我們僅僅是使用人臉識別,那有人已經在TensorFlow的基礎上封裝了專門針對人臉識別的庫 face-api.js2. 基本原理我只是大體說一下,我只是一個感興趣的可以去看看具體的內容。第二步:臉部的不同姿勢使用由瓦希德·卡奇米(Vahid Kazemi)和約瑟菲娜·沙利文(Josephine Sullivan)在 2014 年發明的一種面部特徵點估計(face landmark estimation)算法。
  • 【源碼】常用的人臉識別資料庫以及上篇性別識別源碼
    該人臉庫在人臉識別研究的早期經常被人們採用,但由於變化模式較少,多數系統的識別率均可以達到 90%以上,因此進一步利用的價值已經不大。ORL人臉資料庫中一個採集對象的全部樣本庫中每個採集對象包含 10 幅經過歸一化處理的灰度圖像,圖像尺寸均為 92×112,圖像背景為黑色。
  • 如何應用MTCNN和FaceNet模型實現人臉檢測及識別
    AI 前線導讀:人臉檢測是對人臉進行識別和處理的第一步,主要用於檢測並定位圖片中的人臉,返回高精度的人臉框坐標及人臉特徵點坐標。人臉識別會進一步提取每個人臉中所蘊涵的身份特徵,並將其與已知的人臉進行對比,從而識別每個人臉的身份。
  • 人臉識別中的人臉表情識別技術
    隨著人臉識別技術的發展,如今在識別中應用到對人臉的表情進行識別,可以應用在人機互動、安全、機器人製造、醫療、通信和汽車領域等。那麼,暢視智能來告訴人臉識別技術的人臉表情識別要如何進行?圖像獲取:通過人臉識別攝像頭等圖像捕捉工具獲取靜態人臉圖像或動態圖像序列。
  • 人臉識別,現在連動漫角色都不放過
    至於上下文信息,團隊也做了實驗,下圖是算法在卡通人臉基礎上擴充不同比例下的性能識別。事實上,動物角色訓練出來的特徵樣本,相比於人臉來說,還是有點詭異。不過這也說明,一個標準、大型的動漫人臉數據集是有必要的。
  • 用dlib實現人臉識別的技巧
    很多人都認為人臉識別是一項非常難以實現的工作,看到名字就害怕,然後心懷忐忑到網上一搜,看到網上N頁的教程立馬就放棄了。這些人裡包括曾經的我自己。其實如果如果你不是非要深究其中的原理,只是要實現這一工作的話,人臉識別也沒那麼難。今天我們就來看看如何在40行代碼以內簡單地實現人臉識別。
  • 人臉識別屢被濫用,如何保護我的「臉」?
    近年來,人臉識別技術應用已經愈發廣泛,大家都有相關生活體驗,從線上的APP使用,到線下出入小區,人臉識別已經無處不在了,技術也在不斷升級。前面有「買房被人臉識別,可能多花20萬」的鬧劇,後有「人臉識別第一案」正式宣判,由涉嫌侵犯隱私而引起的糾紛、爭論大有愈演愈烈之勢。
  • 人臉識別:AI產品經理需要了解的CV通識
    人臉關鍵點檢測(人臉對齊):目的是自動估計人臉圖片上臉部特徵點的坐標一般可以使用Openface中的Dlib模型實現人臉檢測,利用OpenCV庫對數據進行處理。最近人臉檢測算法模型的流派包括三類及其之間的組合:viola-jones框架(性能一般速度尚可,適合移動端、嵌入式上使用),dpm(速度較慢),cnn(性能不錯)。
  • OpenCV人臉識別之一:數據收集和預處理
    本系列人臉識別文章用的是opencv2,最新版的opencv3.2的代碼請參考文章:《OpenCV之識別自己的臉——C++源碼放送》;《人臉識別源碼運行指南》(小編附在文末)前段時間對人臉檢測進行了一些嘗試:人臉檢測(C++/Python)(http://www.jianshu.com/p/504c081d7397)但是檢測和識別是不同的,檢測解決的問題是圖片中有沒有人臉;而識別解決的問題是
  • 人臉識別運用於大熊貓,刷臉支付核心安全技術未來可期
    但即使這樣,人臉識別也能準確區分並精準識別,你還在擔心有人會用你的照片進行惡意刷臉支付?還在擔心刷臉支付的安全性?體態完全相似的熊貓也可以進行人臉識別了?近日,西華師範大學發布關於大熊貓保護的最新研究成果:大熊貓面部識別技術。