使用 dlib 進行人臉識別
theme: hydrogen
「這是我參與2022首次更文挑戰的第32天,活動詳情檢視:2022首次更文挑戰」
使用 dlib 進行人臉識別
Dlib
提供了基於深度學習的高效能人臉識別演算法,該模型對戶外資料集中標記人臉的識別準確率可以達到 99.38%。該演算法基於 ResNet-34
網路實現,使用 300
萬張人臉進行訓練,預訓練的模型檔案 dlib_face_recognition_resnet_model_v1.dat 下載後就可以直接用於前向計算。
網路以生成 128
維 (128D) 描述符的方式進行訓練,用於量化人臉。訓練使用三元組執行,單個三元組訓練資料由三個影象組成,其中兩個對應於同一個人。網路為每張影象生成 128D
描述符,三元組損失函式對此進行了量化,嘗試將同一個人的兩個影象的 128D
描述符相距更近,同時將不同人的兩個影象的 128D
描述符相距更遠。
這個過程對數千個不同人的數百萬張影象重複數百萬次,最後,它能夠為每個人生成一個 128D
描述符,最終的 128D
描述符是能夠很好的對人臉進行編碼:
- 同一個人的兩幅影象生成的 128D
描述符彼此非常相似
- 不同人的兩張影象生成的 128D
描述符差別很大
因此,利用 dlib
函式,我們可以使用預訓練模型將人臉對映到 128D
描述符。然後使用這些特徵向量來進行人臉識別。
計算 128D
描述符用於量化人臉的過程很簡單:
```python
使用 dlib 庫載入特徵點預測器、人臉編碼和人臉檢測器
pose_predictor_5_point = dlib.shape_predictor("shape_predictor_5_face_landmarks.dat") face_encoder = dlib.face_recognition_model_v1("dlib_face_recognition_resnet_model_v1.dat") detector = dlib.get_frontal_face_detector()
def face_encodings(face_image, number_of_times_to_upsample=1, num_jitters=1): """返回影象中每個人臉的 128D 描述符"""
# 檢測人臉
face_locations = detector(face_image, number_of_times_to_upsample)
# 檢測面部特徵點
raw_landmarks = [pose_predictor_5_point(face_image, face_location) for face_location in face_locations]
# 使用每個檢測到的特徵點計算每個檢測到的人臉的編碼
return [np.array(face_encoder.compute_face_descriptor(face_image, raw_landmark_set, num_jitters)) for
raw_landmark_set in raw_landmarks]
載入影象並轉換為 RGB 模式
image = cv2.imread("jared_1.jpg") rgb = image[:, :, ::-1]
計算影象中每個人臉的編碼
encodings = face_encodings(rgb)
列印第一個編碼的特徵
print(encodings[0])
如上所示,關鍵是呼叫 `dlib` 的 `face_encoder.compute_face_descriptor()` 函式,使用檢測到的每個人臉的特徵點計算每個檢測到的人臉的 `128D` 編碼,其中 `num_jitters` 引數用於設定每個人臉隨機抖動的次數,返回值為每次計算的平均 `128D` 描述符,輸出的 `128D` 描述符如下:
shell
[-0.09235165 0.11607055 0.03648872 -0.08326858 -0.12627071 -0.01334486 -0.11334236 -0.10083835 0.20534235 -0.1636433 0.16874117 -0.05276754 -0.17746128 -0.05377002 -0.02731067 0.24751744 -0.22732623 -0.20258367 -0.03421091 -0.00150665 0.05875423 0.03020219 0.03901095 0.03496565 -0.15658092 -0.34250638 -0.08725534 -0.06245319 -0.04688681 -0.04861078 -0.07620423 0.05013577 -0.18563135 -0.04075277 0.05248301 0.09195475 -0.00887688 -0.1192601 0.18633801 0.00056917 -0.29226956 0.01442468 0.09583923 0.19053322 0.15580602 -0.04580544 0.01866002 -0.15243134 0.13535264 -0.17270051 0.03029358 0.16308595 0.04719323 0.08862312 0.01600051 -0.112983 0.06787978 0.17171389 -0.09536573 -0.02140218 0.11402114 -0.04710582 -0.01966342 -0.0705786 0.21773803 0.12153016 -0.08498291 -0.24783675 0.06667361 -0.08091511 -0.11054871 0.08837797 -0.17216064 -0.18642734 -0.27270097 -0.03300989 0.31748736 0.06824204 -0.16750985 0.0599058 -0.00497202 -0.02882685 0.07890167 0.19422579 -0.02771271 0.05871597 -0.06130363 0.04929798 0.27234387 -0.04948008 -0.00844343 0.22556995 0.00912007 0.07115038 0.01273906 0.03535268 -0.05074561 0.05441948 -0.13103089 -0.00421767 0.07432865 0.0025964 -0.06208063 0.12578207 -0.16597968 0.09258381 -0.02716768 0.02978029 -0.00216489 -0.01805471 -0.04702468 -0.05231683 0.11994087 -0.16787212 0.17464222 0.16930985 0.05848085 0.09450675 0.11558257 0.0659898 -0.00265438 -0.01509937 -0.22738113 0.01624682 0.13056616 -0.04214386 0.06433617 0.00774699]
```
獲取到檢測到的人臉編碼後,下一步就是進行人臉識別。
使用 128D
描述符計算的某種距離度量可以用於執行人臉識別,如果兩個人臉描述符向量之間的歐幾里得距離小於 0.6
(歐幾里得距離可以使用 numpy.linalg.norm()
計算),則可以認為它們屬於同一個人;否則,他們是不同的人。
接下來,我們使用 5 張已知影象與另 1 張測試影象進行比較。為了比較人臉,我們需要編寫兩個函式:compare_faces()
和 compare_faces_ordered()
。
compare_faces()
函式返回已知人臉編碼與待識別人臉間的距離:
python
def compare_faces(encodings, encoding_to_check):
return list(np.linalg.norm(encodings - encoding_to_check, axis=1))
compare_faces_ordered()
函式返回排序後的已知人臉編碼與待識別人臉間的距離和相應的名稱:
python
def compare_faces_ordered(encodings, face_names, encoding_to_check):
distances = list(np.linalg.norm(encodings - encoding_to_check, axis=1))
return zip(*sorted(zip(distances, face_names)))
接下來,將 5 個已標記影象與 1 個未標記影象進行比較,第一步是載入所有影象並轉換為 RGB
格式:
```python
載入所有影象並轉換為 RGB 格式
known_image_1 = cv2.imread("小新_1.png") known_image_2 = cv2.imread("小甜_1.png") known_image_3 = cv2.imread("小甜_2.png") known_image_4 = cv2.imread("小甜_3.png") known_image_5 = cv2.imread("小新_2.png") unknown_image = cv2.imread("test.png") known_image_1 = known_image_1[:, :, ::-1] known_image_2 = known_image_2[:, :, ::-1] known_image_3 = known_image_3[:, :, ::-1] known_image_4 = known_image_4[:, :, ::-1] known_image_5 = known_image_5[:, :, ::-1] unknown_image = unknown_image[:, :, ::-1]
標記人臉
names = ["小新_1.png", "小甜_1.png", "小甜_2.png", "小甜_3.png", "小新_2.png"]
下一步是計算每個影象的 `128D` 編碼:
python
計算每個影象的 128D 編碼
known_image_1_encoding = face_encodings(known_image_1)[0]
known_image_2_encoding = face_encodings(known_image_2)[0]
known_image_3_encoding = face_encodings(known_image_3)[0]
known_image_4_encoding = face_encodings(known_image_4)[0]
known_image_5_encoding = face_encodings(known_image_5)[0]
known_encodings = [known_image_1_encoding, known_image_2_encoding, known_image_3_encoding, known_image_4_encoding, known_image_5_encoding]
unknown_encoding = face_encodings(unknown_image)[0]
最後,可以使用 `compare_faces_ordered()` 函式比較與識別人臉:
python
computed_distances_ordered, ordered_names = compare_faces_ordered(known_encodings, names, unknown_encoding)
列印返回資訊
print(computed_distances)
print(computed_distances_ordered)
print(ordered_names)
列印的返回資訊如下:
(0.26459402873041915, 0.2728113455078627, 0.2945116087102425, 0.42567525558949304, 0.42899966791571725)
('小甜', '小甜', '小甜', '小新', '小新')
```
通過上示的列印資訊,可以得出結論待識別的人臉屬於小甜,而小新的人臉編碼資訊與待識別人臉的編碼資訊距離較遠,表示不是同一個人:
- OpenCV使用顏色進行膚色檢測
- Keras深度學習——構建電影推薦系統
- PyTorch張量操作詳解
- OpenCV直方圖的比較
- Python 常用字串操作
- 使用 dlib 進行人臉識別
- OpenCV 人臉檢測詳解(僅需2行程式碼學會人臉檢測)
- Keras深度學習——使用fastText構建單詞向量
- Keras深度學習——使用skip-gram和CBOW模型構建單詞向量
- Keras深度學習——從零開始構建單詞向量
- Keras深度學習——生成對抗網路
- Keras深度學習——建立自定義目標檢測資料集
- PyTorch強化學習——基於值迭代的強化學習演算法
- PyTorch強化學習——模擬FrozenLake環境
- PyTorch強化學習——策略評估
- PyTorch強化學習——馬爾科夫決策過程
- Keras深度學習——DeepDream演算法生成影象
- Keras深度學習——使用對抗攻擊生成可欺騙神經網路的影象
- PyTorch強化學習——策略梯度演算法
- Keras深度學習——交通標誌識別