本文介紹了構建自定義人臉識別資料集的三種方法:使用 OpenCV 和 webcam 工具收集人臉影象資料;以程式設計的方式下載人臉影象;手動收集人臉影象。
在接下來的幾篇博文中,作者將帶領大家訓練一個「計算機視覺+深度學習」的模型來執行人臉識別任務。但是,要想訓練出能夠識別影象或視訊流中人臉的模型,我們首先得收集人臉影象的資料集。
如果你使用的是「Labeled Faces in the Wild」(LFW)這樣預先準備好的資料集,那麼你可以不用進行這項困難的工作了。你可以使用我們下一篇博文中的方法建立自己的人臉識別應用。
然而,對於大多數人來說,我們希望識別出的人臉往往不包含在任何現有資料集中,例如:我們自己的、朋友的、家人或者同事的人臉影象。
為了完成這個任務,我們需要收集我們想要識別的人臉樣本,並且以某種方式量化它們。
這個過程通常被稱為「人臉識別註冊」(facial recognition enrollment)。我們稱之為「註冊」是因為在這個過程中,我們會將使用者註冊、登記為我們的資料集和應用中的一個真人樣本。
本文將介紹註冊過程的第一步:建立自定義人臉識別資料集。
如何建立自定義人臉識別資料集
本教程中,我們將介紹 3 種建立自定義人臉識別資料集的方法。第一種方法使用 OpenCV 和 webcam 工具完成兩個任務:(1)在視訊中檢測出人臉;(2)將人臉影象或視訊幀的樣本儲存到磁碟上。
第二種方法將討論如何以程式設計的方式下載人臉影象。
最後,我們將討論如何手動收集人臉影象,以及這種方法何時是適用的。
讓我們開始構建人臉識別資料集吧!
方法 1:通過 OpenCV 和 webcam 進行人臉註冊
圖 1:通過使用 OpenCV 和 webcam,我們可以檢測出視訊流中的人臉,並且將樣本儲存到磁碟上。這個過程可用於建立一個本地人臉識別資料集。
這種方法適用於以下情況:
1. 你要建立一個」能現場使用的」人臉識別系統;
2. 你需要擁有接觸特定人的物理途徑,以收集他們的人臉影象資料。
這樣的系統尤其適用於公司、學校或者其他人們每天親自出現在現場的組織。
為了收集這些人的人臉影象樣本,我們可能需要將他們置於一個特殊的房間中,房間中事先安裝好了視訊攝影機,用於:(1)檢測視訊流中人臉的 (x, y) 座標;(2)將包含使用者人臉的視訊幀寫入磁碟。我們可能甚至需要好幾天或者幾周的時間執行上述操作,以收集下列幾種情況下的人臉樣本:
不同的光照條件
一天中不同的時間
不同的情緒和情感狀態
通過收集不同情況下的人臉樣本,我們可以建立一個更加多樣化、更具代表性的特定使用者人臉影象資料集。
接下來,我們使用一個簡單的 Python 指令碼構建自定義人臉識別資料集。這個 Python 指令碼可以完成以下任務:
1. 連線到我們的 webcam;
2. 檢測人臉;
3. 將包含人臉的視訊幀寫入磁碟。
想要獲取本文中使用的程式碼,請滾動到本文的「Downloads」部分。
準備好之後,請開啟 build_face_dataset.py 檔案,然後我們來一步一步解讀這份程式碼:
在 2-7 行中,我們匯入了所需程式包。尤其是我們所需要的 Opencv 和 imutils 包。安裝 Opencv 的方法請參考我提供的這篇安裝指南(https://www.pyimagesearch.com/opencv-tutorials-resources-guides/)。而 imutils 包則可以很容易地通過 pip 工具進行安裝或升級:
$ pip install --upgrade imutils
如果你使用的是 Python 虛擬環境,請不要忘記使用 workon 命令!
環境安裝好之後,我們接下來將討論兩個需要用到的命令列引數:
命令列引數會在執行時被一個名為 argparse 的程式包(這個程式包會在安裝 Python 環境時被自動安裝)解析。如果你對於 argparse 和命令列引數不太熟悉,我強烈推薦你迅速瀏覽這篇博文(https://www.pyimagesearch.com/2018/03/12/python-argparse-command-line-arguments/)。
我們有兩個需要用到的命令列引數:
--cascade:哈爾級聯(Haar cascade)檔案在磁碟上的路徑。
--output:輸出資料夾的路徑。人臉影象會被儲存在這個資料夾中,因此我推薦你用人臉主人的名字來命名這個資料夾。例如,如果你收集的是「John Smith」的人臉影象,你可以將所有的圖片存放在 dataset/john_smith 資料夾中。
下面,我們將載入人臉的哈爾級聯檔案並且初始化視訊流:
在第 18 行中,我們載入了 OpenCV 的哈爾級聯 detector。這個 detector 會在接下來的逐幀迴圈中完成繁重的任務。
我們在第 24 行初始化並開始我們的視訊流。
注意:如果你使用的是樹莓派,請註釋掉第 24 行,並且取消第 25 行的註釋。
為了讓攝像頭預熱,我們簡單地將程式暫停 2 秒(第 26 行)。
我們還初始化了一個計數器 total,用於表示在磁碟上儲存的人臉影象數量(第 27 行)。
現在讓我們在視訊流上進行逐幀迴圈:
在第 30 行中,我們開始迴圈(按下「q」鍵則退出迴圈)。
從這一行起,我們獲取了一個視訊幀 frame,建立了該幀的一個副本,並且改變了影象的尺寸(第 34-36 行)。
現在,是時候執行人臉檢測了!
我們可以使用 detectMultiScale 方法檢測視訊幀 frame 中的人臉。該函式需要用到下列引數:
image:一個灰度圖;
scaleFactor:指定在每個尺度上,影象縮小多少;
minNeighbor:為了保證檢測的有效性,該引數指定每一個候選矩形邊界框需要有多少相鄰的檢測點;
minSize:可能的最小圖片尺寸。
不幸的是,有時我們需要對這種方法進行調優,以消除誤判或者檢測出一張完整的人臉,但是對於「近距離」拍攝的人臉影象的檢測來說,這些引數是一個很好的起點。
話雖如此,你是否也在尋找一種更加先進、更加可靠的方法呢?在之前的博文中(https://www.pyimagesearch.com/2018/02/26/face-detection-with-opencv-and-deep-learning/),我用 OpenCV 和深度學習實現了人臉檢測。你可以通過文章中使用了預訓練模型的深度學習方法很容易地更新本文中的指令碼。該方法的好處是,不用調參並且訓練十分快。
這種人臉識別方法的結果是一個 rects(矩形邊界框)列表。在第 44、45 行中,我們在 rects 上進行迴圈,並且在幀上畫出矩形邊框,以方便展示。
最後一步,我們將在迴圈中進行兩個工作:(1)在螢幕上展示視訊幀;(2)處理按鍵響應。具體程式碼如下:
在第 48 行中,我們在螢幕上展示了視訊幀,接下來在第 49 行中獲取了鍵入值。
根據按下的是「k」還是「q」,我們會:
如果按下「k」鍵,我們將保留視訊幀並將它儲存到磁碟上(第 53-56 行),並且增加表示獲取到的總幀數的計數器 total(第 58 行)。我們需要在想保留的每一幀處按下「k」鍵。我建議保留不同角度、不同的幀區域、戴/不戴眼鏡等不同情況下拍攝的人臉影象。
如果按下「q」鍵,則退出迴圈,準備退出指令碼(quit)。
如果沒有按下任何鍵,我們就回到迴圈的開頭,從視訊流中獲取一幀。
最終我們將在終端上列印出最終儲存的影象數量,並進行清理:
現在讓我們執行指令碼,收集人臉影象吧!
請確保你已經從本文的「Downloads」部分下載了程式碼和哈爾級聯。
在你的終端裝置中執行下列命令:
$ python build_face_dataset.py --cascade haarcascade_frontalface_default.xml \
--output dataset/adrian
[INFO] starting video stream...
[INFO] 6 face images stored
[INFO] cleaning up...
在執行完指令碼之後,我們發現有 6 張影象被儲存到了 dataset 資料夾的 adrian 子資料夾中:
$ ls dataset/adrian
00000.png 00002.png 00004.png
00001.png 00003.png 00005.png
我建議將人臉影象樣本存在以影象所屬人的名字命名的子資料夾中。
通過這種方式可以強化你的自定義人臉識別資料集的組織結構。
方法 2:通過程式設計下載人臉影象
圖 2:另一種構建人臉識別資料集的方法(如果此人是公眾人物,或者在網路上出現過),是通過一個指令碼在谷歌上進行影象搜尋,或者使用一個利用了 Bing 影象搜尋 API 的 Python 指令碼。
如果你不能在現場拍攝一個人的影象,或者他們是在網路上存在感很強的公眾人物(在某種程度上),你可以通過各種平臺上的 API 以程式設計的方式下載他們的人臉影象樣本。選擇哪種 API 很大程度上取決於你想要收集的是誰的人臉影象。
例如,如果一個人一直在 Twitter 或 Instagram 上發帖,你可能想要用其中一種(或者其他的)社交網路 API 獲取人臉影象。
另一種選擇是,使用像谷歌或 Bing 這樣的搜尋引擎:
使用這篇文章中的方法(https://www.pyimagesearch.com/2017/12/04/how-to-create-a-deep-learning-dataset-using-google-images/),你可以使用谷歌影象「Google Images」手動+程式設計地為給定的查詢下載示例影象。
在我看來,一個更好的選擇可能是,使用 Bing 的影象搜尋 API,它是完全自動化的且不需要手動干預。我在這篇文章中實現了這個全自動化方法(https://www.pyimagesearch.com/2018/04/09/how-to-quickly-build-a-deep-learning-image-dataset/)。
使用後一種方法,我可以從《侏羅紀公園》和《侏羅紀世界》中下載 218 張人臉影象。
通過 Bing 影象搜尋 API 下載 Owen Grady 的人臉影象的命令示例如下:
$ mkdir dataset/owen_grady
$ python search_bing_api.py --query "owen grady" --output dataset/owen_grady
現在讓我們來看整個資料集(刪除不包含該人物人臉的影象後):
$ tree jp_dataset --filelimit 10
jp_dataset
├── alan_grant [22 entries]
├── claire_dearing [53 entries]
├── ellie_sattler [31 entries]
├── ian_malcolm [41 entries]
├── john_hammond [36 entries]
└── owen_grady [35 entries]
6 directories, 0 files
在短短 20 多分鐘內(包括刪除誤判樣本的時間),我就能收集到《侏羅紀公園》/《侏羅紀世界》的自定義人臉資料集:
圖 3:通過 Python 和 Bing 影象搜尋 API 以程式設計的方式建立出的人臉識別資料集示例。圖中是《侏羅紀公園》系列電影中的六個人物。
方法 3:手動收集人臉影象
圖 4:手動下載人臉影象是最不可取的選項,但你不該忘記它。當一個人並不經常在網路上出現,或者影象沒有標籤時,你可以使用這種方法。
最後一種建立自定義人臉識別資料集的方法也是最不可取的一種,是手動尋找並儲存人臉影象樣本。
這種方法顯然是最乏味的,且需要耗費最多的人工工作時間——通常我們更喜歡「自動化」的解決方案,但是在某些情況下,你不得不付諸人工。
使用此方法,你需要手動檢查:
搜尋引擎的搜尋結果(例如,谷歌和 Bing)
社交網路資料(Facebook、Twitter、Instagram、SnapChat 等)
圖片分享服務(Google Photos、Flickr 等)
然後手動將這些影象儲存到磁碟上。
在這些場景下,使用者通常具備某種型別的公開資料,但是比以程式設計的方式用爬蟲爬到的影象要少得多。
PyImageSearch Gurus(免費)示範課程
圖 5:在 PyImageSearch Gurus 課程(https://www.pyimagesearch.com/pyimagesearch-gurus/)中,你將學會構建人臉識別安防系統。當一個未經授權的入侵者坐在你的桌前時,它會通過文字訊息(包含影象)提醒你。
總結
本文介紹了三種為人臉識別任務建立自定義人臉資料集的方法。
你具體會選擇哪種方法完全取決於你自己的人臉識別應用。
如果你正在構建一個「現場」的人臉識別系統,例如用於教室、公司或其他組織的人臉識別系統,你可能會讓使用者進入專門用於收集示例人臉影象的房間,然後在那裡繼續從視訊流中捕獲人臉影象 (方法 1)。
另一方面,如果你正在構建一個包含公眾人物、名人、運動員等的人臉識別系統,那麼在網上可能有他們足夠多的人臉影象樣本。在這種情況下,你可以利用現有的 API 以程式設計方式下載人臉影象樣本 (方法 2)。
最後,如果你試圖識別的面孔在網上沒有公開的個人資料(或者個人資料非常有限),你可能需要手動收集和管理人臉資料集 (方法 3)。這顯然是最人工、最繁瑣的方法,但在某些情況下,如果你想識別某些面孔,可能需要使用這種方法。
原文連結:https://www.pyimagesearch.com/2018/06/11/how-to-build-a-custom-face-recognition-dataset/