文章目錄
- 0 簡介
- 1 人臉識別 - 常用實作技術
- 1.1 基于幾何特征的人臉識別方法
- 1.2 初級神經網路方法,
- 1.3 深度學習方法,
- 2 人臉識別演算法缺陷
- 3 人臉識別流程
- 3.1 相關資料集
- 3.2 對齊
- 3.3 仿射變換
- 3.4 人臉目標檢測
- 3.5 人臉特征提取
- 3.5.1 分類模型有哪些
- 3.5.2 度量學習模型——FaceNet為例
- 3.6 人臉識別(特征分類)
- 3.6.1 歐氏距離
- 3.6.2 余弦距離
- 3.6.3 Joint Bayesian 方法
- 4 實作程序
- 4.1 自己構建人臉資料集
- 4.1.1 拍照程式
- 4.2 預處理
- 4.3 人臉特征提取
- 5 識別效果
- 5.1 人臉檢測效果
- 5.2 人臉識別結果
- 6 最后-畢設幫助
0 簡介
今天學長向大家介紹一個機器視覺的畢設專案,基于深度學習的人臉識別
:基于深度學習的人臉識別【全網最詳細】 - opencv 卷積神經網路
畢設幫助,開題指導,技術解答
🇶746876041

1 人臉識別 - 常用實作技術
人臉識別主要研究的是如何獲得高效的特征, 并利進行人臉匹配的計算, 至今為止人臉識別的演算法已經很多,
1.1 基于幾何特征的人臉識別方法
該方法所考慮的特征相對樸, 所謂的幾何特征是指人臉影像上各器官等的相對位置或相對距離所組成的矢量, 具體指利用人工方式標出人臉影像特征點位置, 對標定好的特征點計算相對距離; 將所得的多個距離按照預定順序組成一個矢量, 該矢量即為幾何特征, Nicholas Roeder 和 Xiaobo Li 對幾何特征的提取進行了詳細研究, 由于幾何特征只是粗略的描述的人臉影像, 因此效果并不如人意,
1.2 初級神經網路方法,
Intrato將無監督/監督混合神經網路應用到人臉識別問題上,該方法比傳統的 BP 神經網路提取的特征更有效, Cottrell 應用級聯 BP 神經網路較好的解決了人臉遮擋和光照變化的問題, W.Shiqian Wu 將 RBF 和 DCT 神經網路應用到人臉識別問題上, E.Osuna 將支持向量機(SVM)應用到人臉識別問題, Kung 和Lin 結合神經網路和統計學方法, 提出了基于概率決策的神經網路(PDBNN),此方法也獲得了很好的結果, 這些方法都取得了較好的效果, 神經網路方法雖然簡化了特征提取的作業, 學習到更加有效的特征, 但是神經網路往往有數目眾多的神經元組成,因此訓練耗時且難于收斂,
1.3 深度學習方法,
其實深度學習早在 20 世紀 90 年代就已經提出, 但是由于當時計算機技術的限制, 深度學習 并沒得到很大的重視和發展, 直到 2012 年由 AlexKrizhevsky 提出的 AlexNet 卷積神經網路在 ILSVRC 影像分類競賽中表示例外突出,從此深度學習尤其是其中的卷積神經網路得到了人們的廣泛關注和深入的研究, 除了在香港中文大學的 DeepID 系列, 還有 Google 提出 FaceNet 網路 [25] , 牛津大學提出的VGG 網路等許多不同的網路, 這些網路都取得了很好的效果,深度學習具有特征自動學習, 泛化能力強和所學特征表現里強等優點, 因此深度學習在人臉識別問題上的應用極大的推動的人臉識別的發展, 但是深度學習也具有所需訓練資料巨大、 訓練耗時長和難于收斂等缺點,
2 人臉識別演算法缺陷
(學長在這里推薦大家可以優化這些點,然后作為課題的創新點)
光照是影響人臉識別的重要原因, 現有的數字影像處理技術都是基于影像的像素值進行計算的, 因此即使是同一個人但由于光照變化引起的像素值的差異使的最終計算結果差異很大, 這極大的影響了人臉識別的性能,姿態是左右人臉識別另一個關鍵點, 在實際問題中人臉資料的采集往往是一種隨意行為, 不能保證每次采集到是正臉, 上一節提到的各種方法往往只能適應一種姿態,對于姿態不同的影像識別問題經常是力不從心, 因此找到一種對姿態變化具有很強的魯棒性的方法也是非常重要的,
資料規模龐大也影響人臉識別性能, 在深度學習應用到人臉識別問題之前, 所提出的方法由于受到計算復雜度限制, 往往在小資料集(包含幾十人或幾百人)性能良好,但是在大規模資料上性能很差, 深度學習由于其具有較強的泛化能力, 因此在較大規模的資料集上表現比傳統方法改善了許多, 但是深度學習的泛化能力也是相對而言較強, 其受訓練集的影響很大, 目前世界上有超過 60 億人, 而且每個地區的人面部差異較大, 在獲取訓練資料集時無法包含所有人, 這會對最終的泛化能力有很大影響,比如訓練資料集中包括的全部是西方人(大部分是這種情況), 訓練得到的網路對于東方人的泛化能力就較低, 因此即使利用深度學習也無法區分世界上所有人,
計算復雜度高對人臉識別也有影響, 計算復雜度往往隨著人臉識別任務復雜度的提高和訓練資料的增加而急速增加, 利用深度學習進行人臉識別, 隨著神經網路規模加深, 引數量也逐漸增大, 也增加計算復雜度, 計算復雜度的增加不僅使訓練時間增加, 演算法難以收斂, 容易出現過擬合問題, 而且也增加了測驗階段所耗時間, 這不利用演算法的實際應用,
3 人臉識別流程
3.1 相關資料集
主要有以下幾種資料集,其中僅MultiPIE需要購買,其余的申請即可,

3.2 對齊
通過確定人臉中的標定點(landmark)的位置進行人臉對齊,(找3個點即可,一般找5個點:鼻子、眼睛、嘴角兩端)對齊后可以找到一個二維坐標平面,進行下一步仿射變換,

3.3 仿射變換
原理
- 二維坐標到二維坐標之間的線性變換
- 不共線的三對對應點決定了一個唯一的仿射變換


3.4 人臉目標檢測
使用神經網路(比如使用的DCNN)進行回歸對標定點進行檢測,

其中,輸入原始畫像后,進行4*4卷積后,在進行池化,卷積…最后使用兩個全連接得到最終結果,這里面采用了一個級聯思想實作CNN組合,級聯思想實作細節如下圖:

3.5 人臉特征提取
3.5.1 分類模型有哪些
- Deepface
- DeepID
- VGG
- ResNet
- FaceNet
3.5.2 度量學習模型——FaceNet為例
學長以常用的FaceNet為例,下圖是FaceNet的簡略示意圖,例如,輸入三張圖片:Anchor、與Anchor不同類的Negative、與Anchor同類的Positive,通過一系列學習后實作同類相近,異類相遠,
距離計算公式(前半部分為與同類positive之間的距離,后半部分計算與不同類negative的距離,)

最終實作效果如下圖所示,距離>1.1即可認為相互之間為不同人,即使一個人不同角度也可以被識別為同一人,

3.6 人臉識別(特征分類)
人臉識別中的人臉驗證問題即是驗證兩張圖片是否來自同一個人,主要有以下三種方法,歐氏距離和余弦距離方法是工業中常用的驗證方法,Joint Bayesian方法常用在學術研究中,首先假定兩張人臉圖片提取的特征向量為量為 xj→ 和 xk→ ,
3.6.1 歐氏距離
距離差越大,相似度越小,

3.6.2 余弦距離

3.6.3 Joint Bayesian 方法

其中,𝑆(?) 是差異 ? 的函式,𝑃(H1)為先驗概率,𝑃(Δ|H1) 為似然概率,𝑃($𝐻_1|?)是后驗概率,是人臉相似性的度量,
4 實作程序

資料集來源網路搜索,我選取了幾名大家認識的人物,有Biden、chenglong、mayun、Trump、yangmi、zhaoliying等,每個人物放入3-4張圖片,如下圖:

獲得此影像資料集,我們將:
- 為資料集中的每個人臉創建 128 維嵌入
- 使用這些嵌入來識別影像和視頻流中人物的面部
4.1 自己構建人臉資料集
或者你有自己的想法,構建一個自己的資料集,可以的話,記得開源給學長(手動狗頭)
4.1.1 拍照程式
想要識別自己,單有別人的資料集還是不行的,還需要自己人臉的照片才行,這就需要我們收集自己的照片,然后和上面的那個資料集一起來訓練模型,在拿著手機自拍的程序中我想到,問什么不寫一個程式用電腦的攝像頭自拍呢,隨便還能研究下怎么用opencv實作拍照的功能,經過一番實驗(其實還是費了好長時間),終于寫了一個拍照程式,
程式的功能就是打開電腦攝像頭,當P鍵按下(P是拍照的首字母?還是Photo的首字母?還是Picture的首字母?)的時候,保存當前幀的影像,簡單到沒朋友(竟然耗費了那么久!),
while (1)
{
char key = waitKey(100);
cap >> frame;
imshow("frame", frame);
string filename = format("D:\\pic\\pic%d.jpg", i);
switch (key)
{
case'p':
i++;
imwrite(filename, frame);
imshow("photo", frame);
waitKey(500);
destroyWindow("photo");
break;
default:
break;
}
}
然后我們就可以運行程式,不停地按下p鍵對自己一通狂拍了,
4.2 預處理
在得到自己的人臉照片之后,還需要對這些照片進行一些預處理才能拿去訓練模型,所謂預處理,其實就是檢測并分割出人臉,并改變人臉的大小與下載的資料集中圖片大小一致,
人臉檢測在之前的博客中已經做了介紹,這里就不再贅述,詳情參考:OpenCV人臉檢測(C++/Python),用ROI分割即可,
檢測出人臉之后改變大小使之與ORL人臉資料庫人臉大小一致,通過加斷點在Locals里面或者是ImageWatch可以看到ORL人臉資料庫人臉的大小是92 x 112,

這里只需要對檢測后得到的ROI做一次resize即可,
這兩步的代碼如下:
std::vector<Rect> faces;
Mat img_gray;
cvtColor(img, img_gray, COLOR_BGR2GRAY);
equalizeHist(img_gray, img_gray);
//-- Detect faces
face_cascade.detectMultiScale(img_gray, faces, 1.1, 3, CV_HAAR_DO_ROUGH_SEARCH, Size(50, 50));
for (size_t j = 0; j < faces.size(); j++)
{
Mat faceROI = img(faces[j]);
Mat MyFace;
if (faceROI.cols > 100)
{
resize(faceROI, MyFace, Size(92, 112));
string str = format("D:\\MyFaces\\MyFcae%d.jpg", i);
imwrite(str, MyFace);
imshow("ii", MyFace);
}
waitKey(10);
}
4.3 人臉特征提取
在識別影像和視頻中的人臉之前,我們首先需要量化訓練集中的人臉, 請記住,我們實際上并不是在這里訓練網路——網路已經被訓練為在大約 300 萬張影像的資料集上創建 128 維嵌入,
當然可以從頭開始訓練網路,甚至可以微調現有模型的權重,
但一般情況,使用預訓練網路然后使用它為我們資料集中的 29張人臉中的每一張構建 128 維嵌入更容易,
然后,在分類程序中,我們可以使用一個簡單的 k-NN 模型 + 投票來進行最終的人臉分類, 其他傳統的機器學習模型也可以在這里使用,
新建 encode_faces.py:
# import the necessary packages
from imutils import paths
import face_recognition
import argparse
import pickle
import cv2
import os
dataset_path='dataset'
encodings_path='encodings.pickle'
detection_method='cnn'
# 獲取資料集中輸入影像的路徑
print("[INFO] quantifying faces...")
imagePaths = list(paths.list_images(dataset_path))
# 初始化已知編碼和已知名稱的串列
knownEncodings = []
knownNames = []
# 遍歷影像路徑
for (i, imagePath) in enumerate(imagePaths):
# 從圖片路徑中提取人名
print("[INFO] processing image {}/{}".format(i + 1,
len(imagePaths)))
name = imagePath.split(os.path.sep)[-2]
# 加載輸入影像并從 BGR 轉換(OpenCV 排序)
# 到 dlib 排序(RGB)
image = cv2.imread(imagePath)
rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 檢測邊界框的 (x, y) 坐標
# 對應輸入影像中的每個人臉
boxes = face_recognition.face_locations(rgb, model=detection_method)
# 計算人臉的嵌入
encodings = face_recognition.face_encodings(rgb, boxes)
# 遍歷 encodings
for encoding in encodings:
# 將每個編碼 + 名稱添加到我們的已知名稱集中
# 編碼
knownEncodings.append(encoding)
knownNames.append(name)
代碼關鍵點解釋
- dataset_path:資料集的路徑,
- encodings_path :我們的人臉編碼被寫入這個引數指向的檔案路徑,
- detection_method :在我們對影像中的人臉進行編碼之前,我們首先需要檢測它們, 或者兩種人臉檢測方法包括 hog 或 cnn ,
現在我們已經定義了我們的引數,讓我們獲取資料集中檔案的路徑(以及執行兩個初始化):
輸入資料集目錄的路徑來構建其中包含的所有影像路徑的串列,
在回圈之前分別初始化兩個串列 knownEncodings 和 knownNames , 這兩個串列將包含資料集中每個人的面部編碼和相應的姓名, 這個回圈將回圈 19次,對應于我們在資料集中的 19張人臉影像,
然后,將面部的邊界框轉換為 128 個數字的串列,這稱為將面部編碼為向量,而 face_recognition.face_encodings 方法會處理它, 編碼和名稱附加到適當的串列(knownEncodings 和 knownNames),然后,將繼續對資料集中的所有 19張影像執行此操作,
# dump the facial encodings + names to disk
print("[INFO] serializing encodings...")
data = {"encodings": knownEncodings, "names": knownNames}
f = open(args["encodings"], "wb")
f.write(pickle.dumps(data))
f.close()
構造了一個帶有兩個鍵的字典—— “encodings” 和 “names” , 將名稱和編碼轉儲到磁盤以備將來呼叫,
[INFO] quantifying faces...
[INFO] processing image 1/19
[INFO] processing image 2/19
[INFO] processing image 3/19
[INFO] processing image 4/19
[INFO] processing image 5/19
[INFO] processing image 6/19
[INFO] processing image 7/19
[INFO] processing image 8/19
[INFO] processing image 9/19
[INFO] processing image 10/19
[INFO] processing image 11/19
[INFO] processing image 12/19
[INFO] processing image 13/19
[INFO] processing image 14/19
[INFO] processing image 15/19
[INFO] processing image 16/19
[INFO] processing image 17/19
[INFO] processing image 18/19
[INFO] processing image 19/19
[INFO] serializing encodings...
Process finished with exit code 0
正如輸出中看到的,我們現在有一個名為 encodings.pickle 的檔案——該檔案包含我們資料集中每個人臉的 128 維人臉嵌入,
5 識別效果
5.1 人臉檢測效果

5.2 人臉識別結果
靜態識別

動態識別

6 最后-畢設幫助
畢設幫助,開題指導,技術解答
🇶746876041
關注公眾號獲取更多畢設資料
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/404225.html
標籤:其他
