前言web
接着上篇《IOS7下的人臉檢測》,咱們順藤摸瓜的學習怎樣在IOS7下用openCV的進行人臉識別。實際上很是easy,由於人臉檢測部分已經完畢。剩下的無非調用openCV的方法對採集到的人臉樣本進行訓練,終於獲得一個可以預測人臉的模型。但是當中的原理可謂是博大精深,由於快臨最近末考試了。沒時間去琢磨當中詳細的細節。此次就先寫個大概的demo,下次更新文章就獲得6月20號以後了。算法
原理:數據庫
從OpenCV2.4以後,openCV增長了新的類FaceRecognizer,咱們可以使用它便捷地進行人臉識別。ide
眼下FaceRecognizer類支持的人臉識別有三種。特徵臉EigenFace、Fisher臉FisherFace、局部二元模式直方圖LBPHFace。分別調用函數createEigenFaceRecognizer、createFisherFaceRecognizer、createLBPHFaceRecognizer創建模型,如下分別對三種方法作介紹。函數
EigenFace性能
顧明思議事實上就是特徵臉的方法,也稱爲基於主成分分析(principal component analysis,簡稱PCA)的人臉識別方法,至於什麼是PCA及其原理可以看看這篇:特徵臉(Eigenface)理論基礎-PCA(主成分分析法)。學習
特徵子臉技術的基本思想是:從統計的觀點,尋找人臉圖像分佈的基本元素。即人臉圖像樣本集協方差矩陣的特徵向量。以此近似地表徵人臉圖像。spa
這些特徵向量稱爲特徵臉(Eigenface)。.net
實際上。特徵臉反映了隱含在人臉樣本集合內部的信息和人臉的結構關係。將眼睛、面頰、下頜的樣本集協方差矩陣的特徵向量稱爲特徵眼、特徵頜和特徵脣。統稱特徵子臉。設計
特徵子臉在對應的圖像空間中生成子空間,稱爲子臉空間。計算出測試圖像窗體在子臉空間的投影距離。若窗體圖像知足閾值比較條件。則推斷其爲人臉。
基於特徵分析的方法,也就是將人臉基準點的相對照率和其餘描寫敘述人臉臉部特徵的形狀參數或類別參數等一塊兒構成識別特徵向量。這樣的基於整體臉的識別不只保留了人臉部件之間的拓撲關係,而且也保留了各部件自己的信息,而基於部件的識別則是經過提取出局部輪廓信息及灰度信息來設計詳細識別算法。現在Eigenface(PCA)算法已經與經典的模板匹配算法一塊兒成爲測試人臉識別系統性能的基準算法。而自1991年特徵臉技術誕生以來,研究者對其進行了各類各樣的實驗和理論分析。FERET'96測試結果也代表,改進的特徵臉算法是主流的人臉識別技術,也是具備最好性能的識別方法之中的一個。
FisherFace
主成分分析是一種基於特徵臉的方法,找到使數據中最慷慨差的特徵線性組合。
這是一個表現數據的強慷慨法。但它沒有考慮類別信息,並且在扔掉主元時。同一時候不少有鑑別的信息都被扔掉。
若是你數據庫中的變化主要是光照變化,那麼PCA此時差點兒失效了。
線性鑑別分析在降維的同一時候考慮類別信息,由統計學家 Sir R. A. Fisher發明。其訴求是爲了找到一種特徵組合方式。達到最大的類間離散度和最小的類內離散度。這個想法很是easy:在低維表示下。一樣的類應該牢牢的聚在一塊兒。而不一樣的類別儘可能距離越遠。 這也被Belhumeur, Hespanha 和 Kriegman所認同。因此他們把鑑別分析引入到人臉識別問題中。
LBPH
LBP的基本思想是對圖像的像素和它局部周圍像素進行對照後的結果進行求和。把這個像素做爲中心。對相鄰像素進行閾值比較。
假設中心像素的亮度大於等於他的相鄰像素,把他標記爲1,不然標記爲0。
你會用二進制數字來表示每個像素。比方11001111。所以,由於周圍相鄰8個像素。你終於可能獲取2^8個可能組合,被稱爲局部二值模式,有時被稱爲LBP碼。
以上內容部分摘自於http://m.blog.csdn.net/blog/ningningxl/10903581,假設更深刻地瞭解這三種算法。可以看看這篇文章。
案例實戰
好了。直接進入正題。這裏我採用openCV的createEigenFaceRecognizer方法,其它的兩種方法大同小異。程序仍是在上篇的基礎上進行修改。請參看:【從零學習openCV】IOS7下的人臉檢測
界面設計例如如下。應該很是easy看出各個功能控件是幹啥的吧 :-)
如下對每一個功能進行說明:
選擇照片:這個請參考我以前的文章。
檢測裁剪
代碼例如如下,詳細原理請看我上篇文章。
- (void) opencvFaceDetect { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; UIImage* img = [image copy]; if(img) { cvSetErrMode(CV_ErrModeParent); IplImage *image = [self CreateIplImageFromUIImage:img]; IplImage *grayImg = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1); //先轉爲灰度圖 cvCvtColor(image, grayImg, CV_BGR2GRAY); //將輸入圖像縮小4倍以加快處理速度 int scale = 4; IplImage *small_image = cvCreateImage(cvSize(image->width/scale,image->height/scale), IPL_DEPTH_8U, 1); cvResize(grayImg, small_image); //載入分類器 NSString *path = [[NSBundle mainBundle] pathForResource:@"haarcascade_frontalface_alt2" ofType:@"xml"]; CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad([path cStringUsingEncoding:NSASCIIStringEncoding], NULL, NULL, NULL); CvMemStorage* storage = cvCreateMemStorage(0); cvClearMemStorage(storage); //關鍵部分,使用cvHaarDetectObjects進行檢測,獲得一系列方框 CvSeq* faces = cvHaarDetectObjects(small_image, cascade, storage ,1.1, (int)self.slider.value, CV_HAAR_DO_CANNY_PRUNING, cvSize(0,0), cvSize(0, 0)); NSLog(@"faces:%d",faces->total); cvReleaseImage(&small_image); cvReleaseImage(&grayImg); if(faces->total>0) { CvRect cvrect = *(CvRect*)cvGetSeqElem(faces, 0); //默認取第一張人臉 cvSetImageROI(image, cvRect(cvrect.x*scale, cvrect.y*scale , cvrect.width*scale, cvrect.height*scale)); //設置ROI,實現區域裁剪 RoIImg = cvCreateImage(cvSize(cvrect.width*scale,cvrect.height*scale), IPL_DEPTH_8U, 3); cvCvtColor(image, RoIImg, CV_BGR2RGB); cvResetImageROI(image); self.imageView.image = [self UIImageFromIplImage:RoIImg]; } cvReleaseImage(&image); } [pool release]; }
增長訓練
獲得了裁剪後的圖片還需要對訓練圖片進行預處理,先轉爲灰度圖,並且調整爲同一大小(我設成了50*50)。這些都是EigenFaceRecognizer的要求,最後進行歸一化,防止光照帶來的影響。
- (IBAction)addTrainClicked:(id)sender { IplImage *grayImg = cvCreateImage(cvGetSize(RoIImg), IPL_DEPTH_8U, 1); //先轉爲灰度圖 cvCvtColor(RoIImg, grayImg, CV_BGR2GRAY); IplImage *small_image = cvCreateImage(cvSize(50,50), IPL_DEPTH_8U, 1); //統一大小 cvResize(grayImg, small_image); cv::Mat cur_mat = cv::cvarrToMat(small_image,true),des_mat; cv::normalize(cur_mat,des_mat,0, 255, cv::NORM_MINMAX, CV_8UC1); //歸一化 images.push_back(des_mat); int labelnum = [self.labelEdit.text intValue]; //獲得編輯框的數字,做爲此圖像的label labels.push_back(labelnum); self.addTrainBtn.enabled = NO; }生成模型
直接調用createEigenFaceRecognizer就能夠,選取PCA主成分維度爲10
- (IBAction)GetModelClicked:(id)sender { model = cv::createEigenFaceRecognizer(10);//PCA主成分的維數爲10 model->train(images,labels); NSLog(@"生成模型!"); }
點擊預測button就可以用獲得的模型對人臉圖片進行預測了,注意打開一張照片後得先進行檢測裁剪後才幹預測。
- (IBAction)PredictClicked:(id)sender { IplImage *grayImg = cvCreateImage(cvGetSize(RoIImg), IPL_DEPTH_8U, 1); //先轉爲灰度圖 cvCvtColor(RoIImg, grayImg, CV_BGR2GRAY); IplImage *small_image = cvCreateImage(cvSize(50,50), IPL_DEPTH_8U, 1); //統一大小 cvResize(grayImg, small_image); cv::Mat cur_mat = cv::cvarrToMat(small_image,true),des_mat; cv::normalize(cur_mat,des_mat,0, 255, cv::NORM_MINMAX, CV_8UC1); //歸一化 int pred = model->predict(des_mat); NSString* tip = [NSString stringWithFormat:@"label:%d",pred]; UIAlertView *alter = [[UIAlertView alloc] initWithTitle:@"識別結果" message:tip delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil]; [alter show]; NSLog(@"%d",pred); }
終於效果:
步驟1:先對楊冪女神的三張寫真進行檢測裁剪,改訓練label爲1。點擊增長訓練button。
步驟2:再對詩詩女神的三張寫真進行檢測裁剪,改訓練label爲2。點擊增長訓練button。
步驟3:點擊生成模型button。
步驟4:打開楊冪女神的另一張照片,進行檢測裁剪後,點擊預測。識別結果爲1,匹配正確。
步驟5:打開詩詩女神的另一張照片。進行檢測裁剪後,點擊預測,識別結果爲2,匹配正確。
可見openCV的特徵臉算法能識別出美女之間的差別O(∩_∩)O
最後整個案例代碼奉上,爲期末考攢人品吧:IOS7下用openCV實現人臉檢測加識別demo
(轉載請註明做者和出處:Shawn-HT http://blog.csdn.net/shawn_ht 未經贊成請勿用於商業用途)
參考文章:
http://blog.csdn.net/liulina603/article/details/7925170
http://m.blog.csdn.net/blog/ningningxl/10903581
http://www.muxiaofei.com/class-facerecognizer-on-the-opencv-face-recognition-face-recognition/