色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何用OpenCV、Python和深度學習實現面部識別?

新機器視覺 ? 來源:YXQ ? 2019-07-05 09:57 ? 次閱讀

Face ID 的興起帶動了一波面部識別技術熱潮。本文將介紹如何使用 OpenCV、Python深度學習在圖像和視頻中實現面部識別,以基于深度識別的面部嵌入,實時執行且達到高準確度。

以下內容由 CSDN 翻譯:

想知道怎樣用OpenCV、Python和深度學習進行面部識別嗎?

這篇文章首先將簡單介紹下基于深度學習的面部識別的工作原理,以及“深度度量學習”(deep metric learning)的概念。接下來我會幫你安裝好面部識別需要的庫。最后我們會發現,這個面部識別的實現能夠實時運行。

理解深度學習面部識別嵌入

那么,基于深度學習的面部識別是怎樣工作的呢?秘密就是一種叫做“深度度量學習”的技術。

如果你有深度學習的經驗,你應該知道,通常情況下訓練好的網絡會接受一個輸入圖像,并且給輸入的圖像生成一個分類或標簽

而在這里,網絡輸出的并不是單一的標簽(也不是圖像中的坐標或邊界盒),而是輸出一個表示特征向量的實數。

對于dlib面部識別網絡來說,輸出的特征向量為128維(即一個由128個實數組成的列表),用來判斷面部。網絡的訓練是通過三元組進行的:

圖1:利用深度度量學習進行面部識別需要“三元組訓練”。三元組包括三張不同的面部圖像,其中兩張屬于同一個人。神經網絡為每張面部圖像生成一個128維向量。對于同一個人的兩張面部圖像,我們調整神經網絡使得輸出向量的距離度量盡可能接近。圖片來源:Adam Geitgey的“Machine Learning is Fun”博客(https://medium.com/@ageitgey/machine-learning-is-fun-part-4-modern-face-recognition-with-deep-learning-c3cffc121d78)

這里我們需要給網絡提供三張圖片:

其中兩張圖片是同一個人的面部;第三張圖片是從數據集中取得的隨機面部圖片,并且保證與另外兩張圖片不是同一個人。以圖1為例,這里我們用了三張圖片,一張是Chad Smith,兩張是Will Ferrell。

網絡會測試這些面部圖片,并為每張圖片生成128維嵌入(embedding,即qualification)。

接下來,基本思路就是調整神經網絡的權重,使得兩張Will Ferrell的測量結果盡量接近,而Chad Smith的測量結果遠離。

我們的面部識別網絡的架構基于He等人在《Deep Residual Learning for Image Recognition》(https://arxiv.org/abs/1512.03385)中提出的ResNet-34,但層數較少,而且過濾器的數量減少了一半。

網絡本身由Davis King(https://www.pyimagesearch.com/2017/03/13/an-interview-with-davis-king-creator-of-the-dlib-toolkit/)在大約300萬張圖片上訓練。在Labeled Faces in the Wild(LFW)(http://vis-www.cs.umass.edu/lfw/)數據集上與其他方法相比,該網絡的準確度達到了99.38%。

Davis King(dlib的作者)和Adam Geitgey(https://adamgeitgey.com/, 我們即將用到的face_recognition模塊的作者)都有文章介紹了基于深度學習的面部識別的工作原理:

High Quality Face Recognition with Deep Metric Learning(Davis,http://blog.dlib.net/2017/02/high-quality-face-recognition-with-deep.html)

Modern Face Recognition with Deep Learning( Adam,https://medium.com/@ageitgey/machine-learning-is-fun-part-4-modern-face-recognition-with-deep-learning-c3cffc121d78)

強烈建議閱讀以上文章,以深入了解深度學習面部嵌入的工作原理。

安裝面部識別庫

為了用Python和OpenCV吸納面部識別,我們需要安裝一些庫:

dlib(http://dlib.net/);

face_recognition(https://github.com/ageitgey/face_recognition)。

由Davis King維護的dlib庫包含了“深度度量學習”的實現,用來在實際的識別過程中構建面部嵌入。

Adam Geitgey創建的face_recognition庫則封裝了dlib的面部識別功能,使之更易用。

我假設你的系統上已經裝好了OpenCV。如果沒有也不用擔心,可以看看我的OpenCV安裝指南一文(https://www.pyimagesearch.com/opencv-tutorials-resources-guides/),選擇適合你的系統的指南即可。

這里我們來安裝dlib和face_recognition庫。

注意:下面的安裝過程需要在Python虛擬環境中進行。我強烈推薦使用虛擬環境來隔離項目,這是使用Python的好習慣。如果你看了我的OpenCV安裝指南,并且安裝了virtualenv和virtualenvwrapper,那么只要在安裝dlib和face_recognition之前執行workon命令即可。

安裝沒有GPU支持的dlib

如果你沒有GPU,可以用pip安裝dlib(參考這篇指南:https://www.pyimagesearch.com/2018/01/22/install-dlib-easy-complete-guide/)。

$workon#optional$pipinstalldlib

或者從源代碼進行編譯:

$workon#optional$gitclonehttps://github.com/davisking/dlib.git$cddlib$mkdirbuild$cdbuild$cmake..-DUSE_AVX_INSTRUCTIONS=1$cmake--build.$cd..$pythonsetup.pyinstall--yesUSE_AVX_INSTRUCTIONS

安裝有GPU支持的dlib(可選)

如果你有兼容CUDA的GPU,那么可以安裝有GPU支持的dlib,這樣面部識別能更快、更精確。

我建議從源代碼安裝dlib,這樣可以更精細地控制安裝過程:

$workon#optional$gitclonehttps://github.com/davisking/dlib.git$cddlib$mkdirbuild$cdbuild$cmake..-DDLIB_USE_CUDA=1-DUSE_AVX_INSTRUCTIONS=1$cmake--build.$cd..$pythonsetup.pyinstall--yesUSE_AVX_INSTRUCTIONS--yesDLIB_USE_CUDA

安裝face_recognition包

face_recognition模塊只需簡單地使用pip命令即可安裝:

$workon#optional$pipinstallface_recognition

安裝imutlis

我們還需要imutils包提供一些遍歷的函數。在Python虛擬環境中使用pip即可:

$workon#optional$pipinstallimutils

面部識別數據集

圖2:利用Python和Bing圖像搜索API自動創建的面部識別數據集,圖中顯示的是電影侏羅紀公園的六個角色。

1993年的《侏羅紀公園》是我最喜歡的電影,為了紀念最新上映的《侏羅紀世界:失落王國》,我們將使用電影中的一些角色進行面部識別:

Alan Grant,古生物學家(22張圖像)

Clair Dearing,公園管理人(53張圖像)

Ellie Sattler,古生物學家(31張圖像)

Ian Malcolm,數學家(41張圖像)

John Hammond,商人,侏羅紀公園所有者(36張圖像)

Owen Grady,恐龍研究學者(35張圖像)

這個數據集只需要30分鐘就可以建好,參見我的文章《怎樣(快速)建立深度學習圖像數據集》(https://www.pyimagesearch.com/2018/04/09/how-to-quickly-build-a-deep-learning-image-dataset/)。

有了這個數據集,我們可以:

為數據集中的每張圖像建立128維嵌入;

利用這些嵌入,從圖像和視頻中識別每個角色的面部。

面部識別項目結構

項目結構可以參考下面的tree命令的輸出結果:

$tree--filelimit10--dirsfirst.├──dataset│├──alan_grant[22entries]│├──claire_dearing[53entries]│├──ellie_sattler[31entries]│├──ian_malcolm[41entries]│├──john_hammond[36entries]│└──owen_grady[35entries]├──examples│├──example_01.png│├──example_02.png│└──example_03.png├──output│└──lunch_scene_output.avi├──videos│└──lunch_scene.mp4├──search_bing_api.py├──encode_faces.py├──recognize_faces_image.py├──recognize_faces_video.py├──recognize_faces_video_file.py└──encodings.pickle10directories,11files

該項目有4個頂層目錄:

dataset/:包含六個角色的面部圖像,用角色名組織到各個子目錄中;

examples/:包含三個不屬于該數據集的測試圖像;

output/:存儲經過面部識別處理后的視頻,上面有我生成的一個視頻,來自于原版《侏羅紀公園》電影的午飯場景;

videos/:輸入視頻存放于該文件夾中,該文件夾也包含了尚未經過面部識別的“午飯場景”的視頻。

根目錄下還有6個文件:

search_bing_api.py:第一步就是建立數據集(我已經幫你做好了)。關于利用Bing API建立數據集的具體方法請參考我這篇文章:https://www.pyimagesearch.com/2018/04/09/how-to-quickly-build-a-deep-learning-image-dataset/;

encode_faces.py:該腳本用來進行面部編碼(128維向量);

recognize_faces_image.py:基于數據集生成的編碼,對單張圖片進行面部識別;

recognize_faces_video.py:對來自攝像頭的實時視頻流進行面部識別并輸出視頻文件;

recognize_faces_video_file.py:對硬盤上保存的視頻文件進行面部識別,并輸出處理后的視頻文件。本文不再討論該腳本,因為它的基本結構與上面識別視頻流的腳本相同;

encodings.pickle:該腳本將encode_faces.py生成的面部識別編碼序列化并保存到硬盤上。

用search_bing_api.py創建好圖像數據集之后,就可以運行encode_faces.py來創建嵌入了。

接下來我們將運行識別腳本來進行面部識別。

用OpenCV和深度學習對面部進行編碼

圖3:利用深度學習和Python進行面部識別。對每一個面部圖像,用face_recognition模塊的方法生成一個128維實數特征向量。

在識別圖像和視頻中的面部之前,我們首先需要在訓練集中識別面部。要注意的是,我們并不是在訓練網絡——該網絡已經在300萬圖像的訓練集上訓練過了。

當然我們可以從頭開始訓練網絡,或者微調已有模型的權重,但那就超出了這個項目的范圍。再說,你需要巨量的圖像才能從頭開始訓練網絡。

相反,使用預先訓練好的網絡來給訓練集中的218張面部圖像建立128維嵌入更容易些。

然后,在分類過程中,只需利用簡單的k-NN模型,加上投票,即可確定最終的面部分類,也可以使用其他經典機器學習模型。

現在打開本文“下載”鏈接中的encode_faces.py文件,看看是如何構建面部嵌入的:

1#importthenecessarypackages2fromimutilsimportpaths3importface_recognition4importargparse5importpickle6importcv27importos

首先需要導入必需的包。這個腳本需要事先安裝imutils、face_recognition和OpenCV。請翻到前面“安裝面部識別庫”一節確保你已經安裝了必須的庫。

首先用argparse處理運行時傳遞的命令行參數

1#constructtheargumentparserandparsethearguments2ap=argparse.ArgumentParser()3ap.add_argument("-i","--dataset",required=True,4help="pathtoinputdirectoryoffaces+images")5ap.add_argument("-e","--encodings",required=True,6help="pathtoserializeddboffacialencodings")7ap.add_argument("-d","--detection-method",type=str,default="cnn",8help="facedetectionmodeltouse:either`hog`or`cnn`")9args=vars(ap.parse_args())

如果你之前沒有用過PyImageSearch,你可以多讀讀我的博客文章,就明白上面這段代碼了。首先利用argparse分析命令行參數,在命令行上執行Python程序時,可以在終端中給腳本提供格外的信息。第2-9行不需要做任何改動,它們只是為了分析終端上的輸入。如果不熟悉這些代碼,可以讀讀我這篇文章:https://www.pyimagesearch.com/2018/03/12/python-argparse-command-line-arguments/。

下面逐一列出參數:

--dataset:數據集的路徑(利用search_bing_api.py創建的數據集);

--encodings:面部編碼將被寫到該參數所指的文件中;

--detection-method:首先需要檢測到圖像中的面部,才能對其進行編碼。兩種面部檢測方法為hog或cnn,因此該參數只接受這兩個值。

現在參數已經定義好了,我們可以獲得數據集文件的路徑了(同時進行兩個初始化):

1#grabthepathstotheinputimagesinourdataset2print("[INFO]quantifyingfaces...")3imagePaths=list(paths.list_images(args["dataset"]))45#initializethelistofknownencodingsandknownnames6knownEncodings=[]7knownNames=[]

行3用輸入數據集的路徑,建立了一個列表imagePaths。

我們還需要在循環開始之前初始化兩個列表,分別是knownEncodings和knownNames。這兩個列表分別包含面部編碼數據和數據集中相應人物的名字(行6和行7)。

現在可以依次循環侏羅紀公園中的每個角色了!

 1#loopovertheimagepaths 2for(i,imagePath)inenumerate(imagePaths): 3#extractthepersonnamefromtheimagepath 4print("[INFO]processingimage{}/{}".format(i+1, 5len(imagePaths))) 6name=imagePath.split(os.path.sep)[-2] 7 8#loadtheinputimageandconvertitfromBGR(OpenCVordering) 9#todlibordering(RGB)10image=cv2.imread(imagePath)11rgb=cv2.cvtColor(image,cv2.COLOR_BGR2RGB)

這段代碼會循環218次,處理數據集中的218張面部圖像。行2在所有圖像路徑中進行循環。

接下來,行6要從imagePath中提取人物的名字(因為子目錄名就是人物名)。

然后將imagePath傳遞給cv2.imread(行10),讀取圖像保存到image中。

OpenCV中的顏色通道排列順序為BGR,但dlib要求的順序為RGB。由于face_recognition模塊使用了dlib,因此在繼續下一步之前,行11轉換了顏色空間,并將轉換后的新圖像保存在rgb中。

接下來定位面部位置并計算編碼:

 1#detectthe(x,y)-coordinatesoftheboundingboxes 2#correspondingtoeachfaceintheinputimage 3boxes=face_recognition.face_locations(rgb, 4model=args["detection_method"]) 5 6#computethefacialembeddingfortheface 7encodings=face_recognition.face_encodings(rgb,boxes) 8 9#loopovertheencodings10forencodinginencodings:11#addeachencoding+nametooursetofknownnamesand12#encodings13knownEncodings.append(encoding)14knownNames.append(name)

這段代碼是最有意思的部分!

每次循環都會檢測一個面部圖像(或者一張圖像中有多個面部,我們假設這些面部都屬于同一個人,但如果你使用自己的圖像的話,這個假設有可能不成立,所以一定要注意)。

比如,假設rgb里的圖像是Ellie Sattler的臉。

行3和4查找面部位置,返回一個包含了許多方框的列表。我們給face_recognition.face_locations方法傳遞了兩個參數:

rgb:RGB圖像;

model:cnn或hog(該值包含在命令行參數字典中,賦給了detection_method鍵)。CNN方法比較準確,但速度較慢;HOG比較快,但不太準確。

然后,在行7,我們要將Ellie Sattler的面部的邊界盒boxes轉換成128個數字。這個步驟就是將面部編碼成向量,可以通過face_recognition.face_encodings方法實現。

接下來秩序將Ellie Sattler的encoding和name添加到恰當的列表中(knownEncodings或knownNames)。

然后對數據集中所有218張圖像進行這一步驟。

提取這些編碼encodings的目的就是要在另一個腳本中利用它們進行面部識別?,F在來看看怎么做:

1#dumpthefacialencodings+namestodisk2print("[INFO]serializingencodings...")3data={"encodings":knownEncodings,"names":knownNames}4f=open(args["encodings"],"wb")5f.write(pickle.dumps(data))6f.close()

行3構建了一個字典,它包含encodings和names兩個鍵。

行4-6將名字和編碼保存到硬盤中,供以后使用。

怎樣才能在終端上運行encode_faces.py腳本?

要創建面部嵌入,可以從終端執行以下命令:

 1$pythonencode_faces.py--datasetdataset--encodingsencodings.pickle 2[INFO]quantifyingfaces... 3[INFO]processingimage1/218 4[INFO]processingimage2/218 5[INFO]processingimage3/218 6... 7[INFO]processingimage216/218 8[INFO]processingimage217/218 9[INFO]processingimage218/21810[INFO]serializingencodings...11$ls-lhencodings*12-rw-r--r--@1adrianstaff234KMay2913:03encodings.pickle

從輸出中課件,它生成了個名為encodings.pickle的文件,該文件包含了數據集中每個面部圖像的128維面部嵌入。

在我的Titan X GPU上,處理整個數據集花費了一分鐘多一點,但如果只使用CPU,就要做好等待很久的心理準備。

在我的Macbook Pro上(沒有GPU),編碼218張圖像需要21分20秒。

如果你有GPU并且編譯dlib時選擇了支持GPU,那么速度應該會快得多。

識別圖像中的面部

圖4:John Hammond的面部識別,使用了Adam Geitgey的深度學習Python模塊face_recognition。

現在已經給數據集中的每張圖像建好了128維面部嵌入,我們可以用OpenCV、Python和深度學習進行面部識別了。

打開recognize_faces_image.py,插入以下代碼(或者從本文的”下載“部分下載代碼和相關的圖像):

 1#importthenecessarypackages 2importface_recognition 3importargparse 4importpickle 5importcv2 6 7#constructtheargumentparserandparsethearguments 8ap=argparse.ArgumentParser() 9ap.add_argument("-e","--encodings",required=True,10help="pathtoserializeddboffacialencodings")11ap.add_argument("-i","--image",required=True,12help="pathtoinputimage")13ap.add_argument("-d","--detection-method",type=str,default="cnn",14help="facedetectionmodeltouse:either`hog`or`cnn`")15args=vars(ap.parse_args())

這段代碼首先導入了必需的包(行2-5)。face_recognition模塊完成主要工作,OpenCV負責加載圖像、轉換圖像,并顯示處理之后的圖像。

行8-15負責分析三個命令行參數:

--encodings:包含面部編碼的pickle文件的路徑;

--image:需要進行面部識別的圖像;

--detection-method:這個選項應該很熟悉了??梢愿鶕到y的能力,選擇hog或cnn之一。追求速度的話就選擇hog,追求準確度就選擇cnn。

注意:在樹莓派上必須選擇hog,因為內存容量不足以運行CNN方法。

接下來要加載計算好的編碼和面部名稱,然后為輸入圖像構建128維面部編碼:

 1#loadtheknownfacesandembeddings 2print("[INFO]loadingencodings...") 3data=pickle.loads(open(args["encodings"],"rb").read()) 4 5#loadtheinputimageandconvertitfromBGRtoRGB 6image=cv2.imread(args["image"]) 7rgb=cv2.cvtColor(image,cv2.COLOR_BGR2RGB) 8 9#detectthe(x,y)-coordinatesoftheboundingboxescorresponding10#toeachfaceintheinputimage,thencomputethefacialembeddings11#foreachface12print("[INFO]recognizingfaces...")13boxes=face_recognition.face_locations(rgb,14model=args["detection_method"])15encodings=face_recognition.face_encodings(rgb,boxes)1617#initializethelistofnamesforeachfacedetected18names=[]

行3從硬盤加載pickle過的編碼和名字數據。稍后在實際的面部識別步驟中會用到這些數據。

然后,行6和行7加載輸入圖像image,并轉換其顏色通道順序(同encode_faces.py腳本一樣),保存到rgb中。

接下來,行13-15繼續檢測輸入圖像中的所有面部,并計算它們的128維encodings(這些代碼也應該很熟悉了)。

現在應該初始化一個列表names,用來保存每個檢測的面部。該列表將在下一步填充。

現在遍歷面部編碼encodings列表:

1#loopoverthefacialembeddings2forencodinginencodings:3#attempttomatcheachfaceintheinputimagetoourknown4#encodings5matches=face_recognition.compare_faces(data["encodings"],6encoding)7name="Unknown"

行2開始遍歷根據輸入圖像計算出的面部編碼。

接下來見證面部識別的奇跡吧!

在行5和行6,我們嘗試利用face_recognition.compare_faces將輸入圖像中的每個面部(encoding)對應到已知的編碼數據集(保存在data["encodings"]中)上。

該函數會返回一個True/False值的列表,每個值對應于數據集中的一張圖像。對于我們的侏羅紀公園的例子,數據集中有218張圖像,因此返回的列表將包含218個布爾值。

compare_faces函數內部會計算待判別圖像的嵌入和數據集中所有面部的嵌入之間的歐幾里得距離。

如果距離位于容許范圍內(容許范圍越小,面部識別系統就越嚴格),則返回True,表明面部吻合。否則,如果距離大于容許范圍,則返回False表示面部不吻合。

本質上我們用了個更”炫酷“的k-NN模型進行分類。具體的實現細節可以參考compare_faces的實現。

最終,name變量會的值就是人的名字。如果沒有任何”投票“,則保持"Unknown"不變(行7)。

根據matches列表,可以計算每個名字的”投票“數目(與每個名字關聯的True值的數目),計票之后選擇最適合的人的名字:

 1#checktoseeifwehavefoundamatch 2ifTrueinmatches: 3#findtheindexesofallmatchedfacestheninitializea 4#dictionarytocountthetotalnumberoftimeseachface 5#wasmatched 6matchedIdxs=[ifor(i,b)inenumerate(matches)ifb] 7counts={} 8 9#loopoverthematchedindexesandmaintainacountfor10#eachrecognizedfaceface11foriinmatchedIdxs:12name=data["names"][i]13counts[name]=counts.get(name,0)+11415#determinetherecognizedfacewiththelargestnumberof16#votes(note:intheeventofanunlikelytiePythonwill17#selectfirstentryinthedictionary)18name=max(counts,key=counts.get)1920#updatethelistofnames21names.append(name)

如果matches中包含任何True的投票(行2),則需要確定True值在matches中的索引位置。這一步在行6中通過建立一個簡單的matchedIdxs列表實現。對于example_01.png來說,它大概是這個樣子:

1(Pdb)matchedIdxs2[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,71,72,73,74,75]

然后初始化一個名為counts的字典,其鍵為角色的名字,值是投票的數量。

接下來遍歷matchedIdxs,統計每個相關的名字,并在counts增加相應的計數值。counts字典可能是這個樣子(Ian Malcolm高票的情況):

1(Pdb)counts2{'ian_malcolm':40}

回憶一下我們的數據集中只有41張圖片,因此40分并且沒有任何其他投票可以認為非常高了。

取出counts中投票最高的名字,本例中為'ian_malcolm'。

循環的第二次迭代(由于圖像中有兩個人臉)會取出下面的counts:

1(Pdb)counts2{'alan_grant':5}

盡管這個投票分值較低,但由于這是字典中唯一的人名,所以很可能我們找到了Alan Grant。

注意:這里使用了Python調試器PDB來檢查counts字典的值。PDB的用法超出了本文的范圍,你可以在Python的文檔頁面(https://docs.python.org/3/library/pdb.html)找到其用法。

如下面的圖5所示,我們正確識別了Ian Malcolm和Alan Grant,所以這一段代碼工作得還不錯。

我們來繼續循環每個人的邊界盒和名字,然后將名字畫在輸出圖像上以供展示之用:

 1#loopovertherecognizedfaces 2for((top,right,bottom,left),name)inzip(boxes,names): 3#drawthepredictedfacenameontheimage 4cv2.rectangle(image,(left,top),(right,bottom),(0,255,0),2) 5y=top-15iftop-15>15elsetop+15 6cv2.putText(image,name,(left,y),cv2.FONT_HERSHEY_SIMPLEX, 70.75,(0,255,0),2) 8 9#showtheoutputimage10cv2.imshow("Image",image)11cv2.waitKey(0)

行2開始循環檢測到的面部邊界盒boxes和預測的names。我們調用了zip(boxes, names)以創建一個容易進行循環的對象,每次迭代將得到一個二元組,從中可以提取邊界盒坐標和名字。

行4利用邊界盒坐標畫一個綠色方框。

我們還利用坐標計算了人名文本的顯示位置(行5),并將人名的文本畫在圖像上(行6和行7)。如果邊界盒位于圖像頂端,則將文本移到邊界盒下方(行5),否則文本就被截掉了。

然后顯示圖像,直到按下任意鍵為止(行10和11)。

怎樣運行面部識別的Python腳本?

在終端中,首先用workon命令保證位于正確的Python虛擬環境中(如果你用了虛擬環境的話)。

然后運行該腳本,同時至少提供兩個命令行參數。如果選擇HoG方式,別忘了傳遞--detection-method hog(否則默認會使用深度學習檢測方式)。

趕快試試吧!

打開終端并執行腳本,用OpenCV和Python進行面部識別:

1$pythonrecognize_faces_image.py--encodingsencodings.pickle2--imageexamples/example_01.png3[INFO]loadingencodings...4[INFO]recognizingfaces...

圖5:Python + OpenCV + 深度學習方法識別出了Alan Grant和Ian Malcom的面部。

另一個面部識別的例子:

1$pythonrecognize_faces_image.py--encodingsencodings.pickle2--imageexamples/example_02.png3[INFO]loadingencodings...4[INFO]recognizingfaces...

圖6:用OpenCV和Python進行面部識別。

在視頻中進行面部識別

圖7:用Python、OpenCV和深度學習在視頻中進行面部識別。

我們已經完成了圖像中的面部識別,現在來試試在視頻中進行(實時)面部識別。

關于性能的重要提示:CNN面部識別器只能在有GPU的情況下實時運行(CPU也可以運行,但視頻會非常卡,實際的幀速率不到0.5FPS)。如果你只有CPU,應當考慮使用HoG方式(或者甚至采用OpenCV的Haar層疊方式,以后會撰文說明),以獲得較好的速度。

下面的腳本從前面的recognize_faces_image.py腳本中借用了許多代碼。因此我將略過之前介紹過的部分,只說明下視頻部分,以便于理解。

下載好代碼之后,打開recognize_faces_video.py:

 1#importthenecessarypackages 2fromimutils.videoimportVideoStream 3importface_recognition 4importargparse 5importimutils 6importpickle 7importtime 8importcv2 910#constructtheargumentparserandparsethearguments11ap=argparse.ArgumentParser()12ap.add_argument("-e","--encodings",required=True,13help="pathtoserializeddboffacialencodings")14ap.add_argument("-o","--output",type=str,15help="pathtooutputvideo")16ap.add_argument("-y","--display",type=int,default=1,17help="whetherornottodisplayoutputframetoscreen")18ap.add_argument("-d","--detection-method",type=str,default="cnn",19help="facedetectionmodeltouse:either`hog`or`cnn`")20args=vars(ap.parse_args())

行2-8導入包,然后行11-20解析命令行參數。

這里有四個命令行參數,其中兩個是介紹過的(--encodings和--detection-method)。另外兩個參數是:

--output:視頻輸出路徑;

--display:指示是否將視頻幀輸出到屏幕的標志。1表示顯示到屏幕,0表示不顯示。

然后加載編碼并啟動VideoStream:

 1#loadtheknownfacesandembeddings 2print("[INFO]loadingencodings...") 3data=pickle.loads(open(args["encodings"],"rb").read()) 4 5#initializethevideostreamandpointertooutputvideofile,then 6#allowthecamerasensortowarmup 7print("[INFO]startingvideostream...") 8vs=VideoStream(src=0).start() 9writer=None10time.sleep(2.0)

我們利用imutils中的VideoStream類來訪問攝像頭。行8啟動視頻流。如果系統中有多個攝像頭(如內置攝像頭和外置USB攝像頭),可以將src=0改成src=1等。

稍后會將處理過的視頻寫到硬盤中,所以這里將writer初始化成None(行9)。sleep兩秒讓攝像頭預熱。

接下來啟動一個while循環,開始抓取并處理視頻幀:

 1#loopoverframesfromthevideofilestream 2whileTrue: 3#grabtheframefromthethreadedvideostream 4frame=vs.read() 5 6#converttheinputframefromBGRtoRGBthenresizeittohave 7#awidthof750px(tospeedupprocessing) 8rgb=cv2.cvtColor(frame,cv2.COLOR_BGR2RGB) 9rgb=imutils.resize(frame,width=750)10r=frame.shape[1]/float(rgb.shape[1])1112#detectthe(x,y)-coordinatesoftheboundingboxes13#correspondingtoeachfaceintheinputframe,thencompute14#thefacialembeddingsforeachface15boxes=face_recognition.face_locations(rgb,16model=args["detection_method"])17encodings=face_recognition.face_encodings(rgb,boxes)18names=[]

循環從行2開始,第一步就是從視頻流中抓取一個frame(行4)。

上述代碼中剩下的行8-18基本上與前一個腳本相同,只不過這里處理的是視頻幀,而不是靜態圖像?;旧暇褪亲x取frame,預處理,檢測到面部邊界盒boxes,然后給每個邊界盒計算encodings。

接下來遍歷每個找到的面部的encodings:

 1#loopoverthefacialembeddings 2forencodinginencodings: 3#attempttomatcheachfaceintheinputimagetoourknown 4#encodings 5matches=face_recognition.compare_faces(data["encodings"], 6encoding) 7name="Unknown" 8 9#checktoseeifwehavefoundamatch10ifTrueinmatches:11#findtheindexesofallmatchedfacestheninitializea12#dictionarytocountthetotalnumberoftimeseachface13#wasmatched14matchedIdxs=[ifor(i,b)inenumerate(matches)ifb]15counts={}1617#loopoverthematchedindexesandmaintainacountfor18#eachrecognizedfaceface19foriinmatchedIdxs:20name=data["names"][i]21counts[name]=counts.get(name,0)+12223#determinetherecognizedfacewiththelargestnumber24#ofvotes(note:intheeventofanunlikelytiePython25#willselectfirstentryinthedictionary)26name=max(counts,key=counts.get)2728#updatethelistofnames29names.append(name)

在這段代碼中依次循環每個encodings,并嘗試匹配到已知的面部數據上。如果找到匹配,則計算數據集中每個名字獲得的票數。然后取出得票最高的名字,就是該面部對應的名字。這些代碼與前面的代碼完全相同。

下一段代碼循環找到的面部并在周圍畫出邊界盒,并顯示人的名字:

 1#loopovertherecognizedfaces 2for((top,right,bottom,left),name)inzip(boxes,names): 3#rescalethefacecoordinates 4top=int(top*r) 5right=int(right*r) 6bottom=int(bottom*r) 7left=int(left*r) 8 9#drawthepredictedfacenameontheimage10cv2.rectangle(frame,(left,top),(right,bottom),11(0,255,0),2)12y=top-15iftop-15>15elsetop+1513cv2.putText(frame,name,(left,y),cv2.FONT_HERSHEY_SIMPLEX,140.75,(0,255,0),2)

這些代碼也完全相同,所以我們只關注與食品有關的代碼。

我們還可以將視頻幀寫到硬盤中,因此來看看是怎樣使用OpenCV將視頻寫到硬盤中的(https://www.pyimagesearch.com/2016/02/22/writing-to-video-with-opencv/):

 1#ifthevideowriterisNone*AND*wearesupposedtowrite 2#theoutputvideotodiskinitializethewriter 3ifwriterisNoneandargs["output"]isnotNone: 4fourcc=cv2.VideoWriter_fourcc(*"MJPG") 5writer=cv2.VideoWriter(args["output"],fourcc,20, 6(frame.shape[1],frame.shape[0]),True) 7 8#ifthewriterisnotNone,writetheframewithrecognized 9#facestodisk10ifwriterisnotNone:11writer.write(frame)

如果命令行參數提供了輸出文件路徑(可選),而我們還沒有初始化視頻的writer(行3),就要先初始化之。

行4初始化了VideoWriter_fourcc。FourCC是一種四字符編碼,在這里就是MJPG 四字符編碼。

接下來將對象、輸出路徑、每秒幀數的目標值和幀尺寸傳遞給VideoWriter(行5和6)。

最后,如果writer存在,就繼續將幀寫到磁盤中。

下面是是否將面部識別視頻幀輸出到屏幕的處理:

1#checktoseeifwearesupposedtodisplaytheoutputframeto2#thescreen3ifargs["display"]>0:4cv2.imshow("Frame",frame)5key=cv2.waitKey(1)&0xFF67#ifthe`q`keywaspressed,breakfromtheloop8ifkey==ord("q"):9break

如果設置了display命令行參數,就顯示視頻幀(行4)并檢查退出鍵("q")是否被按下(行5-8),如果被按下,則break掉循環(行9)。

最后是一些清理工作:

1#doabitofcleanup2cv2.destroyAllWindows()3vs.stop()45#checktoseeifthevideowriterpointneedstobereleased6ifwriterisnotNone:7writer.release()

行2-7清理并釋放屏幕、視頻流和視頻writer。

準備好運行真正的腳本了嗎?

為了演示OpenCV和Python的實時面部識別,打開終端然后執行下面的命令:

1$pythonrecognize_faces_video.py--encodingsencodings.pickle2--outputoutput/webcam_face_recognition_output.avi--display13[INFO]loadingencodings...4[INFO]startingvideostream...

下面是我錄制的演示視頻,用來演示面部識別系統:

視頻文件中的面部識別

之前在“面部識別項目結構”一節中說過,下載的代碼中還有個名為recognize_faces_video_file.py的腳本。

這個腳本實際上和剛才識別攝像頭的腳本相同,只不過它接收視頻文件作為輸入,然后生成輸出視頻文件。

我對原版侏羅紀公園電影中經典的“午飯場景”做了面部識別,在該場景中,演員們圍在桌子旁邊討論他們對于公園的想法:

1$pythonrecognize_faces_video_file.py--encodingsencodings.pickle2--inputvideos/lunch_scene.mp4--outputoutput/lunch_scene_output.avi3--display0

下面是結果:

注意:別忘了我們的模型是根據原版電影中的四個角色進行訓練的:Alan Grant、Ellie Sattler、Ian Malcolm和John Hammond。模型并沒有針對Donald Gennaro(律師)進行訓練,所以他的面部被標記為“Unknown”。這個行為是特意的(不是意外),以演示我們的視頻識別系統在識別訓練過的面部的同時,會把不認識的面部標記為“Unknown”。

下面的視頻中我從《侏羅紀公園》和《侏羅紀世界》的預告片中截取的剪輯:

可見,面部識別和OpenCV代碼的效果很不錯!

面部識別代碼能運行在樹莓派上嗎?

從某種意義上,可以。不過有一些限制:

樹莓派內存太小,沒辦法運行更準確的基于CNN的面部檢測器;

因此只能用HOG方式;

即使如此,HOG方式在樹莓派上也太慢,沒辦法用于實時面部檢測;

所以只能用OpenCV的Haar層疊方式。

即使這樣能運行起來,實際的速率也只有1~2FPS,而且就算是這種速率也需要許多技巧。

總結

在這篇指南中,我們學習了如何利用OpenCV、Python和深度學習來進行面部識別。此外,我們還利用了Davis King的dlib庫和Adam Geitgey的face_recognition模塊,后者對dlib的深度度量學習進行了封裝,使得面部識別更容易完成。

我們發現,我們的面部識別實現同時具有以下兩個特點:準確,并且能在GPU上實時運行。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • python
    +關注

    關注

    56

    文章

    4792

    瀏覽量

    84628
  • 深度學習
    +關注

    關注

    73

    文章

    5500

    瀏覽量

    121113

原文標題:如何用OpenCV、Python和深度學習實現面部識別?

文章出處:【微信號:vision263com,微信公眾號:新機器視覺】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    基于機器學習opencv和平臺Jupyter Notebook的車牌識別案例

    python+opencv實現車牌識別
    發表于 02-28 11:08

    深度學習入門之基于python的理論與實現

    深度學習入門-基于python的理論與實現(2)
    發表于 06-19 11:22

    LabVIEW+Python+openCV

    的,動態鏈接庫也需要配置,還需要知道各個參數含義和類型,這里提供另外一種方法,那就是PythonopenCV工具包,絕對開源和免費,LabVIEW可以利用Python節點調用Python
    發表于 12-07 20:59

    如何使用OpenCVPython深度學習在圖像和視頻中實現面部識別?

    Face ID 的興起帶動了一波面部識別技術熱潮。本文將介紹如何使用 OpenCV、Python深度
    的頭像 發表于 07-17 16:20 ?8048次閱讀

    Opencv人臉識別的制作

    OpenCV(開源計算機視覺庫)是一個非常有用的庫-它提供了許多有用的功能,例如文本識別面部識別,對象檢測,深度圖的創建和機器
    的頭像 發表于 10-13 17:04 ?3467次閱讀
    <b class='flag-5'>Opencv</b>人臉<b class='flag-5'>識別</b>的制作

    深度學習入門:基于Python的理論與實現電子書

    深度學習入門:基于Python的理論與實現電子書
    發表于 03-10 09:42 ?32次下載
    <b class='flag-5'>深度</b><b class='flag-5'>學習</b>入門:基于<b class='flag-5'>Python</b>的理論與<b class='flag-5'>實現</b>電子書

    如何使用Python-OpenCV實現餐盤水果識別與計價的應用

    導讀本文主要介紹使用Python-OpenCV實現餐盤水果識別與計價的應用。 測試圖像與說明 使用圖像,拍攝環境有待改善(存在光照不均和拍攝角度的影響): 餐盤/菜品識別一般方法: (
    的頭像 發表于 07-06 11:02 ?2700次閱讀

    如何使用Python OpenCV進行面部標志檢測

    今天我們將使用相同的 OpenCV 和 Raspberry Pi 進行人臉標志檢測。來自 dlib 庫的預訓練面部標志檢測器模塊將用于檢測面部關鍵面部結構的位置,
    發表于 08-12 16:32 ?1465次閱讀
    如何使用<b class='flag-5'>Python</b> <b class='flag-5'>OpenCV</b>進行<b class='flag-5'>面部</b>標志檢測

    Linux Debian與Python、Flask和OpenCV識別面部

    電子發燒友網站提供《Linux Debian與Python、Flask和OpenCV識別面部.zip》資料免費下載
    發表于 08-24 10:16 ?2次下載
    Linux Debian與<b class='flag-5'>Python</b>、Flask和<b class='flag-5'>OpenCV</b><b class='flag-5'>識別</b><b class='flag-5'>面部</b>

    使用Xbox Kinect和OpenCV進行面部識別

    電子發燒友網站提供《使用Xbox Kinect和OpenCV進行面部識別.zip》資料免費下載
    發表于 07-04 11:25 ?0次下載
    使用Xbox Kinect和<b class='flag-5'>OpenCV</b>進行<b class='flag-5'>面部</b><b class='flag-5'>識別</b>

    Python實現OpenCV的安裝與使用

      本文實例講述了 Python 實現 OpenCV 的安裝與使用。分享給大家供 大家參考,具體如下:  由于下一步要開始研究下深度學習,而
    發表于 07-20 11:46 ?7次下載

    面部表情識別的技術實現

    面部表情識別是一項復雜的技術,需要綜合運用計算機視覺、機器學習、深度學習等多種技術。本文將介紹面部
    的頭像 發表于 08-02 18:10 ?1128次閱讀

    面部表情識別技術的最新研究進展

    面部表情識別技術是人工智能領域的研究熱點之一,對于揭示情感狀態和心理狀況具有重要意義。本文將介紹面部表情識別技術的最新研究進展,包括深度
    的頭像 發表于 08-21 17:58 ?1122次閱讀

    基于Python深度學習人臉識別方法

    基于Python深度學習人臉識別方法是一個涉及多個技術領域的復雜話題,包括計算機視覺、深度學習
    的頭像 發表于 07-14 11:52 ?1251次閱讀

    opencv-pythonopencv一樣嗎

    不一樣。OpenCV(Open Source Computer Vision Library)是一個開源的計算機視覺和機器學習軟件庫,它提供了大量的圖像和視頻處理功能。OpenCV-Python
    的頭像 發表于 07-16 10:38 ?1161次閱讀
    主站蜘蛛池模板: 亚洲午夜精品久久久久久抢| 小xav导航| 无码AV精品一区二区三区| 亚洲精品无码不卡在线播HE| 一个人在线观看免费高清视频| 91福利在线观看| 国产成人午夜精品免费视频| 久久精品99国产精品日本| 人人碰79免费视频| 亚洲日本天堂在线| 达达兔午夜一级毛片| 久久久免费热线精品频| 日本伦理电影聚| 在线色av| 国产精品玖玖玖影院| 欧美成人精品高清在线观看| 性美国人xxxxx18| 啊…嗯啊好深男男小黄文| 精品无码人妻一区二区免费AV| 日日夜夜狠狠干| 2019天天射干网站| 精品极品三大极久久久久| 色欲AV精品人妻一区二区三区 | 国产在线精品一区二区网站免费 | 91麻豆久久| 久久机热免费视频| 亚洲 欧美 国产 综合不卡| 超碰97av 在线人人操| zooskoo1videos人与狗| 国产女高清在线看免费观看| 青娱乐视觉盛宴国产视频| 在线视频网站www色| 精品视频免费在线| 亚洲成片在线看| 国产国拍亚洲精品av麻豆| 日本动漫henta videos| avove主播| 欧美高清videos 360p| 99re这里只有精品国产| 久久人人爽人人片AV人成| 亚洲另类国产综合在线|