OpenCV人臉識別的原理 .

在之前講到的人臉測試后,提取出人臉來,并且保存下來,以供訓練或識別是用,提取人臉的代碼如下:

[html]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. void?GetImageRect(IplImage*?orgImage,?CvRect?rectInImage,?IplImage*?imgRect,double?scale)??
  2. {??
  3. ????//從圖像orgImage中提取一塊(rectInImage)子圖像imgRect??
  4. ????IplImage?*result=imgRect;??
  5. ????CvRect?size;??
  6. ????size.x=rectInImage.x*scale;??
  7. ????size.y=rectInImage.y*scale;??
  8. ????size.width=rectInImage.width*scale;??
  9. ????size.height=rectInImage.height*scale;??
  10. ??????
  11. ????//result=cvCreateImage(?size,?orgImage->depth,?orgImage->nChannels?);??
  12. ????//從圖像中提取子圖像??
  13. ????cvSetImageROI(orgImage,size);??
  14. ????cvCopy(orgImage,result);??
  15. ????cvResetImageROI(orgImage);??
  16. }??


人臉預處理

現在你已經得到一張人臉,你可以使用那張人臉圖片進行人臉識別。然而,假如你嘗試這樣簡單地從一張普通圖片直接進行人臉識別的話,你將會至少損失10%的準確率!

在一個人臉識別系統中,應用多種預處理技術對將要識別的圖片進行標準化處理是極其重要的。多數人臉識別算法對光照條件十分敏感,所以假如在暗室訓練,在明亮的房間就可能不會被識別出來等等。這個問題可歸于“lumination dependent”,并且還有其它很多例子,比如臉部也應當在圖片的一個十分固定的位置(比如眼睛位置為相同的像素坐標),固定的大小,旋轉角度,頭發和裝飾,表情(笑,怒等),光照方向(向左或向上等),這就是在進行人臉識別前,使用好的圖片預處理過濾器十分重要的原因。你還應該做一些其它事情,比如去除臉部周圍的多余像素(如用橢圓遮罩,只顯示其內部的人臉區域而不是頭發或圖片背景,因為他們的變化多于臉部區域)。

為簡單起見,我展示給你的人臉識別系統是使用灰度圖像的特征臉方法。所以我將向你說明怎樣簡單地把彩色圖像轉化為灰度圖像,并且之后簡單地使用直方圖均衡化(Histogram Equalization)作為一種自動的標準化臉部圖像亮度和對比度的方法。為了得到更好的結果,你可以使用彩色人臉識別(color face recognition,ideally with color histogram fitting in HSV or another color space instead of RGB),或者使用更多的預處理,比如邊緣增強(edge enhancement),輪廓檢測(contour detection),手勢檢測(motion detection),等等。
你可以看到一個預處理階段的例子:

?

這是把一幅RGB格式的圖像或灰度圖像轉變為灰度圖像的基本代碼。它還把圖像調整成了固定的維度,然后應用直方圖均衡化來實現固定的亮度和對比度。

PCA原理

現在你已經有了一張經過預處理后的臉部圖片,你可以使用特征臉(PCA)進行人臉識別。OpenCV自帶了執行PCA操作的”cvEigenDecomposite()”函數,然而你需要一個圖片數據庫(訓練集)告訴機器怎樣識別當中的人。

所以你應該收集每個人的一組預處理后的臉部圖片用于識別。比如,假如你想要從10人的班級當中識別某個人,你可以為每個人存儲20張圖片,總共就有200張大小相同(如100×100像素)的經預處理的臉部圖片。

特征臉的理論在Servo Magazine的兩篇文章(Face Recognition with Eigenface)中解釋了,但我仍會在這里嘗試著向你解釋。

我們使用“主元分析”把你的200張訓練圖片轉換成一個代表這些訓練圖片主要區別的“特征臉”集。首先它將會通過獲取每個像素的平均值,生成這些圖片的“平均人臉圖片”。然后特征臉將會與“平均人臉”比較。第一個特征臉是最主要的臉部區別,第二個特征臉是第二重要的臉部區別,等……直到你有了大約50張代表大多數訓練集圖片的區別的特征臉。

??
? ?
在上面這些示例圖片中你可以看到平均人臉和第一個以及最后一個特征臉。注意到,平均人臉顯示的是一個普通人的平滑臉部結構,排在最前的一些特征臉顯示了一些主要的臉部特征,而最后的特征臉(比如Eigenface 119)主要是圖像噪聲。你可以在下面看到前32張特征臉。


?
簡單地說,特征臉方法(Principal Component Analysis)計算出了訓練集中圖片的主要區別,并且用這些“區別”的組合來代表每幅訓練圖片。
比如,一張訓練圖片可能是如下的組成:

(averageFace) + (13.5% of eigenface0) – (34.3% of eigenface1) + (4.7% of eigenface2) + … + (0.0% of eigenface199).
一旦計算出來,就可以認為這張訓練圖片是這200個比率(ratio):

{13.5, -34.3, 4.7, …, 0.0}.

用特征臉圖片分別乘以這些比率,并加上平均人臉圖片 (average face),從這200個比率還原這張訓練圖片是完全可以做到的。但是既然很多排在后面的特征臉是圖像噪聲或者不會對圖片有太大作用,這個比率表可以被降低到只剩下最主要的,比如前30個,不會對圖像質量有很大影響。所以現在可以用30個特征臉,平均人臉圖片,和一個含有30個比率的表,來代表全部的200張訓練圖片。

在另一幅圖片中識別一個人,可以應用相同的PCA計算,使用相同的200個特征臉來尋找200個代表輸入圖片的比率。并且仍然可以只保留前30個比率而忽略其余的比率,因為它們是次要的。然后通過搜索這些比率的表,尋找在數據庫中已知的20個人,來看誰的前30個比率與輸入圖片的前30個比率最接近。這就是尋找與輸入圖片最相似的訓練圖片的基本方法,總共提供了200張訓練圖片。

訓練圖片

創建一個人臉識別數據庫,就是訓練一個列出圖片文件和每個文件代表的人的文本文件,形成一個facedata.xml“文件。
比如,你可以把這些輸入一個名為”trainingphoto.txt”的文本文件:
joke1.jpg
joke2.jpg
joke3.jpg
joke4.jpg
lily1.jpg
lily2.jpg
lily3.jpg
lily4.jpg
它告訴這個程序,第一個人的名字叫“joke,而joke有四張預處理后的臉部圖像,第二個人的名字叫”lily”,有她的四張圖片。這個程序可以使用”loadFaceImgArray()”函數把這些圖片加載到一個圖片數組中。

為了從這些加載好的圖片中創建一個數據庫,你可以使用OpenCV的”cvCalcEigenObjects()”和”cvEigenDecomposite()”函數。

獲得特征空間的函數:

[html]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. void?cvCalcEigenObjects(?int?nObjects,?void*?input,?void*?output,?int?ioFlags,?int?ioBufSize,?void*?userData,CvTermCriteria*?calcLimit,?IplImage*?avg,?float*?eigVals?)??

nObjects:目標的數目,即輸入訓練圖片的數目。
input:輸入訓練的圖片。
output:輸出特征臉,總共有nEigens
ioFlags、ioBufSize:默認為0
userData:指向回調函數(callback function)必須數據結構體的指針。
calcLimit:終止迭代計算目標特征的條件。根據calcLimit的參數,計算會在前nEigens主要特征目標被提取后結束(這句話有點繞,應該就是提取了前nEigens個特征值,),另一種結束的情況是:目前特征值同最s大特征值的比值降至calcLimit的epsilon值之下。
賦值如下calcLimit = cvTermCriteria( CV_TERMCRIT_ITER, nEigens, 1);
它的類型定義如下:
typedef struct CvTermCriteria
{
  int type;  int max_iter;    //最大迭代次數
  double epsilon;    //結果精確性
}
avg:訓練樣本的平均圖像
eigVals:以降序排列的特征值的行向量指針。可以為0。

最后將所得數據形成一個facedata.xml“文件保存下來,它可以隨時被重新載入來識別經訓練過的人。

圖像在特征空間的投影:

[html]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. void?cvEigenDecomposite(?IplImage*?obj,?int?nEigObjs,?void*?eigInput,int?ioFlags,?void*?userData,?IplImage*?avg,?float*?coeffs?);??


?

obj:輸入圖像,訓練或識別圖像
nEigObjs:特征空間的eigen數量
eigInput:特征空間中的特征臉
ioFlags、userData:默認為0
avg:特征空間中的平均圖像
coeffs:這是唯一一個輸出,即人臉在子空間的投影,特征值

識別的過程

1. 讀取用于測試的圖片。

2. 平均人臉,特征臉和特征值(比率)使用函數“loadTrainingData()” 從人臉識別數據庫文件(the face recognition database fil)“facedata.xml”載入。

3. 使用OpenCV的函數“cvEigenDecomposite()”,每張輸入的圖片都被投影到PCA子空間,來觀察哪些特征臉的比率最適合于代表這張圖片。

4. 現在有了特征值(特征臉圖片的比率)代表這張輸入圖片,程序需要查找原始的訓練圖片,找出擁有最相似比率的圖片。這些用數學的方法在“findNearestNeighbor()”函數中執行,采用的是“歐幾里得距離(Euclidean Distance)”,但是它只是基本地檢查輸入圖片與每張訓練圖片的相似性,找到最相似的一張:一張在歐幾里得空間上與輸入圖片距離最近的圖片。就像在 Servo Magazine的文章上提到的那樣,如果使用馬氏距離( the Mahalanobis space,需要在代碼里定義 USE_MAHALANOBIS_DISTANCE),你可以得到更準確的結果。

5. 在輸入圖片與最相似圖片之間的距離用于確定可信度(confidence),作為是否識別出某人的指導。1.0的可信度意味著完全相同,0.0或者負的可信度意味著非常不相似。但是需要注意,我在代碼中用到的可信度公式只是一個非常基本的可信度測量,不是很可靠,但是我覺得多數人會想要看到一個粗略的可信度值。你可能發現它對你的圖片給出錯誤的值,所以你可以禁用它(比如:把可信度設為恒定的1.0)。

一旦指導哪張訓練圖片和輸入圖片最相似,并假定可信度值不是太低(應該至少是0.6或更高),那么它就指出了那個人是誰,換句話說,它識別出了那個人!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/387666.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/387666.shtml
英文地址,請注明出處:http://en.pswp.cn/news/387666.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

說一下SEO和SEM到底有哪些區別?

開場白免了,我們直接說與主題相關的。 SEO和SEM到底有什么區別? SEO和SEM到底有什么區別 我們先理解字面意思: SEO(Search Engine Optimization):漢譯為搜索引擎優化。 SEM(Search Engine Marke…

django模型的繼承

很多時候,我們都不是從‘一窮二白’開始編寫模型的,有時候可以從第三方庫中繼承,有時候可以從以前的代碼中繼承,甚至現寫一個模型用于被其它模型繼承。這樣做的好處,我就不贅述了,每個學習Django的人都非常…

SpringBoot部署項目到Docker倉庫

SpringBoot部署項目到Docker倉庫1.開啟遠程控制端口Centos7開啟方式: vim /lib/systemd/system/docker.service找到ExecStart行 ExecStart/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock 重啟docker 啟動 systemctl start docker守護進程…

人臉識別經典方法

這篇文章是擼主要介紹人臉識別經典方法的第一篇,后續會有其他方法更新。特征臉方法基本是將人臉識別推向真正可用的第一種方法,了解一下還是很有必要的。特征臉用到的理論基礎PCA在另一篇博客里:特征臉(Eigenface)理論基礎-PCA(主成分分析法)…

Jquery常用正則驗證

常用校驗的正則表達式var rulesConfig { /** * str.replace(/^\s|\s$/g, ) 解析: str:要替換的字符串 \s : 表示 space ,空格 : 一個或多個 ^: 開始,^\s,以空格開始 $: 結束&#x…

svm參數說明

svm參數說明---------------------- 如果你要輸出類的概率,一定要有-b參數 svm-train training_set_file model_file svm-predict test_file model_fileoutput_file 自動腳本:Python easy.py train_data test_data 自動選擇最優參數,自動進行…

poj-3667(線段樹區間合并)

題目鏈接&#xff1a;傳送門 參考文章&#xff1a;傳送門 思路&#xff1a;線段樹區間合并問題&#xff0c;每次查詢到滿足線段樹的區間最左值&#xff0c;然后更新線段樹。 #include<iostream> #include<cstdio> #include<cstring> using namespace std; co…

面試題編程題11-python 生成隨機數

隨機整數&#xff1a; random.randint(a,b), [a,b] random.randrange(a,b,step) [a,b) 隨機實數 random.random()返回0 到1 之間的浮點數轉載于:https://www.cnblogs.com/feihujiushiwo/p/10922454.html

車牌識別之顏色選取

車牌定位是車牌識別中第一步&#xff0c;也是最重要的一步。 由于中國車牌種類多樣&#xff0c;顏色不一&#xff0c; 再加上車牌經常有污損&#xff0c;以及車牌周圍干擾因素太多&#xff0c;都成為了車牌定位的難點。 這里首先使用最簡單算法來描述車牌定位&#xff0c;以及他…

Python - 排序( 插入, 冒泡, 快速, 二分 )

插入排序 算法分析 兩次循環, 大循環對隊列中的每一個元素拿出來作為小循環的裁定對象 小循環對堆當前循環對象在有序隊列中尋找插入的位置 性能參數 空間復雜度  O(1) 時間復雜度  O(n^2) 詳細代碼解讀 import randomdef func(l):# 外層循環: 對應遍歷所有的無序數據for i…

[EmguCV|C#]使用CvInvoke自己繪製色彩直方圖-直方圖(Hitsogram)系列(4)

2014-02-0610325 0C# 檢舉文章 過年結束了&#xff0c;雖然還是學生所以其實還有兩個禮拜的假期&#xff0c;不過為了不讓自己發慌&#xff0c;趁著假期多利用充實自己&#xff0c;所以提早回到開工狀態&#xff0c;而這次總算要把一直說的自己動手繪製猜色直方圖文章寫出。 …

G.點我

鏈接&#xff1a;https://ac.nowcoder.com/acm/contest/903/G 題意&#xff1a; X腿與隊友到河北省來參加2019河北省大學生程序設計競賽&#xff0c;然而這場比賽的題目難度實在是太高了。比賽開始一個小時后&#xff0c;X腿仍然沒有做出一個題。這時候&#xff0c;X腿驚訝的發…

輪廓的查找、表達、繪制、特性及匹配(How to Use Contour? Find, Component, Construct, Features Match)

前言 輪廓是構成任何一個形狀的邊界或外形線。前面講了如何根據色彩及色彩的分布&#xff08;直方圖對比和模板匹配&#xff09;來進行匹配&#xff0c;現在我們來看看如何利用物體的輪廓。包括以下內容&#xff1a;輪廓的查找、表達方式、組織方式、繪制、特性、匹配。 查…

Android:IntentService的學習

在Android的四大組件中&#xff0c;Service排行老二&#xff0c;在Android中的主要作用是后臺服務&#xff0c;進行與界面無關的操作。由于Service運行在主線程&#xff0c;所以進行異步操作需要在子線進行。為此Android為我們提供了IntentService。 IntentService是一個抽象類…

智能商業大會構造信息化交流平臺

在快速發展的當今社會&#xff0c;所有事物都在日新月異地變化著&#xff0c;相較于過去的傳統商業的變化速度&#xff0c;現今基于數據的互聯網商業變化速度高出了一個量級&#xff0c;同時市場對于企業的應對速度也有了更高的要求&#xff0c;然而面對大體量的數據&#xff0…

itcast-ssh-crm實踐

分析 BaseDao 文件上傳 轉載于:https://www.cnblogs.com/hellowq/p/10209761.html

分類器大牛們

David Lowe&#xff1a;Sift算法的發明者&#xff0c;天才。 Rob Hess&#xff1a;sift的源碼OpenSift的作者&#xff0c;個人主頁上有openSift的下載鏈接&#xff0c;Opencv中sift的實現&#xff0c;也是參考這個。 Koen van de Sande&#xff1a;作者給出了sift,densesift,co…

go 成長路上的坑(1)

一、先來看一段代碼 package mainimport "fmt"type X struct{}func (x *X) test(){println("h1",x) } func main(){a : X{} a.test()(&X{}).test()(X{}).test() } 猜猜他的結果 二、揭曉答案 package mainimport "fmt"type X struct{}func (…

利用python腳本程序監控文件被修改

需求&#xff1a;利用python編寫監控程序&#xff0c;監控一個文件目錄&#xff0c;當目錄下的文件發生改變時&#xff0c;實現有修改就發報警郵件 郵件使用QQ郵箱&#xff0c;需要開啟smtp&#xff0c;使用手機發生短信&#xff0c;騰訊會給你發郵箱密碼。如下所示&#xff1a…

Oracle RAC

環境如下&#xff1a; Linux操作系統&#xff1a;Centos 6.5 64bit &#xff08;這個版本的redhat 6內核等OS在安裝grid最后執行root.sh時會出現crs-4124&#xff0c;是oracle11.2.0.1的bug&#xff09; VMware version&#xff1a;Workstation 8.0.3 build-703057 Oracle…