Dlib模型人脸特征检测原理及demo
?
cungudafa 2019-06-24 16:55:34 ?8003 ?收藏 49
展開
目錄
序
Dlib模型
Dlib人臉特征檢測原理
(1)提取特征點
(2)獲取特征數據集寫入csv
(3)計算特征數據集的歐氏距離作對比
正文
一、構建自己的數據集
二、特征檢測
三、人臉識別
四、擴展
序
Dlib模型
安裝dlib
下載地址:https://pypi.org/simple/dlib/
安裝教程參考前一文:基于dlib庫人臉特征提取【構建自己的人臉識別數據集】
dlib人臉檢測模塊有5個特征點以及68個特征點的數據集
Dlib人臉特征檢測原理
(1)提取特征點
圖中為68個特征數據點顯示效果
參考鏈接:python+OpenCv+dlib實現人臉68個關鍵點檢測并標注
(2)獲取特征數據集寫入csv
根據數據集,模型----訓練----》68個特征數據
寫入csv:
(3)計算特征數據集的歐氏距離作對比
圖中為我的運行效果:選取最接近(歐氏距離最小)的值,標注為person 1
圖像處理部分運用了python3.7和opencv3.4.1,需要具備這方面的知識。
正文
環境:python3.7+anaconda3+jupyternotebook
完整項目結構:
一、構建自己的數據集
1錄入數據集源碼-》
參考我前一篇文章:基于dlib庫人臉特征提取【構建自己的人臉識別數據集】
文件錄入時:輸入姓名,錄入樣本數:
一個樣本:(百度爬取正臉圖片也可)(爬取源碼見前面鏈接)
人臉數據集目錄(在這里排上序是為了命名不重復,細節處理。)
二、特征檢測
主要文件目錄:
2獲取特征點并保存數據源碼:get_features.py
# 從人臉圖像文件中提取人臉特征存入 CSV
# Features extraction from images and save into features_all.csv
# return_128d_features() ? ? ? ? ?獲取某張圖像的128D特征
# compute_the_mean() ? ? ? ? ? ? ?計算128D特征均值
from cv2 import cv2 as cv2
import os
import dlib
from skimage import io
import csv
import numpy as np
# 要讀取人臉圖像文件的路徑
path_images_from_camera = "D:/myworkspace/JupyterNotebook/People/person/"
# Dlib 正向人臉檢測器
detector = dlib.get_frontal_face_detector()
# Dlib 人臉預測器
predictor = dlib.shape_predictor("D:/myworkspace/JupyterNotebook/People/model/shape_predictor_68_face_landmarks.dat")
# Dlib 人臉識別模型
# Face recognition model, the object maps human faces into 128D vectors
face_rec = dlib.face_recognition_model_v1("D:/myworkspace/JupyterNotebook/People/model/dlib_face_recognition_resnet_model_v1.dat")
# 返回單張圖像的 128D 特征
def return_128d_features(path_img):
? ? img_rd = io.imread(path_img)
? ? img_gray = cv2.cvtColor(img_rd, cv2.COLOR_BGR2RGB)
? ? faces = detector(img_gray, 1)
? ? print("%-40s %-20s" % ("檢測到人臉的圖像 / image with faces detected:", path_img), '\n')
? ? # 因為有可能截下來的人臉再去檢測,檢測不出來人臉了
? ? # 所以要確保是 檢測到人臉的人臉圖像 拿去算特征
? ? if len(faces) != 0:
? ? ? ? shape = predictor(img_gray, faces[0])
? ? ? ? face_descriptor = face_rec.compute_face_descriptor(img_gray, shape)
? ? else:
? ? ? ? face_descriptor = 0
? ? ? ? print("no face")
? ? return face_descriptor
# 將文件夾中照片特征提取出來, 寫入 CSV
def return_features_mean_personX(path_faces_personX):
? ? features_list_personX = []
? ? photos_list = os.listdir(path_faces_personX)
? ? if photos_list:
? ? ? ? for i in range(len(photos_list)):
? ? ? ? ? ? # 調用return_128d_features()得到128d特征
? ? ? ? ? ? print("%-40s %-20s" % ("正在讀的人臉圖像 / image to read:", path_faces_personX + "/" + photos_list[i]))
? ? ? ? ? ? features_128d = return_128d_features(path_faces_personX + "/" + photos_list[i])
? ? ? ? ? ? # ?print(features_128d)
? ? ? ? ? ? # 遇到沒有檢測出人臉的圖片跳過
? ? ? ? ? ? if features_128d == 0:
? ? ? ? ? ? ? ? i += 1
? ? ? ? ? ? else:
? ? ? ? ? ? ? ? features_list_personX.append(features_128d)
? ? else:
? ? ? ? print("文件夾內圖像文件為空 / Warning: No images in " + path_faces_personX + '/', '\n')
? ? # 計算 128D 特征的均值
? ? # N x 128D -> 1 x 128D
? ? if features_list_personX:
? ? ? ? features_mean_personX = np.array(features_list_personX).mean(axis=0)
? ? else:
? ? ? ? features_mean_personX = '0'
? ? return features_mean_personX
# 讀取某人所有的人臉圖像的數據
people = os.listdir(path_images_from_camera)
people.sort()
with open("D:/myworkspace/JupyterNotebook/People/feature/features2_all.csv", "w", newline="") as csvfile:
? ? writer = csv.writer(csvfile)
? ? for person in people:
? ? ? ? print("##### " + person + " #####")
? ? ? ? # Get the mean/average features of face/personX, it will be a list with a length of 128D
? ? ? ? features_mean_personX = return_features_mean_personX(path_images_from_camera + person)
? ? ? ? writer.writerow(features_mean_personX)
? ? ? ? print("特征均值 / The mean of features:", list(features_mean_personX))
? ? ? ? print('\n')
? ? print("所有錄入人臉數據存入 / Save all the features of faces registered into: D:/myworkspace/JupyterNotebook/People/feature/features_all2.csv")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
三、人臉識別
3視頻流實時識別人臉數據:face_face.py
# 攝像頭實時人臉識別
import os
import winsound # 系統音效
from playsound import playsound # 音頻播放
import dlib ? ? ? ? ?# 人臉處理的庫 Dlib
import csv # 存入表格
import time
import sys
import numpy as np ? # 數據處理的庫 numpy
from cv2 import cv2 as cv2 ? ? ? ? ? # 圖像處理的庫 OpenCv
import pandas as pd ?# 數據處理的庫 Pandas
# 人臉識別模型,提取128D的特征矢量
# face recognition model, the object maps human faces into 128D vectors
# Refer this tutorial: http://dlib.net/python/index.html#dlib.face_recognition_model_v1
facerec = dlib.face_recognition_model_v1("D:/myworkspace/JupyterNotebook/People/model/dlib_face_recognition_resnet_model_v1.dat")
# 計算兩個128D向量間的歐式距離
# compute the e-distance between two 128D features
def return_euclidean_distance(feature_1, feature_2):
? ? feature_1 = np.array(feature_1)
? ? feature_2 = np.array(feature_2)
? ? dist = np.sqrt(np.sum(np.square(feature_1 - feature_2)))
? ? return dist
# 處理存放所有人臉特征的 csv
path_features_known_csv = "D:/myworkspace/JupyterNotebook/People/feature/features2_all.csv"
csv_rd = pd.read_csv(path_features_known_csv, header=None)
# 用來存放所有錄入人臉特征的數組
# the array to save the features of faces in the database
features_known_arr = []
# 讀取已知人臉數據
# print known faces
for i in range(csv_rd.shape[0]):
? ? features_someone_arr = []
? ? for j in range(0, len(csv_rd.ix[i, :])):
? ? ? ? features_someone_arr.append(csv_rd.ix[i, :][j])
? ? features_known_arr.append(features_someone_arr)
print("Faces in Database:", len(features_known_arr))
# Dlib 檢測器和預測器
# The detector and predictor will be used
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('D:/myworkspace/JupyterNotebook/People/model/shape_predictor_68_face_landmarks.dat')
# 創建 cv2 攝像頭對象
# cv2.VideoCapture(0) to use the default camera of PC,
# and you can use local video name by use cv2.VideoCapture(filename)
cap = cv2.VideoCapture(0)
# cap.set(propId, value)
# 設置視頻參數,propId 設置的視頻參數,value 設置的參數值
cap.set(3, 480)
# cap.isOpened() 返回 true/false 檢查初始化是否成功
# when the camera is open
while cap.isOpened():
? ? flag, img_rd = cap.read()
? ? kk = cv2.waitKey(1)
? ? # 取灰度
? ? img_gray = cv2.cvtColor(img_rd, cv2.COLOR_RGB2GRAY)
? ? # 人臉數 faces
? ? faces = detector(img_gray, 0)
? ? # 待會要寫的字體 font to write later
? ? font = cv2.FONT_HERSHEY_COMPLEX
? ? # 存儲當前攝像頭中捕獲到的所有人臉的坐標/名字
? ? # the list to save the positions and names of current faces captured
? ? pos_namelist = []
? ? name_namelist = []
? ? # 按下 q 鍵退出
? ? # press 'q' to exit
? ? if kk == ord('q'):
? ? ? ? break
? ? else:
? ? ? ? # 檢測到人臉 when face detected
? ? ? ? if len(faces) != 0: ?
? ? ? ? ? ? # 獲取當前捕獲到的圖像的所有人臉的特征,存儲到 features_cap_arr
? ? ? ? ? ? # get the features captured and save into features_cap_arr
? ? ? ? ? ? features_cap_arr = []
? ? ? ? ? ? for i in range(len(faces)):
? ? ? ? ? ? ? ? shape = predictor(img_rd, faces[i])
? ? ? ? ? ? ? ? features_cap_arr.append(facerec.compute_face_descriptor(img_rd, shape))
? ? ? ? ? ? # 遍歷捕獲到的圖像中所有的人臉
? ? ? ? ? ? # traversal all the faces in the database
? ? ? ? ? ? for k in range(len(faces)):
? ? ? ? ? ? ? ? print("##### camera person", k+1, "#####")
? ? ? ? ? ? ? ? # 讓人名跟隨在矩形框的下方
? ? ? ? ? ? ? ? # 確定人名的位置坐標
? ? ? ? ? ? ? ? # 先默認所有人不認識,是 unknown
? ? ? ? ? ? ? ? # set the default names of faces with "unknown"
? ? ? ? ? ? ? ? name_namelist.append("unknown")
? ? ? ? ? ? ? ? # 每個捕獲人臉的名字坐標 the positions of faces captured
? ? ? ? ? ? ? ? pos_namelist.append(tuple([faces[k].left(), int(faces[k].bottom() + (faces[k].bottom() - faces[k].top())/4)]))
? ? ? ? ? ? ? ? # 對于某張人臉,遍歷所有存儲的人臉特征
? ? ? ? ? ? ? ? # for every faces detected, compare the faces in the database
? ? ? ? ? ? ? ? e_distance_list = []
? ? ? ? ? ? ? ? for i in range(len(features_known_arr)):
? ? ? ? ? ? ? ? ? ? # 如果 person_X 數據不為空
? ? ? ? ? ? ? ? ? ? if str(features_known_arr[i][0]) != '0.0':
? ? ? ? ? ? ? ? ? ? ? ? print("with person", str(i + 1), "the e distance: ", end='')
? ? ? ? ? ? ? ? ? ? ? ? e_distance_tmp = return_euclidean_distance(features_cap_arr[k], features_known_arr[i])
? ? ? ? ? ? ? ? ? ? ? ? print(e_distance_tmp)
? ? ? ? ? ? ? ? ? ? ? ? e_distance_list.append(e_distance_tmp)
? ? ? ? ? ? ? ? ? ? else:
? ? ? ? ? ? ? ? ? ? ? ? # 空數據 person_X
? ? ? ? ? ? ? ? ? ? ? ? e_distance_list.append(999999999)
? ? ? ? ? ? ? ? # 找出最接近的一個人臉數據是第幾個
? ? ? ? ? ? ? ? # Find the one with minimum e distance
? ? ? ? ? ? ? ? similar_person_num = e_distance_list.index(min(e_distance_list))
? ? ? ? ? ? ? ? print("Minimum e distance with person", int(similar_person_num)+1)
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? # 計算人臉識別特征與數據集特征的歐氏距離
? ? ? ? ? ? ? ? # 距離小于0.4則標出為可識別人物
? ? ? ? ? ? ? ? if min(e_distance_list) < 0.4:
? ? ? ? ? ? ? ? ? ? # 這里可以修改攝像頭中標出的人名
? ? ? ? ? ? ? ? ? ? # Here you can modify the names shown on the camera
? ? ? ? ? ? ? ? ? ? # 1、遍歷文件夾目錄
? ? ? ? ? ? ? ? ? ? folder_name = 'D:/myworkspace/JupyterNotebook/People/person'
? ? ? ? ? ? ? ? ? ? # 最接近的人臉
? ? ? ? ? ? ? ? ? ? sum=similar_person_num+1
? ? ? ? ? ? ? ? ? ? key_id=1 # 從第一個人臉數據文件夾進行對比
? ? ? ? ? ? ? ? ? ? # 獲取文件夾中的文件名:1wang、2zhou、3...
? ? ? ? ? ? ? ? ? ? file_names = os.listdir(folder_name)
? ? ? ? ? ? ? ? ? ? for name in file_names:
? ? ? ? ? ? ? ? ? ? ? ? # print(name+'->'+str(key_id))
? ? ? ? ? ? ? ? ? ? ? ? if sum ==key_id:
? ? ? ? ? ? ? ? ? ? ? ? ? ? #winsound.Beep(300,500)# 響鈴:300頻率,500持續時間
? ? ? ? ? ? ? ? ? ? ? ? ? ? name_namelist[k] = name[1:]#人名刪去第一個數字(用于視頻輸出標識)
? ? ? ? ? ? ? ? ? ? ? ? key_id += 1
? ? ? ? ? ? ? ? ? ? # 播放歡迎光臨音效
? ? ? ? ? ? ? ? ? ? #playsound('D:/myworkspace/JupyterNotebook/People/music/welcome.wav')
? ? ? ? ? ? ? ? ? ? # print("May be person "+str(int(similar_person_num)+1))
? ? ? ? ? ? ? ? ? ? # -----------篩選出人臉并保存到visitor文件夾------------
? ? ? ? ? ? ? ? ? ? for i, d in enumerate(faces):
? ? ? ? ? ? ? ? ? ? ? ? x1 = d.top() if d.top() > 0 else 0
? ? ? ? ? ? ? ? ? ? ? ? y1 = d.bottom() if d.bottom() > 0 else 0
? ? ? ? ? ? ? ? ? ? ? ? x2 = d.left() if d.left() > 0 else 0
? ? ? ? ? ? ? ? ? ? ? ? y2 = d.right() if d.right() > 0 else 0
? ? ? ? ? ? ? ? ? ? ? ? face = img_rd[x1:y1,x2:y2]
? ? ? ? ? ? ? ? ? ? ? ? size = 64
? ? ? ? ? ? ? ? ? ? ? ? face = cv2.resize(face, (size,size))
? ? ? ? ? ? ? ? ? ? ? ? # 要存儲visitor人臉圖像文件的路徑
? ? ? ? ? ? ? ? ? ? ? ? path_visitors_save_dir = "D:/myworkspace/JupyterNotebook/People/visitor/known"
? ? ? ? ? ? ? ? ? ? ? ? # 存儲格式:2019-06-24-14-33-40wang.jpg
? ? ? ? ? ? ? ? ? ? ? ? now_time = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
? ? ? ? ? ? ? ? ? ? ? ? save_name = str(now_time)+str(name_namelist[k])+'.jpg'
? ? ? ? ? ? ? ? ? ? ? ? # print(save_name)
? ? ? ? ? ? ? ? ? ? ? ? # 本次圖片保存的完整url
? ? ? ? ? ? ? ? ? ? ? ? save_path = path_visitors_save_dir+'/'+ save_name ? ?
? ? ? ? ? ? ? ? ? ? ? ? # 遍歷visitor文件夾所有文件名
? ? ? ? ? ? ? ? ? ? ? ? visitor_names = os.listdir(path_visitors_save_dir)
? ? ? ? ? ? ? ? ? ? ? ? visitor_name=''
? ? ? ? ? ? ? ? ? ? ? ? for name in visitor_names:
? ? ? ? ? ? ? ? ? ? ? ? ? ? # 名字切片到分鐘數:2019-06-26-11-33-00wangyu.jpg
? ? ? ? ? ? ? ? ? ? ? ? ? ? visitor_name=(name[0:16]+'-00'+name[19:])
? ? ? ? ? ? ? ? ? ? ? ? # print(visitor_name)
? ? ? ? ? ? ? ? ? ? ? ? visitor_save=(save_name[0:16]+'-00'+save_name[19:])
? ? ? ? ? ? ? ? ? ? ? ? # print(visitor_save)
? ? ? ? ? ? ? ? ? ? ? ? # 一分鐘之內重復的人名不保存
? ? ? ? ? ? ? ? ? ? ? ? if visitor_save!=visitor_name:
? ? ? ? ? ? ? ? ? ? ? ? ? ? cv2.imwrite(save_path, face)
? ? ? ? ? ? ? ? ? ? ? ? ? ? print('新存儲:'+path_visitors_save_dir+'/'+str(now_time)+str(name_namelist[k])+'.jpg')
? ? ? ? ? ? ? ? ? ? ? ? else:
? ? ? ? ? ? ? ? ? ? ? ? ? ? print('重復,未保存!')
? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? else:
? ? ? ? ? ? ? ? ? ? # 播放無法識別音效
? ? ? ? ? ? ? ? ? ? #playsound('D:/myworkspace/JupyterNotebook/People/music/sorry.wav')
? ? ? ? ? ? ? ? ? ? print("Unknown person")
? ? ? ? ? ? ? ? ? ? # -----保存圖片-------
? ? ? ? ? ? ? ? ? ? # -----------篩選出人臉并保存到visitor文件夾------------
? ? ? ? ? ? ? ? ? ? for i, d in enumerate(faces):
? ? ? ? ? ? ? ? ? ? ? ? x1 = d.top() if d.top() > 0 else 0
? ? ? ? ? ? ? ? ? ? ? ? y1 = d.bottom() if d.bottom() > 0 else 0
? ? ? ? ? ? ? ? ? ? ? ? x2 = d.left() if d.left() > 0 else 0
? ? ? ? ? ? ? ? ? ? ? ? y2 = d.right() if d.right() > 0 else 0
? ? ? ? ? ? ? ? ? ? ? ? face = img_rd[x1:y1,x2:y2]
? ? ? ? ? ? ? ? ? ? ? ? size = 64
? ? ? ? ? ? ? ? ? ? ? ? face = cv2.resize(face, (size,size))
? ? ? ? ? ? ? ? ? ? ? ? # 要存儲visitor-》unknown人臉圖像文件的路徑
? ? ? ? ? ? ? ? ? ? ? ? path_visitors_save_dir = "D:/myworkspace/JupyterNotebook/People/visitor/unknown"
? ? ? ? ? ? ? ? ? ? ? ? # 存儲格式:2019-06-24-14-33-40unknown.jpg
? ? ? ? ? ? ? ? ? ? ? ? now_time = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
? ? ? ? ? ? ? ? ? ? ? ? # print(save_name)
? ? ? ? ? ? ? ? ? ? ? ? # 本次圖片保存的完整url
? ? ? ? ? ? ? ? ? ? ? ? save_path = path_visitors_save_dir+'/'+ str(now_time)+'unknown.jpg'
? ? ? ? ? ? ? ? ? ? ? ? cv2.imwrite(save_path, face)
? ? ? ? ? ? ? ? ? ? ? ? print('新存儲:'+path_visitors_save_dir+'/'+str(now_time)+'unknown.jpg')
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? # 矩形框
? ? ? ? ? ? ? ? # draw rectangle
? ? ? ? ? ? ? ? for kk, d in enumerate(faces):
? ? ? ? ? ? ? ? ? ? # 繪制矩形框
? ? ? ? ? ? ? ? ? ? cv2.rectangle(img_rd, tuple([d.left(), d.top()]), tuple([d.right(), d.bottom()]), (0, 255, 255), 2)
? ? ? ? ? ? ? ? print('\n')
? ? ? ? ? ? # 在人臉框下面寫人臉名字
? ? ? ? ? ? # write names under rectangle
? ? ? ? ? ? for i in range(len(faces)):
? ? ? ? ? ? ? ? cv2.putText(img_rd, name_namelist[i], pos_namelist[i], font, 0.8, (0, 255, 255), 1, cv2.LINE_AA)
? ? print("Faces in camera now:", name_namelist, "\n")
? ? #cv2.putText(img_rd, "Press 'q': Quit", (20, 450), font, 0.8, (84, 255, 159), 1, cv2.LINE_AA)
? ? cv2.putText(img_rd, "Face Recognition", (20, 40), font, 1, (0, 0, 255), 1, cv2.LINE_AA)
? ? cv2.putText(img_rd, "Visitors: " + str(len(faces)), (20, 100), font, 1, (0, 0, 255), 1, cv2.LINE_AA)
? ? # 窗口顯示 show with opencv
? ? cv2.imshow("camera", img_rd)
# 釋放攝像頭 release camera
cap.release()
# 刪除建立的窗口 delete all the windows
cv2.destroyAllWindows()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
四、擴展
這次項目實踐了解了dlib人臉識別原理,復習了opencv使用原理,我們的項目要求:
假定該系統完成后將工作于學生宿舍門口,攝像頭安裝于門的貓眼處、或者門側邊墻上:
對本宿舍的學生進行人臉識別(身份驗證),
通過驗證就播放語音“歡迎光臨!”(模擬開門),否則播放“抱歉,無法驗證您的身份!”,
同時用數據庫記錄來訪者的身份、人臉圖片和訪問時間等信息。
實現過程:
在前文的基礎上,增加數據集為全寢室人臉識別;
python語音播放參考前文:Python讀取wav音頻文件
記錄來訪者,以時間和檢測名命名的圖片存儲到文件visitor
附:
1、更多人臉識別運用github參考:https://github.com/cungudafa/cungudafa.github.io
2、人臉識別源碼參考:https://github.com/ageitgey/face_recognition#face-recognition
3、基于人工智能數據集經典案例(貓狗數據集)參考:
https://github.com/fchollet/deep-learning-with-python-notebooks/blob/master/5.2-using-convnets-with-small-datasets.ipynb
https://github.com/fchollet/deep-learning-with-python-notebooks/blob/master/5.4-visualizing-what-convnets-learn.ipynb
?
總結
以上是生活随笔為你收集整理的Dlib模型人脸特征检测原理及demo的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 人脸识别-dlib
- 下一篇: 人脸识别之insightface开源代码