怎样使用OpenCV进行人脸识别
不斷維護(hù)的地址:http://plzcoding.com/face-recognition-with-opencv/
怎樣使用OpenCV進(jìn)行人臉識(shí)別
???????? 本文大部分來(lái)自O(shè)penCV官網(wǎng)上的Face Reconition with OpenCV這節(jié)內(nèi)容(http://docs.opencv.org/modules/contrib/doc/facerec/facerec_tutorial.html),小弟我嘗試翻譯一些重要內(nèi)容。這部分內(nèi)容是Philipp Wagner寫(xiě)的,他的github:https://github.com/bytefish,他的網(wǎng)站http://www.bytefish.de/,應(yīng)該是個(gè)德國(guó)人。下面應(yīng)該是他的照片。
???????? 友情提示,要看懂代碼前,你得先知道OpenCV的安裝和配置,會(huì)用C++,用過(guò)一些OpenCV函數(shù)。基本的圖像處理和矩陣知識(shí)也是需要的。[gm:我是簫鳴的注釋]由于我僅僅是翻譯,對(duì)于六級(jí)才過(guò)的我,肯定有一些翻譯錯(cuò)的或者不當(dāng)?shù)牡胤?#xff0c;所以請(qǐng)大家糾錯(cuò)。
1.1.介紹Introduction
從OpenCV2.4開(kāi)始,加入了新的類FaceRecognizer,我們可以使用它便捷地進(jìn)行人臉識(shí)別實(shí)驗(yàn)。本文既介紹代碼使用,又介紹算法原理。(他寫(xiě)的源代碼,我們可以在OpenCV的opencv\modules\contrib\doc\facerec\src下找到,當(dāng)然也可以在他的github中找到,如果你想研究源碼,自然可以去看看,不復(fù)雜)
?
目前支持的算法有
??????? Eigenfaces特征臉createEigenFaceRecognizer()
???????? Fisherfaces ?createFisherFaceRecognizer()
???????? LocalBinary Patterns Histograms局部二值直方圖?createLBPHFaceRecognizer()
下面所有的例子中的代碼在OpenCV安裝目錄下的samples/cpp下面都能找到,所有的代碼商用或者學(xué)習(xí)都是免費(fèi)的。
?
1.2.人臉識(shí)別Face Recognition
對(duì)人類來(lái)說(shuō),人臉識(shí)別很容易。文獻(xiàn)[Tu06]告訴我們,僅僅是才三天的嬰兒已經(jīng)可以區(qū)分周圍熟悉的人臉了。那么對(duì)于計(jì)算機(jī)來(lái)說(shuō),到底有多難?其實(shí),迄今為止,我們對(duì)于人類自己為何可以區(qū)分不同的人所知甚少。是人臉內(nèi)部特征(眼睛、鼻子、嘴巴)還是外部特征(頭型、發(fā)際線)對(duì)于人類識(shí)別更有效?我們?cè)趺捶治鲆粡垐D像,大腦是如何對(duì)它編碼的?David Hubel和TorstenWiesel向我們展示,我們的大腦針對(duì)不同的場(chǎng)景,如線、邊、角或者運(yùn)動(dòng)這些局部特征有專門的神經(jīng)細(xì)胞作出反應(yīng)。顯然我們沒(méi)有把世界看成零散的塊塊,我們的視覺(jué)皮層必須以某種方式把不同的信息來(lái)源轉(zhuǎn)化成有用的模式。自動(dòng)人臉識(shí)別就是如何從一幅圖像中提取有意義的特征,把它們放入一種有用的表示方式,然后對(duì)他們進(jìn)行一些分類。基于幾何特征的人臉的人臉識(shí)別可能是最直觀的方法來(lái)識(shí)別人臉。第一個(gè)自動(dòng)人臉識(shí)別系統(tǒng)在[Kanade73]中又描述:標(biāo)記點(diǎn)(眼睛、耳朵、鼻子等的位置)用來(lái)構(gòu)造一個(gè)特征向量(點(diǎn)與點(diǎn)之間的距離、角度等)。通過(guò)計(jì)算測(cè)試和訓(xùn)練圖像的特征向量的歐氏距離來(lái)進(jìn)行識(shí)別。這樣的方法對(duì)于光照變化很穩(wěn)健,但也有巨大的缺點(diǎn):標(biāo)記點(diǎn)的確定是很復(fù)雜的,即使是使用最先進(jìn)的算法。一些幾何特征人臉識(shí)別近期工作在文獻(xiàn)[Bru92]中有描述。一個(gè)22維的特征向量被用在一個(gè)大數(shù)據(jù)庫(kù)上,單靠幾何特征不能提供足夠的信息用于人臉識(shí)別。
?
特征臉?lè)椒ㄔ谖墨I(xiàn)[TP91]中有描述,他描述了一個(gè)全面的方法來(lái)識(shí)別人臉:面部圖像是一個(gè)點(diǎn),這個(gè)點(diǎn)是從高維圖像空間找到它在低維空間的表示,這樣分類變得很簡(jiǎn)單。低維子空間低維是使用主元分析(Principal Component Analysis,PCA)找到的,它可以找擁有最大方差的那個(gè)軸。雖然這樣的轉(zhuǎn)換是從最佳重建角度考慮的,但是他沒(méi)有把標(biāo)簽問(wèn)題考慮進(jìn)去。[gm:讀懂這段需要一些機(jī)器學(xué)習(xí)知識(shí)]。想象一個(gè)情況,如果變化是基于外部來(lái)源,比如光照。軸的最大方差不一定包含任何有鑒別性的信息,因此此時(shí)的分類是不可能的。因此,一個(gè)使用線性鑒別(Linear Discriminant Analysis,LDA)的特定類投影方法被提出來(lái)解決人臉識(shí)別問(wèn)題[BHK97]。其中一個(gè)基本的想法就是,使類內(nèi)方差最小的同時(shí),使類外方差最大。
近年來(lái),各種局部特征提取方法出現(xiàn)。為了避免輸入的圖像的高維數(shù)據(jù),僅僅使用的局部特征描述圖像的方法被提出,提取的特征(很有希望的)對(duì)于局部遮擋、光照變化、小樣本等情況更強(qiáng)健。有關(guān)局部特征提取的方法有蓋伯小波(Gabor Waelets)([Wiskott97]),離散傅立葉變換(DiscreteCosinus Transform,DCT)([Messer06]),局部二值模式(LocalBinary Patterns,LBP)([AHP04])。使用什么方法來(lái)提取時(shí)域空間的局部特征依舊是一個(gè)開(kāi)放性的研究問(wèn)題,因?yàn)榭臻g信息是潛在有用的信息。
1.3.人臉庫(kù)Face Database
我們先獲取一些數(shù)據(jù)來(lái)進(jìn)行實(shí)驗(yàn)吧。我不想在這里做一個(gè)幼稚的例子。我們?cè)谘芯咳四樧R(shí)別,所以我們需要一個(gè)真的人臉圖像!你可以自己創(chuàng)建自己的數(shù)據(jù)集,也可以從這里(http://face-rec.org/databases/)下載一個(gè)。
AT&TFacedatabase又稱ORL人臉數(shù)據(jù)庫(kù),40個(gè)人,每人10張照片。照片在不同時(shí)間、不同光照、不同表情(睜眼閉眼、笑或者不笑)、不同人臉細(xì)節(jié)(戴眼鏡或者不戴眼鏡)下采集。所有的圖像都在一個(gè)黑暗均勻的背景下采集的,正面豎直人臉(有些有有輕微旋轉(zhuǎn))。
?
YaleFacedatabase A?ORL數(shù)據(jù)庫(kù)對(duì)于初始化測(cè)試比較適合,但它是一個(gè)簡(jiǎn)單的數(shù)據(jù)庫(kù),特征臉已經(jīng)可以達(dá)到97%的識(shí)別率,所以你使用其他方法很難得到更好的提升。Yale人臉數(shù)據(jù)庫(kù)是一個(gè)對(duì)于初始實(shí)驗(yàn)更好的數(shù)據(jù)庫(kù),因?yàn)樽R(shí)別問(wèn)題更復(fù)雜。這個(gè)數(shù)據(jù)庫(kù)包括15個(gè)人(14個(gè)男人,1個(gè)女人),每一個(gè)都有11個(gè)灰度圖像,大小是320*243像素。數(shù)據(jù)庫(kù)中有光照變化(中心光照、左側(cè)光照、右側(cè)光照)、表情變化(開(kāi)心、正常、悲傷、瞌睡、驚訝、眨眼)、眼鏡(戴眼鏡或者沒(méi)戴)。
???????? 壞消息是它不可以公開(kāi)下載,可能因?yàn)樵瓉?lái)的服務(wù)器壞了。但我們可以找到一些鏡像(比如?theMIT)但我不能保證它的完整性。如果你需要自己剪裁和校準(zhǔn)圖像,可以閱讀我的筆記(bytefish.de/blog/fisherfaces)。
?
ExtendedYale Facedatabase B?此數(shù)據(jù)庫(kù)包含38個(gè)人的2414張圖片,并且是剪裁好的。這個(gè)數(shù)據(jù)庫(kù)重點(diǎn)是測(cè)試特征提取是否對(duì)光照變化強(qiáng)健,因?yàn)閳D像的表情、遮擋等都沒(méi)變化。我認(rèn)為這個(gè)數(shù)據(jù)庫(kù)太大,不適合這篇文章的實(shí)驗(yàn),我建議使用ORL數(shù)據(jù)庫(kù)。
1.3.1.?準(zhǔn)備數(shù)據(jù)
我們從網(wǎng)上下了數(shù)據(jù),下了我們需要在程序中讀取它,我決定使用CSV文件讀取它。一個(gè)CSV文件包含文件名,緊跟一個(gè)標(biāo)簽。
/path/to/image.ext;0
???????? 假設(shè)/path/to/image.ext是圖像,就像你在windows下的c:/faces/person0/image0.jpg。最后我們給它一個(gè)標(biāo)簽0。這個(gè)標(biāo)簽類似代表這個(gè)人的名字,所以同一個(gè)人的照片的標(biāo)簽都一樣。我們對(duì)下載的ORL數(shù)據(jù)庫(kù)進(jìn)行標(biāo)識(shí),可以獲取到如下結(jié)果:
./at/s1/1.pgm;0 ./at/s1/2.pgm;0 ... ./at/s2/1.pgm;1 ./at/s2/2.pgm;1 ... ./at/s40/1.pgm;39 ./at/s40/2.pgm;39想象我已經(jīng)把圖像解壓縮在D:/data/at下面,而CSV文件在D:/data/at.txt。下面你根據(jù)自己的情況修改替換即可。一旦你成功建立CSV文件,就可以像這樣運(yùn)行示例程序:
facerec_demo.exe D:/data/at.txt1.3.2?Creating the CSV File
你不需要手工來(lái)創(chuàng)建一個(gè)CSV文件,我已經(jīng)寫(xiě)了一個(gè)Python程序來(lái)做這事。
[gm:說(shuō)一個(gè)我實(shí)現(xiàn)的方法
如果你會(huì)cmd命令,或者稱DOS命令,那么你打開(kāi)命令控制臺(tái)。假設(shè)我們的圖片放在J:下的Faces文件夾下,可以輸入如下語(yǔ)句:
J:\Faces\ORL>dir /b/s *.bmp > at.txt然后你打開(kāi)at.txt文件可能看到如下內(nèi)容(后面的0,1..標(biāo)簽是自己加的):
。。。。 J:\Faces\ORL\s1\1.bmp;0 J:\Faces\ORL\s1\10.bmp;0 J:\Faces\ORL\s1\2.bmp;0 J:\Faces\ORL\s1\3.bmp;0 J:\Faces\ORL\s1\4.bmp;0 J:\Faces\ORL\s1\5.bmp;0 J:\Faces\ORL\s1\6.bmp;0 J:\Faces\ORL\s1\7.bmp;0 J:\Faces\ORL\s1\8.bmp;0 J:\Faces\ORL\s1\9.bmp;0 J:\Faces\ORL\s10\1.bmp;1 J:\Faces\ORL\s10\10.bmp;1 J:\Faces\ORL\s10\2.bmp;1 J:\Faces\ORL\s10\3.bmp;1 J:\Faces\ORL\s10\4.bmp;1 J:\Faces\ORL\s10\5.bmp;1 J:\Faces\ORL\s10\6.bmp;1 。。。。自然還有c++編程等方法可以做得更好,看這篇文章反響,如果很多人需要,我就把這部分的代碼寫(xiě)出來(lái)。(遍歷多個(gè)文件夾,標(biāo)上標(biāo)簽)
]
特征臉Eigenfaces
???????? 我們講過(guò),圖像表示的問(wèn)題是他的高維問(wèn)題。二維灰度圖像p*q大小,是一個(gè)m=qp維的向量空間,所以一個(gè)100*100像素大小的圖像就是10,000維的圖像空間。問(wèn)題是,是不是所有的維數(shù)空間對(duì)我們來(lái)說(shuō)都有用?我們可以做一個(gè)決定,如果數(shù)據(jù)有任何差異,我們可以通過(guò)尋找主元來(lái)知道主要信息。主成分分析(Principal Component Analysis,PCA)是KarlPearson?(1901)獨(dú)立發(fā)表的,而?Harold Hotelling?(1933)把一些可能相關(guān)的變量轉(zhuǎn)換成一個(gè)更小的不相關(guān)的子集。想法是,一個(gè)高維數(shù)據(jù)集經(jīng)常被相關(guān)變量表示,因此只有一些的維上數(shù)據(jù)才是有意義的,包含最多的信息。PCA方法尋找數(shù)據(jù)中擁有最大方差的方向,被稱為主成分。
算法描述Algorithmic Description
令???表示一個(gè)隨機(jī)特征,其中??.
?
?
?
x的K個(gè)主成份:
? ? ? ??
?
其中? .
PCA基的重構(gòu):
? ? ? ? ? ? ? ? ??
?
其中??.
然后特征臉通過(guò)下面的方式進(jìn)行人臉識(shí)別:
A.? 把所有的訓(xùn)練數(shù)據(jù)投影到PCA子空間
B.? 把待識(shí)別圖像投影到PCA子空間
C.? 找到訓(xùn)練數(shù)據(jù)投影后的向量和待識(shí)別圖像投影后的向量最近的那個(gè)。
還有一個(gè)問(wèn)題有待解決。比如我們有400張圖片,每張100*100像素大小,那么PCA需要解決協(xié)方差矩陣?的求解,而X的大小是10000*400,那么我們會(huì)得到10000*10000大小的矩陣,這需要大概0.8GB的內(nèi)存。解決這個(gè)問(wèn)題不容易,所以我們需要另一個(gè)計(jì)策。就是轉(zhuǎn)置一下再求,特征向量不變化。文獻(xiàn)?[Duda01]中有描述。
[gm:這個(gè)PCA還是自己搜著看吧,這里的講的不清楚,不適合初學(xué)者看]
?
OpenCV中使用特征臉Eigenfaces in OpenCV
給出示例程序源代碼
#include "opencv2/core/core.hpp" #include "opencv2/contrib/contrib.hpp" #include "opencv2/highgui/highgui.hpp" ? #include <iostream> #include <fstream> #include <sstream> ? usingnamespace cv; usingnamespace std; ? static Mat norm_0_255(InputArray _src) { ??? Mat src = _src.getMat(); ??? // 創(chuàng)建和返回一個(gè)歸一化后的圖像矩陣: ??? Mat dst; ??? switch(src.channels()) { ??? case1: ??????? cv::normalize(_src, dst, 0,255, NORM_MINMAX, CV_8UC1); ??????? break; ??? case3: ??????? cv::normalize(_src, dst, 0,255, NORM_MINMAX, CV_8UC3); ??????? break; ??? default: ??????? src.copyTo(dst); ??????? break; ??? } ??? return dst; } //使用CSV文件去讀圖像和標(biāo)簽,主要使用stringstream和getline方法 staticvoid read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator =';') { ??? std::ifstream file(filename.c_str(), ifstream::in); ??? if (!file) { ??????? string error_message ="No valid input file was given, please check the given filename."; ??????? CV_Error(CV_StsBadArg, error_message); ??? } ??? string line, path, classlabel; ??? while (getline(file, line)) { ??????? stringstream liness(line); ??????? getline(liness, path, separator); ??????? getline(liness, classlabel); ??????? if(!path.empty()&&!classlabel.empty()) { ??????????? images.push_back(imread(path, 0)); ??????????? labels.push_back(atoi(classlabel.c_str())); ??????? } ??? } } ? int main(int argc, constchar*argv[]) { ??? // 檢測(cè)合法的命令,顯示用法 ??? // 如果沒(méi)有參數(shù)輸入則退出!. ??? if (argc <2) { ??????? cout <<"usage: "<< argv[0]<<" <csv.ext> <output_folder> "<< endl; ??????? exit(1); ??? } ??? string output_folder; ??? if (argc ==3) { ??????? output_folder = string(argv[2]); ??? } ??? //讀取你的CSV文件路徑. ??? string fn_csv = string(argv[1]); ??? // 2個(gè)容器來(lái)存放圖像數(shù)據(jù)和對(duì)應(yīng)的標(biāo)簽 ??? vector<Mat> images; ??? vector<int> labels; ??? // 讀取數(shù)據(jù). 如果文件不合法就會(huì)出錯(cuò) ??? // 輸入的文件名已經(jīng)有了. ??? try { ??????? read_csv(fn_csv, images, labels); ??? } catch (cv::Exception& e) { ??????? cerr <<"Error opening file \""<< fn_csv <<"\". Reason: "<< e.msg << endl; ??????? // 文件有問(wèn)題,我們啥也做不了了,退出了 ??????? exit(1); ??? } ??? // 如果沒(méi)有讀取到足夠圖片,我們也得退出. ??? if(images.size()<=1) { ??????? string error_message ="This demo needs at least 2 images to work. Please add more images to your data set!"; ??????? CV_Error(CV_StsError, error_message); ??? } ??? // 得到第一張照片的高度. 在下面對(duì)圖像 ??? // 變形到他們?cè)即笮r(shí)需要 ??? int height = images[0].rows; ??? // 下面的幾行代碼僅僅是從你的數(shù)據(jù)集中移除最后一張圖片 ??? //[gm:自然這里需要根據(jù)自己的需要修改,他這里簡(jiǎn)化了很多問(wèn)題] ??? Mat testSample = images[images.size() -1]; ??? int testLabel = labels[labels.size() -1]; ??? images.pop_back(); ??? labels.pop_back(); ??? // 下面幾行創(chuàng)建了一個(gè)特征臉模型用于人臉識(shí)別, ??? // 通過(guò)CSV文件讀取的圖像和標(biāo)簽訓(xùn)練它。 ??? // T這里是一個(gè)完整的PCA變換 ??? //如果你只想保留10個(gè)主成分,使用如下代碼 ??? //????? cv::createEigenFaceRecognizer(10); ??? // ??? // 如果你還希望使用置信度閾值來(lái)初始化,使用以下語(yǔ)句: ??? //????? cv::createEigenFaceRecognizer(10, 123.0); ??? // ??? // 如果你使用所有特征并且使用一個(gè)閾值,使用以下語(yǔ)句: ??? //????? cv::createEigenFaceRecognizer(0, 123.0); ??? // ??? Ptr<FaceRecognizer> model = createEigenFaceRecognizer(); ??? model->train(images, labels); ??? // 下面對(duì)測(cè)試圖像進(jìn)行預(yù)測(cè),predictedLabel是預(yù)測(cè)標(biāo)簽結(jié)果 ??? int predictedLabel = model->predict(testSample); ??? // ??? // 還有一種調(diào)用方式,可以獲取結(jié)果同時(shí)得到閾值: ??? //????? int predictedLabel = -1; ??? //????? double confidence = 0.0; ??? //????? model->predict(testSample, predictedLabel, confidence); ??? // ??? string result_message = format("Predicted class = %d / Actual class = %d.", predictedLabel, testLabel); ??? cout << result_message << endl; ??? // 這里是如何獲取特征臉模型的特征值的例子,使用了getMat方法: ??? Mat eigenvalues = model->getMat("eigenvalues"); ??? // 同樣可以獲取特征向量: ??? Mat W = model->getMat("eigenvectors"); ??? // 得到訓(xùn)練圖像的均值向量 ??? Mat mean = model->getMat("mean"); ??? // 現(xiàn)實(shí)還是保存: ??? if(argc==2) { ??????? imshow("mean", norm_0_255(mean.reshape(1, images[0].rows))); ??? } else { ??????? imwrite(format("%s/mean.png", output_folder.c_str()), norm_0_255(mean.reshape(1, images[0].rows))); ??? } ??? // 現(xiàn)實(shí)還是保存特征臉: ??? for (int i =0; i < min(10, W.cols); i++) { ??????? string msg = format("Eigenvalue #%d = %.5f", i, eigenvalues.at<double>(i)); ??????? cout << msg << endl; ??????? // 得到第 #i個(gè)特征 ??????? Mat ev = W.col(i).clone(); ??????? //把它變成原始大小,為了把數(shù)據(jù)顯示歸一化到0~255. ??????? Mat grayscale = norm_0_255(ev.reshape(1, height)); ??????? // 使用偽彩色來(lái)顯示結(jié)果,為了更好的感受. ??????? Mat cgrayscale; ??????? applyColorMap(grayscale, cgrayscale, COLORMAP_JET); ??????? // 顯示或者保存: ??????? if(argc==2) { ??????????? imshow(format("eigenface_%d", i), cgrayscale); ??????? } else { ??????????? imwrite(format("%s/eigenface_%d.png", output_folder.c_str(), i), norm_0_255(cgrayscale)); ??????? } ??? } ??? // 在一些預(yù)測(cè)過(guò)程中,顯示還是保存重建后的圖像: ??? for(int num_components =10; num_components <300; num_components+=15) { ??????? // 從模型中的特征向量截取一部分 ??????? Mat evs = Mat(W, Range::all(), Range(0, num_components)); ??????? Mat projection = subspaceProject(evs, mean, images[0].reshape(1,1)); ??????? Mat reconstruction = subspaceReconstruct(evs, mean, projection); ??????? // 歸一化結(jié)果,為了顯示: ??????? reconstruction = norm_0_255(reconstruction.reshape(1, images[0].rows)); ??????? // 顯示或者保存: ??????? if(argc==2) { ??????????? imshow(format("eigenface_reconstruction_%d", num_components), reconstruction); ??????? } else { ??????????? imwrite(format("%s/eigenface_reconstruction_%d.png", output_folder.c_str(), num_components), reconstruction); ??????? } ??? } ??? // 如果我們不是存放到文件中,就顯示他,這里使用了暫定等待鍵盤(pán)輸入: ??? if(argc==2) { ??????? waitKey(0); ??? } ??? return0; }???????? 我使用了偽彩色圖像,所以你可以看到在特征臉中灰度值是如何分布的。你可以看到特征臉不但對(duì)人臉特征進(jìn)行編碼,還對(duì)這些圖像中的光照進(jìn)行編碼。(看第四張圖像是左側(cè)的光照,而第五張是右側(cè)的光照)[gm:PCA對(duì)光照變化圖像識(shí)別效果很差,自然有一些改進(jìn)方法,有后再談]
?
我們已經(jīng)看到了,我們可以利用低維近似來(lái)重構(gòu)人臉,我們看看對(duì)于一個(gè)好的重構(gòu),需要多少特征臉。我將依次畫(huà)出10,30,。。310張?zhí)卣髂槙r(shí)的效果。
for(int num_components =10; num_components <300; num_components+=15) { ??? Mat evs = Mat(W, Range::all(), Range(0, num_components)); ??? Mat projection = subspaceProject(evs, mean, images[0].reshape(1,1)); ??? Mat reconstruction = subspaceReconstruct(evs, mean, projection); ??? reconstruction = norm_0_255(reconstruction.reshape(1, images[0].rows)); ??? if(argc==2) { ??????? imshow(format("eigenface_reconstruction_%d", num_components), reconstruction); ??? } else { ??????? imwrite(format("%s/eigenface_reconstruction_%d.png", output_folder.c_str(), num_components), reconstruction); ??? } }?
顯然10個(gè)特征向量[gm:1個(gè)特征向量可以變形成一個(gè)特征臉,這里特征向量和特征臉概念有些近似]是不夠的,50個(gè)特征向量可以有效的編碼出重要的人臉特征。在ORL數(shù)據(jù)庫(kù)中,當(dāng)使用300個(gè)特征向量時(shí),你將獲取一個(gè)比較好的和重構(gòu)結(jié)果。有定理指出重構(gòu)需要選擇多少特征臉才合適,但它嚴(yán)重依賴于人臉數(shù)據(jù)庫(kù)。[gm:也就是沒(méi)啥討論意義,針對(duì)現(xiàn)實(shí)情況做出考慮吧]。文獻(xiàn)[Zhao03]是一個(gè)好的開(kāi)始研究起點(diǎn)。
?
?
Fisherfaces
???????? 主成分分析是一種基于特征臉的方法,找到使數(shù)據(jù)中最大方差的特征線性組合。這是一個(gè)表現(xiàn)數(shù)據(jù)的強(qiáng)大方法,但它沒(méi)有考慮類別信息,并且在扔掉主元時(shí),同時(shí)許多有鑒別的信息都被扔掉。假設(shè)你數(shù)據(jù)庫(kù)中的變化主要是光照變化,那么PCA此時(shí)幾乎失效了。[gm:把光照情況類似的照片認(rèn)為一樣,而不管人臉其他細(xì)節(jié)]可以看去http://www.bytefish.de/wiki/pca_lda_with_gnu_octave?看下例子。
???????? 線性鑒別分析在降維的同時(shí)考慮類別信息,由統(tǒng)計(jì)學(xué)家?Sir R. A. Fisher發(fā)明。在他1936年的文獻(xiàn)中,他成功對(duì)花進(jìn)行了分類:The useof multiple measurements in taxonomic problems?[Fisher36]。為了找到一種特征組合方式,達(dá)到最大的類間離散度和最小的類內(nèi)離散度。這個(gè)想法很簡(jiǎn)單:在低維表示下,相同的類應(yīng)該緊緊的聚在一起,而不同的類別盡量距離越遠(yuǎn)。?這也被Belhumeur,?Hespanha?和?Kriegman所認(rèn)同,所以他們把鑒別分析引入到人臉識(shí)別問(wèn)題中[BHK97]。
算法描述Algorithmic Description
令x是一個(gè)來(lái)自c個(gè)類中的隨機(jī)向量,
? ? ? ? ? ? ? ? ? ??
?
散度矩陣???和S_{W}如下計(jì)算:
? ? ? ? ? ? ? ? ? ?
?
, 其中???是全部數(shù)據(jù)的均值 ? ??:
? ? ? ? ? ? ? ?
?
而??是某個(gè)類的均值? :
? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
?
Fisher的分類算法可以看出一個(gè)投影矩陣? , 使得類的可分性最大:
? ? ? ? ? ? ? ? ? ?
?
接下來(lái)?[BHK97], 一個(gè)解決這個(gè)普通特征值優(yōu)化問(wèn)題的方法被提出:
? ? ? ? ? ? ??? ? ??
?
???????? 還有一個(gè)問(wèn)題未解決,?Sw的排列最多只有?(N-c), ?N?個(gè)樣本和c個(gè)類別。在模式識(shí)別中,樣本數(shù)據(jù)個(gè)數(shù)N的大小一般小于輸入數(shù)據(jù)的維數(shù)。?[gm:比如說(shuō)之前的圖片,N=400,而10000就是數(shù)據(jù)維數(shù)]那么,散度矩陣Sw就是奇異的(可以看文獻(xiàn)[RJ91])。在文獻(xiàn)[BHK97]中,使用PCA把數(shù)據(jù)投影到(N-c)維的子空間,然后再使用線性鑒別分析,因?yàn)镾w不是奇異矩陣了(可逆矩陣)。
然后優(yōu)化問(wèn)題可以寫(xiě)成:
? ? ? ? ??
?
投影矩陣W,可以把樣本投影到(c-1)維的空間上,可以表示為
? ? ? ? ? ? ? ? ?
?
Fisherfaces in OpenCV
#include "opencv2/core/core.hpp" #include "opencv2/contrib/contrib.hpp" #include "opencv2/highgui/highgui.hpp" ? #include <iostream> #include <fstream> #include <sstream> ? usingnamespace cv; usingnamespace std; ? static Mat norm_0_255(InputArray _src) { ??? Mat src = _src.getMat(); ??? // 創(chuàng)建和返回歸一化的圖像: ??? Mat dst; ??? switch(src.channels()) { ??? case1: ??????? cv::normalize(_src, dst, 0,255, NORM_MINMAX, CV_8UC1); ??????? break; ??? case3: ??????? cv::normalize(_src, dst, 0,255, NORM_MINMAX, CV_8UC3); ??????? break; ??? default: ??????? src.copyTo(dst); ??????? break; ??? } ??? return dst; } ? staticvoid read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator =';') { ??? std::ifstream file(filename.c_str(), ifstream::in); ??? if (!file) { ??????? string error_message ="No valid input file was given, please check the given filename."; ??????? CV_Error(CV_StsBadArg, error_message); ??? } ??? string line, path, classlabel; ??? while (getline(file, line)) { ??????? stringstream liness(line); ??????? getline(liness, path, separator); ??????? getline(liness, classlabel); ??????? if(!path.empty()&&!classlabel.empty()) { ??????????? images.push_back(imread(path, 0)); ??????????? labels.push_back(atoi(classlabel.c_str())); ??????? } ??? } } ? int main(int argc, constchar*argv[]) { ??? // 判斷輸入命令是否有效,輸出用法 ??? // 如果沒(méi)有輸入?yún)?shù). ??? if (argc <2) { ??????? cout <<"usage: "<< argv[0]<<" <csv.ext> <output_folder> "<< endl; ??????? exit(1); ??? } ??? string output_folder; ??? if (argc ==3) { ??????? output_folder = string(argv[2]); ??? } ??? // 獲取CSV文件的路徑. ??? string fn_csv = string(argv[1]); ??? // 這些容器存放圖片和標(biāo)簽. ??? vector<Mat> images; ??? vector<int> labels; ??? // 載入數(shù)據(jù).如果不合理,會(huì)出錯(cuò) ??? // 輸入文件名fn_csv已經(jīng)有了. ??? try { ??????? read_csv(fn_csv, images, labels); ??? } catch (cv::Exception& e) { ??????? cerr <<"Error opening file \""<< fn_csv <<"\". Reason: "<< e.msg << endl; ??????? // 什么也不能做了 ??????? exit(1); ??? } ??? // 如果沒(méi)有足夠圖像就退出掉. ??? if(images.size()<=1) { ??????? string error_message ="This demo needs at least 2 images to work. Please add more images to your data set!"; ??????? CV_Error(CV_StsError, error_message); ??? } ??? int height = images[0].rows; ? ??? Mat testSample = images[images.size() -1]; ??? int testLabel = labels[labels.size() -1]; ??? images.pop_back(); ??? labels.pop_back(); ??? // 如果想保存10個(gè)fisherfaces ??? //????? cv::createFisherFaceRecognizer(10); ??? // ??? // 如果要以123.0作為置信閾值 ??? //????? cv::createFisherFaceRecognizer(0, 123.0); ??? // ??? Ptr<FaceRecognizer> model = createFisherFaceRecognizer(); ??? model->train(images, labels); ??? int predictedLabel = model->predict(testSample); ??? // ??? //????? model->predict(testSample, predictedLabel, confidence); ??? // ??? string result_message = format("Predicted class = %d / Actual class = %d.", predictedLabel, testLabel); ??? cout << result_message << endl; ??? Mat eigenvalues = model->getMat("eigenvalues"); ??? Mat W = model->getMat("eigenvectors"); ??? Mat mean = model->getMat("mean"); ??? if(argc==2) { ??????? imshow("mean", norm_0_255(mean.reshape(1, images[0].rows))); ??? } else { ??????? imwrite(format("%s/mean.png", output_folder.c_str()), norm_0_255(mean.reshape(1, images[0].rows))); ??? } ??? //顯示還是保存, 最多16 Fisherfaces: ??? for (int i =0; i < min(16, W.cols); i++) { ??????? string msg = format("Eigenvalue #%d = %.5f", i, eigenvalues.at<double>(i)); ??????? cout << msg << endl; ??????? Mat ev = W.col(i).clone(); ??????? Mat grayscale = norm_0_255(ev.reshape(1, height)); ??????? // 使用Bone偽彩色圖像來(lái)顯示. ??????? Mat cgrayscale; ??????? applyColorMap(grayscale, cgrayscale, COLORMAP_BONE); ??????? if(argc==2) { ??????????? imshow(format("fisherface_%d", i), cgrayscale); ??????? } else { ??????????? imwrite(format("%s/fisherface_%d.png", output_folder.c_str(), i), norm_0_255(cgrayscale)); ??????? } ??? } ??? for(int num_component =0; num_component < min(16, W.cols); num_component++) { ??????? Mat ev = W.col(num_component); ??????? Mat projection = subspaceProject(ev, mean, images[0].reshape(1,1)); ??????? Mat reconstruction = subspaceReconstruct(ev, mean, projection); ??????? reconstruction = norm_0_255(reconstruction.reshape(1, images[0].rows)); ??????? if(argc==2) { ??????????? imshow(format("fisherface_reconstruction_%d", num_component), reconstruction); ??????? } else { ??????????? imwrite(format("%s/fisherface_reconstruction_%d.png", output_folder.c_str(), num_component), reconstruction); ??????? } ??? } ??? if(argc==2) { ??????? waitKey(0); ??? } ??? return0; }在這個(gè)例子中,我使用YaleA人臉數(shù)據(jù)庫(kù),僅僅因?yàn)轱@示更好些。每一個(gè)Fisherface都和原始圖像有同樣長(zhǎng)度,因此它可以被顯示成圖像。下面顯示了16張F(tuán)isherfaces圖像。
???????? Fisherfaces方法學(xué)習(xí)一個(gè)正對(duì)標(biāo)簽的轉(zhuǎn)換矩陣,所依它不會(huì)如特征臉那樣那么注重光照。鑒別分析是尋找可以區(qū)分人的面部特征。需要說(shuō)明的是,Fisherfaces的性能也很依賴于輸入數(shù)據(jù)。實(shí)際上,如果你對(duì)光照好的圖片上學(xué)習(xí)Fisherfaces,而想對(duì)不好的光照?qǐng)D片進(jìn)行識(shí)別,那么他可能會(huì)找到錯(cuò)誤的主元,因?yàn)樵诓缓霉庹請(qǐng)D片上,這些特征不優(yōu)越。這似乎是符合邏輯的,因?yàn)檫@個(gè)方法沒(méi)有機(jī)會(huì)去學(xué)習(xí)光照。[gm:那么采集圖像時(shí)就要考慮光照變化,訓(xùn)練時(shí)考慮所有光照情況,數(shù)據(jù)庫(kù)multi-pie就考慮很多種光照]
???????? Fisherfaces允許對(duì)投影圖像進(jìn)行重建,就行特征臉一樣。但是由于我們僅僅使用這些特征來(lái)區(qū)分不同的類別,因此你無(wú)法期待對(duì)原圖像有一個(gè)好的重建效果。[gm:也就是特征臉把每個(gè)圖片看成一個(gè)個(gè)體,重建時(shí)效果也有保證,而Fisherfaces把一個(gè)人的照片看成一個(gè)整體,那么重建時(shí)重建的效果則不是很好]。對(duì)于Fisherfaces方法我們將把樣本圖像逐個(gè)投影到Fisherfaces上。因此你可以獲得一個(gè)好的可視效果,每個(gè)Fisherfaces特征可以被描述為
for(int num_component =0; num_component < min(16, W.cols); num_component++) { ??? Mat ev = W.col(num_component); ??? Mat projection = subspaceProject(ev, mean, images[0].reshape(1,1)); ??? Mat reconstruction = subspaceReconstruct(ev, mean, projection); ??? reconstruction = norm_0_255(reconstruction.reshape(1, images[0].rows)); ??? if(argc==2) { ??????? imshow(format("fisherface_reconstruction_%d", num_component), reconstruction); ??? } else { ??????? imwrite(format("%s/fisherface_reconstruction_%d.png", output_folder.c_str(), num_component), reconstruction); ??? } }對(duì)于人類眼睛來(lái)說(shuō),差異比較微妙,但你還是可以看到一些差異的。
局部二值模式直方圖Local Binary Patterns Histograms
???????? Eigenfaces和Fisherfaces使用整體方法來(lái)進(jìn)行人臉識(shí)別[gm:直接使用所有的像素]。你把你的數(shù)據(jù)當(dāng)作圖像空間的高維向量。我們都知道高維數(shù)據(jù)是糟糕的,所以一個(gè)低維子空間被確定,對(duì)于信息保存可能很好。Eigenfaces是最大化總的散度,這樣可能導(dǎo)致,當(dāng)方差由外部條件產(chǎn)生時(shí),最大方差的主成分不適合用來(lái)分類。所以為使用一些鑒別分析,我們使用了LDA方法來(lái)優(yōu)化。Fisherfaces方法可以很好的運(yùn)作,至少在我們假設(shè)的模型的有限情況下。
???????? 現(xiàn)實(shí)生活是不完美的。你無(wú)法保證在你的圖像中光照條件是完美的,或者說(shuō)1個(gè)人的10張照片。所以,如果每人僅僅只有一張照片呢?我們的子空間的協(xié)方差估計(jì)方法可能完全錯(cuò)誤,所以識(shí)別也可能錯(cuò)誤。是否記得Eigenfaces在AT&T數(shù)據(jù)庫(kù)上達(dá)到了96%的識(shí)別率?對(duì)于這樣有效的估計(jì),我們需要多少?gòu)堄?xùn)練圖像呢?下圖是Eigenfaces和Fisherfaces方法在AT&T數(shù)據(jù)庫(kù)上的首選識(shí)別率,這是一個(gè)簡(jiǎn)單的數(shù)據(jù)庫(kù):
?
???????? 因此,若你想得到好的識(shí)別率,你大約需要每個(gè)人有8(7~9)張圖像,而Fisherfaces在這里并沒(méi)有好的幫助。以上的實(shí)驗(yàn)是10個(gè)圖像的交叉驗(yàn)證結(jié)果,使用了facerec框架:?https://github.com/bytefish/facerec。這不是一個(gè)刊物,所以我不會(huì)用高深的數(shù)學(xué)分析來(lái)證明這個(gè)圖像。?當(dāng)遇到小的訓(xùn)練數(shù)據(jù)集時(shí),可以看一下文獻(xiàn)[KM01],了解二種方法的細(xì)節(jié)分析。
???????? 一些研究專注于圖像局部特征的提取。主意是我們不把整個(gè)圖像看成一個(gè)高維向量,僅僅用局部特征來(lái)描述一個(gè)物體。通過(guò)這種方式提取特征,你將獲得一個(gè)低維隱式。一個(gè)好主意!但是你很快發(fā)現(xiàn)這種圖像表示方法不僅僅遭受光照變化。你想想圖像中的尺度變化、形變、旋轉(zhuǎn)—我們的局部表示方式起碼對(duì)這些情況比較穩(wěn)健。正如SIFT,LBP方法在2D紋理分析中舉足輕重。LBP的基本思想是對(duì)圖像的像素和它局部周圍像素進(jìn)行對(duì)比后的結(jié)果進(jìn)行求和。把這個(gè)像素作為中心,對(duì)相鄰像素進(jìn)行閾值比較。如果中心像素的亮度大于等于他的相鄰像素,把他標(biāo)記為1,否則標(biāo)記為0。你會(huì)用二進(jìn)制數(shù)字來(lái)表示每個(gè)像素,比如11001111。因此,由于周圍相鄰8個(gè)像素,你最終可能獲取2^8個(gè)可能組合,被稱為局部二值模式,有時(shí)被稱為L(zhǎng)BP碼。第一個(gè)在文獻(xiàn)中描述的LBP算子實(shí)際使用的是3*3的鄰域。
算法描述Algorithmic Description
???????? 一個(gè)更加正式的LBP操作可以被定義為
? ? ? ? ? ? ? ? ? ? ?
?
其中?是中心像素,亮度是?;而?則是相鄰像素的亮度。s是一個(gè)符號(hào)函數(shù):
?
?? ? ? ?
這種描述方法使得你可以很好的捕捉到圖像中的細(xì)節(jié)。實(shí)際上,研究者們可以用它在紋理分類上得到最先進(jìn)的水平。正如剛才描述的方法被提出后,固定的近鄰區(qū)域?qū)τ诔叨茸兓木幋a失效。所以,使用一個(gè)變量的擴(kuò)展方法,在文獻(xiàn)[AHP04]中有描述。主意是使用可變半徑的圓對(duì)近鄰像素進(jìn)行編碼,這樣可以捕捉到如下的近鄰:
? ? ? ? ? ??
對(duì)一個(gè)給定的點(diǎn)? ?,他的近鄰點(diǎn)??可以由如下計(jì)算:
? ? ? ??
其中,R是圓的半徑,而P是樣本點(diǎn)的個(gè)數(shù)。
這個(gè)操作是對(duì)原始LBP算子的擴(kuò)展,所以有時(shí)被稱為擴(kuò)展LBP(又稱為圓形LBP)。如果一個(gè)在圓上的點(diǎn)不在圖像坐標(biāo)上,我們使用他的內(nèi)插點(diǎn)。計(jì)算機(jī)科學(xué)有一堆聰明的插值方法,而OpenCV使用雙線性插值。
? ? ? ? ?
LBP算子,對(duì)于灰度的單調(diào)變化很穩(wěn)健。我們可以看到手工改變后的圖像的LBP圖像(你可以看到LBP圖像是什么樣子的!)
? ? ? ? ? ??
?
???????? 那么剩下來(lái)的就是如何合并空間信息用于人臉識(shí)別模型。Ahonenet. Al在文獻(xiàn)?[AHP04]中提出表示方法,對(duì)LBP圖像成m個(gè)塊,每個(gè)塊提取直方圖。通過(guò)連接局部特直方圖(而不是合并)然后就能得到空間增強(qiáng)的特征向量。這些直方圖被稱為局部二值模式直方圖。
OpenCV中的局部二值模式直方圖Local Binary Patterns Histograms inOpenCV
#include "opencv2/core/core.hpp" #include "opencv2/contrib/contrib.hpp" #include "opencv2/highgui/highgui.hpp" ? #include <iostream> #include <fstream> #include <sstream> ? usingnamespace cv; usingnamespace std; ? staticvoid read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator =';') { ??? std::ifstream file(filename.c_str(), ifstream::in); ??? if (!file) { ??????? string error_message ="No valid input file was given, please check the given filename."; ??????? CV_Error(CV_StsBadArg, error_message); ??? } ??? string line, path, classlabel; ??? while (getline(file, line)) { ??????? stringstream liness(line); ??????? getline(liness, path, separator); ??????? getline(liness, classlabel); ??????? if(!path.empty()&&!classlabel.empty()) { ??????????? images.push_back(imread(path, 0)); ??????????? labels.push_back(atoi(classlabel.c_str())); ??????? } ??? } } ? int main(int argc, constchar*argv[]) { ??? if (argc !=2) { ??????? cout <<"usage: "<< argv[0]<<" <csv.ext>"<< endl; ??????? exit(1); ??? } ??? string fn_csv = string(argv[1]); ??? vector<Mat> images; ??? vector<int> labels; ??? try { ??????? read_csv(fn_csv, images, labels); ??? } catch (cv::Exception& e) { ??????? cerr <<"Error opening file \""<< fn_csv <<"\". Reason: "<< e.msg << endl; ??????? // nothing more we can do ??????? exit(1); ??? } ??? if(images.size()<=1) { ??????? string error_message ="This demo needs at least 2 images to work. Please add more images to your data set!"; ??????? CV_Error(CV_StsError, error_message); ??? } ??? int height = images[0].rows; ??? Mat testSample = images[images.size() -1]; ??? int testLabel = labels[labels.size() -1]; ??? images.pop_back(); ??? labels.pop_back(); ??? // TLBPHFaceRecognizer 使用了擴(kuò)展的LBP ??? // 在其他的算子中他可能很容易被擴(kuò)展 ??? // 下面是默認(rèn)參數(shù) ??? //????? radius = 1 ??? //????? neighbors = 8 ??? //????? grid_x = 8 ??? //???? ?grid_y = 8 ??? // ??? // 如果你要?jiǎng)?chuàng)建 LBPH FaceRecognizer 半徑是2,16個(gè)鄰域 ??? //????? cv::createLBPHFaceRecognizer(2, 16); ??? // ??? // 如果你需要一個(gè)閾值,并且使用默認(rèn)參數(shù): ??? //????? cv::createLBPHFaceRecognizer(1,8,8,8,123.0) ??? // ??? Ptr<FaceRecognizer> model = createLBPHFaceRecognizer(); ??? model->train(images, labels); ??? int predictedLabel = model->predict(testSample); ??? //????? int predictedLabel = -1; ??? //????? double confidence = 0.0; ??? //????? model->predict(testSample, predictedLabel, confidence); ??? // ??? string result_message = format("Predicted class = %d / Actual class = %d.", predictedLabel, testLabel); ??? cout << result_message << endl; ??? // 有時(shí)你需要設(shè)置或者獲取內(nèi)部數(shù)據(jù)模型, ??? // 他不能被暴露在 cv::FaceRecognizer類中. ??? // ??? // 首先我們對(duì)FaceRecognizer的閾值設(shè)置到0.0,而不是重寫(xiě)訓(xùn)練模型 ??? // 當(dāng)你重新估計(jì)模型時(shí)很重要 ????// ??? model->set("threshold",0.0); ??? predictedLabel = model->predict(testSample); ??? cout <<"Predicted class = "<< predictedLabel << endl; ??? // 由于確保高效率,LBP圖沒(méi)有被存儲(chǔ)在模型里面。D ??? cout <<"Model Information:"<< endl; ??? string model_info = format("\tLBPH(radius=%i, neighbors=%i, grid_x=%i, grid_y=%i, threshold=%.2f)", ??????????? model->getInt("radius"), ??????????? model->getInt("neighbors"), ??????????? model->getInt("grid_x"), ??????????? model->getInt("grid_y"), ??????????? model->getDouble("threshold")); ??? cout << model_info << endl; ??? // 我們可以獲取樣本的直方圖: ??? vector<Mat> histograms = model->getMatVector("histograms"); ??? // 我需要現(xiàn)實(shí)它嗎? 或許它的長(zhǎng)度才是我們感興趣的: ??? cout <<"Size of the histograms: "<< histograms[0].total()<< endl; ??? return0; }總結(jié)Conclusion
你已經(jīng)學(xué)會(huì)如何在真實(shí)應(yīng)用下,使用新的FaceRecognizer類。讀完算法,可能到你進(jìn)行實(shí)驗(yàn)的時(shí)候了,使用它們,改進(jìn)它們,讓OpenCV社區(qū)參與其中!
?
文獻(xiàn)Literature
| [AHP04] | (1,?2,?3)?Ahonen, T., Hadid, A., and Pietikainen, M.?Face Recognition with Local Binary Patterns.?Computer Vision - ECCV 2004 (2004), 469–481. |
?
| [BHK97] | (1,?2,?3,?4,?5)?Belhumeur, P. N., Hespanha, J., and Kriegman, D.?Eigenfaces vs. Fisherfaces: Recognition Using Class Specific Linear Projection.?IEEE Transactions on Pattern Analysis and Machine Intelligence 19, 7 (1997), 711–720. |
?
| [Bru92] | Brunelli, R., Poggio, T.?Face Recognition through Geometrical Features.?European Conference on Computer Vision (ECCV) 1992, S. 792–800. |
?
| [Duda01] | Duda, Richard O. and Hart, Peter E. and Stork, David G.,?Pattern Classification?(2nd Edition) 2001. |
?
| [Fisher36] | Fisher, R. A.?The use of multiple measurements in taxonomic problems.?Annals Eugen. 7 (1936), 179–188. |
?
| [GBK01] | Georghiades, A.S. and Belhumeur, P.N. and Kriegman, D.J.,?From Few to Many: Illumination Cone Models for Face Recognition under Variable Lighting and Pose?IEEE Transactions on Pattern Analysis and Machine Intelligence 23, 6 (2001), 643-660. |
?
| [Kanade73] | Kanade, T.?Picture processing system by computer complex and recognition of human faces.?PhD thesis, Kyoto University, November 1973 |
?
| [KM01] | Martinez, A and Kak, A.?PCA versus LDA?IEEE Transactions on Pattern Analysis and Machine Intelligence, Vol. 23, No.2, pp. 228-233, 2001. |
?
| [Lee05] | Lee, K., Ho, J., Kriegman, D.?Acquiring Linear Subspaces for Face Recognition under Variable Lighting.?In: IEEE Transactions on Pattern Analysis and Machine Intelligence (PAMI) 27 (2005), Nr. 5 |
?
| [Messer06] | Messer, K. et al.?Performance Characterisation of Face Recognition Algorithms and Their Sensitivity to Severe Illumination Changes.?In: In: ICB, 2006, S. 1–11. |
?
| [RJ91] | |
?
| [Tan10] | Tan, X., and Triggs, B.?Enhanced local texture feature sets for face recognition under difficult lighting conditions.?IEEE Transactions on Image Processing 19 (2010), 1635–650. |
?
| [TP91] | Turk, M., and Pentland, A.?Eigenfaces for recognition.?Journal of Cognitive Neuroscience 3 (1991), 71–86. |
?
| [Tu06] | Chiara Turati, Viola Macchi Cassia, F. S., and Leo, I.?Newborns face recognition: Role of inner and outer facial features. Child Development?77, 2 (2006), 297–311. |
?
| [Wiskott97] | Wiskott, L., Fellous, J., Krüger, N., Malsburg, C.?Face Recognition By Elastic Bunch Graph Matching.IEEE Transactions on Pattern Analysis and Machine Intelligence 19 (1997), S. 775–779 |
?
| [Zhao03] | Zhao, W., Chellappa, R., Phillips, P., and Rosenfeld, A. Face recognition: A literature survey. ACM Computing Surveys (CSUR) 35, 4 (2003), 399–458. |
人臉對(duì)齊Aligning Face Images
???????? 對(duì)于圖像數(shù)據(jù)的對(duì)其很重要,特別遇到情感檢測(cè)這類任務(wù),你需要越多的細(xì)節(jié)越好。相信我,你不會(huì)要自己動(dòng)手做吧。我給你提供了一個(gè)Python代碼。
# ?CropFace(image, eye_left, eye_right, offset_pct, dest_sz) # eye_left?is the position of the left eye # eye_right?is the position of the right eye # offset_pct?is the percent of the image you want to keep next to the eyes (horizontal, vertical direction) # dest_sz?is the size of the output image # importsys,math,Image ? defDistance(p1,p2): ? dx = p2[0]- p1[0] ? dy = p2[1]- p1[1] ? return math.sqrt(dx*dx+dy*dy) ? defScaleRotateTranslate(image, angle, center =None, new_center =None, scale =None, resample=Image.BICUBIC): ? if (scale isNone)and (center isNone): ??? return image.rotate(angle=angle, resample=resample) ? nx,ny = x,y = center ? sx=sy=1.0 ? if new_center: ??? (nx,ny) = new_center ? if scale: ??? (sx,sy) = (scale, scale) ? cosine = math.cos(angle) ? sine = math.sin(angle) ? a = cosine/sx ? b = sine/sx ? c = x-nx*a-ny*b ? d =-sine/sy ? e = cosine/sy ? f = y-nx*d-ny*e ? return image.transform(image.size, Image.AFFINE, (a,b,c,d,e,f), resample=resample) ? defCropFace(image, eye_left=(0,0), eye_right=(0,0), offset_pct=(0.2,0.2), dest_sz = (70,70)): ? # calculate offsets in original image ? offset_h = math.floor(float(offset_pct[0])*dest_sz[0]) ? offset_v = math.floor(float(offset_pct[1])*dest_sz[1]) ? # get the direction ? eye_direction = (eye_right[0]- eye_left[0], eye_right[1]- eye_left[1]) ? # calc rotation angle in radians ? rotation =-math.atan2(float(eye_direction[1]),float(eye_direction[0])) ? # distance between them ? dist = Distance(eye_left, eye_right) ? # calculate the reference eye-width ? reference = dest_sz[0]-2.0*offset_h ? # scale factor ? scale =float(dist)/float(reference) ? # rotate original around the left eye ? image = ScaleRotateTranslate(image, center=eye_left, angle=rotation) ? # crop the rotated image ? crop_xy = (eye_left[0]- scale*offset_h, eye_left[1]- scale*offset_v) ? crop_size = (dest_sz[0]*scale, dest_sz[1]*scale) ? image = image.crop((int(crop_xy[0]),int(crop_xy[1]),int(crop_xy[0]+crop_size[0]),int(crop_xy[1]+crop_size[1]))) ? # resize it ? image = image.resize(dest_sz, Image.ANTIALIAS) ? return image ? if __name__ =="__main__": ? image =? Image.open("arnie.jpg") ? CropFace(image, eye_left=(252,364), eye_right=(420,366), offset_pct=(0.1,0.1), dest_sz=(200,200)).save("arnie_10_10_200_200.jpg") ? CropFace(image, eye_left=(252,364), eye_right=(420,366), offset_pct=(0.2,0.2), dest_sz=(200,200)).save("arnie_20_20_200_200.jpg") ? CropFace(image, eye_left=(252,364), eye_right=(420,366), offset_pct=(0.3,0.3), dest_sz=(200,200)).save("arnie_30_30_200_200.jpg") ? CropFace(image, eye_left=(252,364), eye_right=(420,366), offset_pct=(0.2,0.2)).save("arnie_20_20_70_70.jpg")設(shè)想我們有一張施瓦辛格的照片?thisphoto of Arnold Schwarzenegger,人眼坐標(biāo)是(252,364)和(420,366)。參數(shù)是水平偏移、垂直偏移和你縮放后的圖像大小。[gm:我建議使用最小的那張圖片]
?
| Configuration | Cropped, Scaled, Rotated Face |
| 0.1 (10%), 0.1 (10%), (200,200) | |
| 0.2 (20%), 0.2 (20%), (200,200) | |
| 0.3 (30%), 0.3 (30%), (200,200) | |
| 0.2 (20%), 0.2 (20%), (70,70) |
?
?
?
?
CSV for the AT&T Facedatabase
| ? 1 ? 2 ? 3 ? 4 ? 5 ? 6 ? 7 ? 8 ? 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 | /home/philipp/facerec/data/at/s13/2.pgm;12 /home/philipp/facerec/data/at/s13/7.pgm;12 /home/philipp/facerec/data/at/s13/6.pgm;12 /home/philipp/facerec/data/at/s13/9.pgm;12 /home/philipp/facerec/data/at/s13/5.pgm;12 /home/philipp/facerec/data/at/s13/3.pgm;12 /home/philipp/facerec/data/at/s13/4.pgm;12 /home/philipp/facerec/data/at/s13/10.pgm;12 /home/philipp/facerec/data/at/s13/8.pgm;12 /home/philipp/facerec/data/at/s13/1.pgm;12 /home/philipp/facerec/data/at/s17/2.pgm;16 /home/philipp/facerec/data/at/s17/7.pgm;16 /home/philipp/facerec/data/at/s17/6.pgm;16 /home/philipp/facerec/data/at/s17/9.pgm;16 /home/philipp/facerec/data/at/s17/5.pgm;16 /home/philipp/facerec/data/at/s17/3.pgm;16 /home/philipp/facerec/data/at/s17/4.pgm;16 /home/philipp/facerec/data/at/s17/10.pgm;16 /home/philipp/facerec/data/at/s17/8.pgm;16 /home/philipp/facerec/data/at/s17/1.pgm;16 /home/philipp/facerec/data/at/s32/2.pgm;31 /home/philipp/facerec/data/at/s32/7.pgm;31 /home/philipp/facerec/data/at/s32/6.pgm;31 /home/philipp/facerec/data/at/s32/9.pgm;31 /home/philipp/facerec/data/at/s32/5.pgm;31 /home/philipp/facerec/data/at/s32/3.pgm;31 /home/philipp/facerec/data/at/s32/4.pgm;31 /home/philipp/facerec/data/at/s32/10.pgm;31 /home/philipp/facerec/data/at/s32/8.pgm;31 /home/philipp/facerec/data/at/s32/1.pgm;31 /home/philipp/facerec/data/at/s10/2.pgm;9 /home/philipp/facerec/data/at/s10/7.pgm;9 /home/philipp/facerec/data/at/s10/6.pgm;9 /home/philipp/facerec/data/at/s10/9.pgm;9 /home/philipp/facerec/data/at/s10/5.pgm;9 /home/philipp/facerec/data/at/s10/3.pgm;9 /home/philipp/facerec/data/at/s10/4.pgm;9 /home/philipp/facerec/data/at/s10/10.pgm;9 /home/philipp/facerec/data/at/s10/8.pgm;9 /home/philipp/facerec/data/at/s10/1.pgm;9 /home/philipp/facerec/data/at/s27/2.pgm;26 /home/philipp/facerec/data/at/s27/7.pgm;26 /home/philipp/facerec/data/at/s27/6.pgm;26 /home/philipp/facerec/data/at/s27/9.pgm;26 /home/philipp/facerec/data/at/s27/5.pgm;26 /home/philipp/facerec/data/at/s27/3.pgm;26 /home/philipp/facerec/data/at/s27/4.pgm;26 /home/philipp/facerec/data/at/s27/10.pgm;26 /home/philipp/facerec/data/at/s27/8.pgm;26 /home/philipp/facerec/data/at/s27/1.pgm;26 /home/philipp/facerec/data/at/s5/2.pgm;4 /home/philipp/facerec/data/at/s5/7.pgm;4 /home/philipp/facerec/data/at/s5/6.pgm;4 /home/philipp/facerec/data/at/s5/9.pgm;4 /home/philipp/facerec/data/at/s5/5.pgm;4 /home/philipp/facerec/data/at/s5/3.pgm;4 /home/philipp/facerec/data/at/s5/4.pgm;4 /home/philipp/facerec/data/at/s5/10.pgm;4 /home/philipp/facerec/data/at/s5/8.pgm;4 /home/philipp/facerec/data/at/s5/1.pgm;4 /home/philipp/facerec/data/at/s20/2.pgm;19 /home/philipp/facerec/data/at/s20/7.pgm;19 /home/philipp/facerec/data/at/s20/6.pgm;19 /home/philipp/facerec/data/at/s20/9.pgm;19 /home/philipp/facerec/data/at/s20/5.pgm;19 /home/philipp/facerec/data/at/s20/3.pgm;19 /home/philipp/facerec/data/at/s20/4.pgm;19 /home/philipp/facerec/data/at/s20/10.pgm;19 /home/philipp/facerec/data/at/s20/8.pgm;19 /home/philipp/facerec/data/at/s20/1.pgm;19 /home/philipp/facerec/data/at/s30/2.pgm;29 /home/philipp/facerec/data/at/s30/7.pgm;29 /home/philipp/facerec/data/at/s30/6.pgm;29 /home/philipp/facerec/data/at/s30/9.pgm;29 /home/philipp/facerec/data/at/s30/5.pgm;29 /home/philipp/facerec/data/at/s30/3.pgm;29 /home/philipp/facerec/data/at/s30/4.pgm;29 /home/philipp/facerec/data/at/s30/10.pgm;29 /home/philipp/facerec/data/at/s30/8.pgm;29 /home/philipp/facerec/data/at/s30/1.pgm;29 /home/philipp/facerec/data/at/s39/2.pgm;38 /home/philipp/facerec/data/at/s39/7.pgm;38 /home/philipp/facerec/data/at/s39/6.pgm;38 /home/philipp/facerec/data/at/s39/9.pgm;38 /home/philipp/facerec/data/at/s39/5.pgm;38 /home/philipp/facerec/data/at/s39/3.pgm;38 /home/philipp/facerec/data/at/s39/4.pgm;38 /home/philipp/facerec/data/at/s39/10.pgm;38 /home/philipp/facerec/data/at/s39/8.pgm;38 /home/philipp/facerec/data/at/s39/1.pgm;38 /home/philipp/facerec/data/at/s35/2.pgm;34 /home/philipp/facerec/data/at/s35/7.pgm;34 /home/philipp/facerec/data/at/s35/6.pgm;34 /home/philipp/facerec/data/at/s35/9.pgm;34 /home/philipp/facerec/data/at/s35/5.pgm;34 /home/philipp/facerec/data/at/s35/3.pgm;34 /home/philipp/facerec/data/at/s35/4.pgm;34 /home/philipp/facerec/data/at/s35/10.pgm;34 /home/philipp/facerec/data/at/s35/8.pgm;34 /home/philipp/facerec/data/at/s35/1.pgm;34 /home/philipp/facerec/data/at/s23/2.pgm;22 /home/philipp/facerec/data/at/s23/7.pgm;22 /home/philipp/facerec/data/at/s23/6.pgm;22 /home/philipp/facerec/data/at/s23/9.pgm;22 /home/philipp/facerec/data/at/s23/5.pgm;22 /home/philipp/facerec/data/at/s23/3.pgm;22 /home/philipp/facerec/data/at/s23/4.pgm;22 /home/philipp/facerec/data/at/s23/10.pgm;22 /home/philipp/facerec/data/at/s23/8.pgm;22 /home/philipp/facerec/data/at/s23/1.pgm;22 /home/philipp/facerec/data/at/s4/2.pgm;3 /home/philipp/facerec/data/at/s4/7.pgm;3 /home/philipp/facerec/data/at/s4/6.pgm;3 /home/philipp/facerec/data/at/s4/9.pgm;3 /home/philipp/facerec/data/at/s4/5.pgm;3 /home/philipp/facerec/data/at/s4/3.pgm;3 /home/philipp/facerec/data/at/s4/4.pgm;3 /home/philipp/facerec/data/at/s4/10.pgm;3 /home/philipp/facerec/data/at/s4/8.pgm;3 /home/philipp/facerec/data/at/s4/1.pgm;3 /home/philipp/facerec/data/at/s9/2.pgm;8 /home/philipp/facerec/data/at/s9/7.pgm;8 /home/philipp/facerec/data/at/s9/6.pgm;8 /home/philipp/facerec/data/at/s9/9.pgm;8 /home/philipp/facerec/data/at/s9/5.pgm;8 /home/philipp/facerec/data/at/s9/3.pgm;8 /home/philipp/facerec/data/at/s9/4.pgm;8 /home/philipp/facerec/data/at/s9/10.pgm;8 /home/philipp/facerec/data/at/s9/8.pgm;8 /home/philipp/facerec/data/at/s9/1.pgm;8 /home/philipp/facerec/data/at/s37/2.pgm;36 /home/philipp/facerec/data/at/s37/7.pgm;36 /home/philipp/facerec/data/at/s37/6.pgm;36 /home/philipp/facerec/data/at/s37/9.pgm;36 /home/philipp/facerec/data/at/s37/5.pgm;36 /home/philipp/facerec/data/at/s37/3.pgm;36 /home/philipp/facerec/data/at/s37/4.pgm;36 /home/philipp/facerec/data/at/s37/10.pgm;36 /home/philipp/facerec/data/at/s37/8.pgm;36 /home/philipp/facerec/data/at/s37/1.pgm;36 /home/philipp/facerec/data/at/s24/2.pgm;23 /home/philipp/facerec/data/at/s24/7.pgm;23 /home/philipp/facerec/data/at/s24/6.pgm;23 /home/philipp/facerec/data/at/s24/9.pgm;23 /home/philipp/facerec/data/at/s24/5.pgm;23 /home/philipp/facerec/data/at/s24/3.pgm;23 /home/philipp/facerec/data/at/s24/4.pgm;23 /home/philipp/facerec/data/at/s24/10.pgm;23 /home/philipp/facerec/data/at/s24/8.pgm;23 /home/philipp/facerec/data/at/s24/1.pgm;23 /home/philipp/facerec/data/at/s19/2.pgm;18 /home/philipp/facerec/data/at/s19/7.pgm;18 /home/philipp/facerec/data/at/s19/6.pgm;18 /home/philipp/facerec/data/at/s19/9.pgm;18 /home/philipp/facerec/data/at/s19/5.pgm;18 /home/philipp/facerec/data/at/s19/3.pgm;18 /home/philipp/facerec/data/at/s19/4.pgm;18 /home/philipp/facerec/data/at/s19/10.pgm;18 /home/philipp/facerec/data/at/s19/8.pgm;18 /home/philipp/facerec/data/at/s19/1.pgm;18 /home/philipp/facerec/data/at/s8/2.pgm;7 /home/philipp/facerec/data/at/s8/7.pgm;7 /home/philipp/facerec/data/at/s8/6.pgm;7 /home/philipp/facerec/data/at/s8/9.pgm;7 /home/philipp/facerec/data/at/s8/5.pgm;7 /home/philipp/facerec/data/at/s8/3.pgm;7 /home/philipp/facerec/data/at/s8/4.pgm;7 /home/philipp/facerec/data/at/s8/10.pgm;7 /home/philipp/facerec/data/at/s8/8.pgm;7 /home/philipp/facerec/data/at/s8/1.pgm;7 /home/philipp/facerec/data/at/s21/2.pgm;20 /home/philipp/facerec/data/at/s21/7.pgm;20 /home/philipp/facerec/data/at/s21/6.pgm;20 /home/philipp/facerec/data/at/s21/9.pgm;20 /home/philipp/facerec/data/at/s21/5.pgm;20 /home/philipp/facerec/data/at/s21/3.pgm;20 /home/philipp/facerec/data/at/s21/4.pgm;20 /home/philipp/facerec/data/at/s21/10.pgm;20 /home/philipp/facerec/data/at/s21/8.pgm;20 /home/philipp/facerec/data/at/s21/1.pgm;20 /home/philipp/facerec/data/at/s1/2.pgm;0 /home/philipp/facerec/data/at/s1/7.pgm;0 /home/philipp/facerec/data/at/s1/6.pgm;0 /home/philipp/facerec/data/at/s1/9.pgm;0 /home/philipp/facerec/data/at/s1/5.pgm;0 /home/philipp/facerec/data/at/s1/3.pgm;0 /home/philipp/facerec/data/at/s1/4.pgm;0 /home/philipp/facerec/data/at/s1/10.pgm;0 /home/philipp/facerec/data/at/s1/8.pgm;0 /home/philipp/facerec/data/at/s1/1.pgm;0 /home/philipp/facerec/data/at/s7/2.pgm;6 /home/philipp/facerec/data/at/s7/7.pgm;6 /home/philipp/facerec/data/at/s7/6.pgm;6 /home/philipp/facerec/data/at/s7/9.pgm;6 /home/philipp/facerec/data/at/s7/5.pgm;6 /home/philipp/facerec/data/at/s7/3.pgm;6 /home/philipp/facerec/data/at/s7/4.pgm;6 /home/philipp/facerec/data/at/s7/10.pgm;6 /home/philipp/facerec/data/at/s7/8.pgm;6 /home/philipp/facerec/data/at/s7/1.pgm;6 /home/philipp/facerec/data/at/s16/2.pgm;15 /home/philipp/facerec/data/at/s16/7.pgm;15 /home/philipp/facerec/data/at/s16/6.pgm;15 /home/philipp/facerec/data/at/s16/9.pgm;15 /home/philipp/facerec/data/at/s16/5.pgm;15 /home/philipp/facerec/data/at/s16/3.pgm;15 /home/philipp/facerec/data/at/s16/4.pgm;15 /home/philipp/facerec/data/at/s16/10.pgm;15 /home/philipp/facerec/data/at/s16/8.pgm;15 /home/philipp/facerec/data/at/s16/1.pgm;15 /home/philipp/facerec/data/at/s36/2.pgm;35 /home/philipp/facerec/data/at/s36/7.pgm;35 /home/philipp/facerec/data/at/s36/6.pgm;35 /home/philipp/facerec/data/at/s36/9.pgm;35 /home/philipp/facerec/data/at/s36/5.pgm;35 /home/philipp/facerec/data/at/s36/3.pgm;35 /home/philipp/facerec/data/at/s36/4.pgm;35 /home/philipp/facerec/data/at/s36/10.pgm;35 /home/philipp/facerec/data/at/s36/8.pgm;35 /home/philipp/facerec/data/at/s36/1.pgm;35 /home/philipp/facerec/data/at/s25/2.pgm;24 /home/philipp/facerec/data/at/s25/7.pgm;24 /home/philipp/facerec/data/at/s25/6.pgm;24 /home/philipp/facerec/data/at/s25/9.pgm;24 /home/philipp/facerec/data/at/s25/5.pgm;24 /home/philipp/facerec/data/at/s25/3.pgm;24 /home/philipp/facerec/data/at/s25/4.pgm;24 /home/philipp/facerec/data/at/s25/10.pgm;24 /home/philipp/facerec/data/at/s25/8.pgm;24 /home/philipp/facerec/data/at/s25/1.pgm;24 /home/philipp/facerec/data/at/s14/2.pgm;13 /home/philipp/facerec/data/at/s14/7.pgm;13 /home/philipp/facerec/data/at/s14/6.pgm;13 /home/philipp/facerec/data/at/s14/9.pgm;13 /home/philipp/facerec/data/at/s14/5.pgm;13 /home/philipp/facerec/data/at/s14/3.pgm;13 /home/philipp/facerec/data/at/s14/4.pgm;13 /home/philipp/facerec/data/at/s14/10.pgm;13 /home/philipp/facerec/data/at/s14/8.pgm;13 /home/philipp/facerec/data/at/s14/1.pgm;13 /home/philipp/facerec/data/at/s34/2.pgm;33 /home/philipp/facerec/data/at/s34/7.pgm;33 /home/philipp/facerec/data/at/s34/6.pgm;33 /home/philipp/facerec/data/at/s34/9.pgm;33 /home/philipp/facerec/data/at/s34/5.pgm;33 /home/philipp/facerec/data/at/s34/3.pgm;33 /home/philipp/facerec/data/at/s34/4.pgm;33 /home/philipp/facerec/data/at/s34/10.pgm;33 /home/philipp/facerec/data/at/s34/8.pgm;33 /home/philipp/facerec/data/at/s34/1.pgm;33 /home/philipp/facerec/data/at/s11/2.pgm;10 /home/philipp/facerec/data/at/s11/7.pgm;10 /home/philipp/facerec/data/at/s11/6.pgm;10 /home/philipp/facerec/data/at/s11/9.pgm;10 /home/philipp/facerec/data/at/s11/5.pgm;10 /home/philipp/facerec/data/at/s11/3.pgm;10 /home/philipp/facerec/data/at/s11/4.pgm;10 /home/philipp/facerec/data/at/s11/10.pgm;10 /home/philipp/facerec/data/at/s11/8.pgm;10 /home/philipp/facerec/data/at/s11/1.pgm;10 /home/philipp/facerec/data/at/s26/2.pgm;25 /home/philipp/facerec/data/at/s26/7.pgm;25 /home/philipp/facerec/data/at/s26/6.pgm;25 /home/philipp/facerec/data/at/s26/9.pgm;25 /home/philipp/facerec/data/at/s26/5.pgm;25 /home/philipp/facerec/data/at/s26/3.pgm;25 /home/philipp/facerec/data/at/s26/4.pgm;25 /home/philipp/facerec/data/at/s26/10.pgm;25 /home/philipp/facerec/data/at/s26/8.pgm;25 /home/philipp/facerec/data/at/s26/1.pgm;25 /home/philipp/facerec/data/at/s18/2.pgm;17 /home/philipp/facerec/data/at/s18/7.pgm;17 /home/philipp/facerec/data/at/s18/6.pgm;17 /home/philipp/facerec/data/at/s18/9.pgm;17 /home/philipp/facerec/data/at/s18/5.pgm;17 /home/philipp/facerec/data/at/s18/3.pgm;17 /home/philipp/facerec/data/at/s18/4.pgm;17 /home/philipp/facerec/data/at/s18/10.pgm;17 /home/philipp/facerec/data/at/s18/8.pgm;17 /home/philipp/facerec/data/at/s18/1.pgm;17 /home/philipp/facerec/data/at/s29/2.pgm;28 /home/philipp/facerec/data/at/s29/7.pgm;28 /home/philipp/facerec/data/at/s29/6.pgm;28 /home/philipp/facerec/data/at/s29/9.pgm;28 /home/philipp/facerec/data/at/s29/5.pgm;28 /home/philipp/facerec/data/at/s29/3.pgm;28 /home/philipp/facerec/data/at/s29/4.pgm;28 /home/philipp/facerec/data/at/s29/10.pgm;28 /home/philipp/facerec/data/at/s29/8.pgm;28 /home/philipp/facerec/data/at/s29/1.pgm;28 /home/philipp/facerec/data/at/s33/2.pgm;32 /home/philipp/facerec/data/at/s33/7.pgm;32 /home/philipp/facerec/data/at/s33/6.pgm;32 /home/philipp/facerec/data/at/s33/9.pgm;32 /home/philipp/facerec/data/at/s33/5.pgm;32 /home/philipp/facerec/data/at/s33/3.pgm;32 /home/philipp/facerec/data/at/s33/4.pgm;32 /home/philipp/facerec/data/at/s33/10.pgm;32 /home/philipp/facerec/data/at/s33/8.pgm;32 /home/philipp/facerec/data/at/s33/1.pgm;32 /home/philipp/facerec/data/at/s12/2.pgm;11 /home/philipp/facerec/data/at/s12/7.pgm;11 /home/philipp/facerec/data/at/s12/6.pgm;11 /home/philipp/facerec/data/at/s12/9.pgm;11 /home/philipp/facerec/data/at/s12/5.pgm;11 /home/philipp/facerec/data/at/s12/3.pgm;11 /home/philipp/facerec/data/at/s12/4.pgm;11 /home/philipp/facerec/data/at/s12/10.pgm;11 /home/philipp/facerec/data/at/s12/8.pgm;11 /home/philipp/facerec/data/at/s12/1.pgm;11 /home/philipp/facerec/data/at/s6/2.pgm;5 /home/philipp/facerec/data/at/s6/7.pgm;5 /home/philipp/facerec/data/at/s6/6.pgm;5 /home/philipp/facerec/data/at/s6/9.pgm;5 /home/philipp/facerec/data/at/s6/5.pgm;5 /home/philipp/facerec/data/at/s6/3.pgm;5 /home/philipp/facerec/data/at/s6/4.pgm;5 /home/philipp/facerec/data/at/s6/10.pgm;5 /home/philipp/facerec/data/at/s6/8.pgm;5 /home/philipp/facerec/data/at/s6/1.pgm;5 /home/philipp/facerec/data/at/s22/2.pgm;21 /home/philipp/facerec/data/at/s22/7.pgm;21 /home/philipp/facerec/data/at/s22/6.pgm;21 /home/philipp/facerec/data/at/s22/9.pgm;21 /home/philipp/facerec/data/at/s22/5.pgm;21 /home/philipp/facerec/data/at/s22/3.pgm;21 /home/philipp/facerec/data/at/s22/4.pgm;21 /home/philipp/facerec/data/at/s22/10.pgm;21 /home/philipp/facerec/data/at/s22/8.pgm;21 /home/philipp/facerec/data/at/s22/1.pgm;21 /home/philipp/facerec/data/at/s15/2.pgm;14 /home/philipp/facerec/data/at/s15/7.pgm;14 /home/philipp/facerec/data/at/s15/6.pgm;14 /home/philipp/facerec/data/at/s15/9.pgm;14 /home/philipp/facerec/data/at/s15/5.pgm;14 /home/philipp/facerec/data/at/s15/3.pgm;14 /home/philipp/facerec/data/at/s15/4.pgm;14 /home/philipp/facerec/data/at/s15/10.pgm;14 /home/philipp/facerec/data/at/s15/8.pgm;14 /home/philipp/facerec/data/at/s15/1.pgm;14 /home/philipp/facerec/data/at/s2/2.pgm;1 /home/philipp/facerec/data/at/s2/7.pgm;1 /home/philipp/facerec/data/at/s2/6.pgm;1 /home/philipp/facerec/data/at/s2/9.pgm;1 /home/philipp/facerec/data/at/s2/5.pgm;1 /home/philipp/facerec/data/at/s2/3.pgm;1 /home/philipp/facerec/data/at/s2/4.pgm;1 /home/philipp/facerec/data/at/s2/10.pgm;1 /home/philipp/facerec/data/at/s2/8.pgm;1 /home/philipp/facerec/data/at/s2/1.pgm;1 /home/philipp/facerec/data/at/s31/2.pgm;30 /home/philipp/facerec/data/at/s31/7.pgm;30 /home/philipp/facerec/data/at/s31/6.pgm;30 /home/philipp/facerec/data/at/s31/9.pgm;30 /home/philipp/facerec/data/at/s31/5.pgm;30 /home/philipp/facerec/data/at/s31/3.pgm;30 /home/philipp/facerec/data/at/s31/4.pgm;30 /home/philipp/facerec/data/at/s31/10.pgm;30 /home/philipp/facerec/data/at/s31/8.pgm;30 /home/philipp/facerec/data/at/s31/1.pgm;30 /home/philipp/facerec/data/at/s28/2.pgm;27 /home/philipp/facerec/data/at/s28/7.pgm;27 /home/philipp/facerec/data/at/s28/6.pgm;27 /home/philipp/facerec/data/at/s28/9.pgm;27 /home/philipp/facerec/data/at/s28/5.pgm;27 /home/philipp/facerec/data/at/s28/3.pgm;27 /home/philipp/facerec/data/at/s28/4.pgm;27 /home/philipp/facerec/data/at/s28/10.pgm;27 /home/philipp/facerec/data/at/s28/8.pgm;27 /home/philipp/facerec/data/at/s28/1.pgm;27 /home/philipp/facerec/data/at/s40/2.pgm;39 /home/philipp/facerec/data/at/s40/7.pgm;39 /home/philipp/facerec/data/at/s40/6.pgm;39 /home/philipp/facerec/data/at/s40/9.pgm;39 /home/philipp/facerec/data/at/s40/5.pgm;39 /home/philipp/facerec/data/at/s40/3.pgm;39 /home/philipp/facerec/data/at/s40/4.pgm;39 /home/philipp/facerec/data/at/s40/10.pgm;39 /home/philipp/facerec/data/at/s40/8.pgm;39 /home/philipp/facerec/data/at/s40/1.pgm;39 /home/philipp/facerec/data/at/s3/2.pgm;2 /home/philipp/facerec/data/at/s3/7.pgm;2 /home/philipp/facerec/data/at/s3/6.pgm;2 /home/philipp/facerec/data/at/s3/9.pgm;2 /home/philipp/facerec/data/at/s3/5.pgm;2 /home/philipp/facerec/data/at/s3/3.pgm;2 /home/philipp/facerec/data/at/s3/4.pgm;2 /home/philipp/facerec/data/at/s3/10.pgm;2 /home/philipp/facerec/data/at/s3/8.pgm;2 /home/philipp/facerec/data/at/s3/1.pgm;2 /home/philipp/facerec/data/at/s38/2.pgm;37 /home/philipp/facerec/data/at/s38/7.pgm;37 /home/philipp/facerec/data/at/s38/6.pgm;37 /home/philipp/facerec/data/at/s38/9.pgm;37 /home/philipp/facerec/data/at/s38/5.pgm;37 /home/philipp/facerec/data/at/s38/3.pgm;37 /home/philipp/facerec/data/at/s38/4.pgm;37 /home/philipp/facerec/data/at/s38/10.pgm;37 /home/philipp/facerec/data/at/s38/8.pgm;37 /home/philipp/facerec/data/at/s38/1.pgm;37 |
?
C#版的人臉識(shí)別(只實(shí)現(xiàn)了特征臉)EMGU Multiple Face Recognition using PCA and Parallel Optimisatioin:
?http://www.codeproject.com/Articles/261550/EMGU-Multiple-Face-Recognition-using-PCA-and-Paral?msg=4377858
總結(jié)
以上是生活随笔為你收集整理的怎样使用OpenCV进行人脸识别的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 日本各地方与所属各县名称及其读音
- 下一篇: OpenCV3如何使用SIFT和SURF