Refiérase principalmente a dos artículos:
https://blog.csdn.net/liuxiao214/article/details/83411820
https://www.jianshu.com/p/577af31ced74
0. Medio ambiente
windows
python3.6
Dlib
numpy==1.14.5
glob
opencv-python==3.4.3.18
Instale la referencia de Dlib: https://blog.csdn.net/qq_35975447/article/details/109802787
0.1 Estructura de archivos
│ .gitignore
│ faceAlignment.py
│ faceDetect.py
│ faceLandmarks.py
│ faceRecognition.py
│ file.txt
│
├─data
│ │ test_1988.jpg
│ │
│ ├─candidate-faces
│ │ liushishi.jpg
│ │ liuyifei.jpg
│ │ tangyan.jpg
│ │ tongliya.jpg
│ │ yangzi.jpg
│ │ zhaoliying.jpg
│ │
│ └─faces
│ tangyan.jpg
│ zhaoliying.jpg
│
├─models
│ dlib_face_recognition_resnet_model_v1.dat
│ mmod_human_face_detector.dat
│ shape_predictor_5_face_landmarks.dat
│ shape_predictor_68_face_landmarks.dat
│
└─results
├─alignment
│ test_1988_0_Align68.jpg
│ test_1988_1_Align68.jpg
│ test_1988_2_Align68.jpg
│ test_1988_3_Align68.jpg
│ test_1988_4_Align68.jpg
│ test_1988_5_Align68.jpg
│
├─detect
│ test_1988_HOG.jpg
│ test_1988_MMOD.jpg
│
├─landmarks
│ test_1988_5Landmarks.jpg
│ test_1988_68Landmarks.jpg
│
└─recongnition
recognition_reslut.txt
0.2 Descarga del modelo
https://github.com/davisking/dlib-models
0.3 mi código
https://download.csdn.net/download/qq_35975447/13129563
1. Comparación de dos métodos de detección de rostros
Los dos métodos incluyen principalmente: Dlib incluye y llama al modelo de aprendizaje profundo.
1.1 Hora
CERDO |
MMOD |
1.437422513961792s
|
106.82666826248169s |
1.2 Efecto
Imagen original:
Efecto HOG:
Efecto MMOD:
1.2 Código
El código aquí se refiere principalmente al primer enlace, y luego, de acuerdo con el método propio de Dlib y llamando al modelo de aprendizaje profundo, el tiempo de prueba se ejecuta en un bucle y la imagen se guarda en el directorio results / detect /:
# encoding:utf-8
import dlib
import cv2
import os
import time
def rect_to_bb(rect): # 获得人脸矩形的坐标信息
x = rect.left()
y = rect.top()
w = rect.right() - x
h = rect.bottom() - y
return (x, y, w, h)
def resize(image, width=1200): # 将待检测的image进行resize
r = width * 1.0 / image.shape[1]
dim = (width, int(image.shape[0] * r))
resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
return resized
def detect(isHOG=False):
image_path = "./data/"
image_file = "test_1988.jpg"
startTime = time.time()
if isHOG:
detector = dlib.get_frontal_face_detector() # 基于HOG+SVM分类
else:
model_path = "./models/mmod_human_face_detector.dat" # 基于 Maximum-Margin Object Detector 的深度学习人脸检测方案
detector = dlib.cnn_face_detection_model_v1(model_path)
image = cv2.imread(image_path + image_file)
image = resize(image, width=1200)
# image = resize(image, width=600)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
rects = detector(gray, 1)
print("{} method, detect spend {}s ".format(("HOG" if isHOG else "MMOD"), time.time()-startTime))
for (i, rect) in enumerate(rects):
if isHOG:
(x, y, w, h) = rect_to_bb(rect)
else:
(x, y, w, h) = rect_to_bb(rect.rect)
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(image, "Face: {}".format(i + 1), (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
cv2.imshow("Output", image)
savePath = "./results/detect/"
if not os.path.exists(savePath):
os.makedirs(savePath)
if isHOG:
saveName = image_file[:-4] + "_HOG.jpg"
else:
saveName = image_file[:-4] + "_MMOD.jpg"
cv2.imwrite(savePath + saveName, image)
cv2.waitKey(10)
if __name__ == "__main__":
isHOG = True
detect(isHOG)
if isHOG:
isHOG = not isHOG
detect(isHOG)
2. Dos comparaciones de detección de puntos clave de rostros
Los dos tipos principales incluyen: 5 puntos clave y 68 puntos clave. Ambos necesitan llamar al modelo.
2.1 Hora
68Hitos |
5Hitos |
0.011994600296020508s |
0.0030002593994140625s |
2.2 Efecto de rendimiento
5 puntos de referencia
68 puntos de referencia
2.3 Código
El código aquí se refiere principalmente al primer enlace, ejecuta los dos métodos respectivamente y luego guarda los resultados en ./results/landmarks/:
# encoding:utf-8
import dlib
import numpy as np
import cv2
import os
import time
def rect_to_bb(rect): # 获得人脸矩形的坐标信息
x = rect.left()
y = rect.top()
w = rect.right() - x
h = rect.bottom() - y
return (x, y, w, h)
def shape_to_np(shape, is68Landmarks=True, dtype="int"): # 将包含68个特征的的shape转换为numpy array格式
if is68Landmarks:
landmarkNum = 68
else:
landmarkNum = 5
coords = np.zeros((landmarkNum, 2), dtype=dtype)
for i in range(0, landmarkNum):
coords[i] = (shape.part(i).x, shape.part(i).y)
return coords
def resize(image, width=1200): # 将待检测的image进行resize
r = width * 1.0 / image.shape[1]
dim = (width, int(image.shape[0] * r))
resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
return resized
def feature(is68Landmarks=True):
image_path = "./data/"
image_file = "test_1988.jpg"
detector = dlib.get_frontal_face_detector()
if is68Landmarks:
predictor = dlib.shape_predictor("./models/shape_predictor_68_face_landmarks.dat")
else:
predictor = dlib.shape_predictor("./models/shape_predictor_5_face_landmarks.dat")
image = cv2.imread(image_path + image_file)
image = resize(image, width=1200)# 1200
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
rects = detector(gray, 1)
shapes = []
startTime = time.time()
for (i, rect) in enumerate(rects):
shape = predictor(gray, rect)
shape = shape_to_np(shape, is68Landmarks)
shapes.append(shape)
(x, y, w, h) = rect_to_bb(rect)
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(image, "Face: {}".format(i + 1), (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
print("{} method, detect spend {}s ".format(("68Landmarks" if is68Landmarks else "5Landmarks"), time.time()-startTime))
for shape in shapes:
for (x, y) in shape:
cv2.circle(image, (x, y), 2, (0, 0, 255), -1)
cv2.imshow("Output", image)
savePath = "./results/landmarks/"
if not os.path.exists(savePath):
os.makedirs(savePath)
if is68Landmarks:
saveName = image_file[:-4] + "_68Landmarks.jpg"
else:
saveName = image_file[:-4] + "_5Landmarks.jpg"
cv2.imwrite(savePath + saveName, image)
cv2.waitKey(10)
if __name__ == "__main__":
is68Landmarks = True
feature(is68Landmarks)
if is68Landmarks:
is68Landmarks = not is68Landmarks
feature(is68Landmarks)
3. Alineación facial
Tuve que probar los dos métodos aquí, pero los 5 puntos clave no parecían ser fáciles de cambiar, así que me di por vencido, pero el código de referencia todavía está en él y puede eliminarlo usted mismo.
3.1 Hora
Alineación |
0.04295229911804199s |
3.2 Efecto
Dado que la imagen es demasiado vaga, elija algunas:
3.3 Código
Los puntos clave aquí se basan en:
Los resultados se guardarán en ./results/alignment/:
# encoding:utf-8
import dlib
import cv2
import numpy as np
import math
import os
import time
def rect_to_bb(rect): # 获得人脸矩形的坐标信息
x = rect.left()
y = rect.top()
w = rect.right() - x
h = rect.bottom() - y
return (x, y, w, h)
def resize(image, width=1200): # 将待检测的image进行resize
r = width * 1.0 / image.shape[1]
dim = (width, int(image.shape[0] * r))
resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
return resized
def face_alignment_68(faces):
# 使用68点关键点模型,根据关键点信息求解变换矩阵,然后把变换矩阵应用到整个图像上。
predictor = dlib.shape_predictor("./models/shape_predictor_68_face_landmarks.dat") # 用来预测关键点
faces_aligned = []
global startTime
startTime = time.time()
for face in faces:
rec = dlib.rectangle(0,0,face.shape[0],face.shape[1])
shape = predictor(np.uint8(face),rec) # 注意输入的必须是uint8类型
order = [36,45,30,48,54] # left eye, right eye, nose, left mouth, right mouth 注意关键点的顺序,这个在网上可以找
for j in order:
x = shape.part(j).x
y = shape.part(j).y
cv2.circle(face, (x, y), 2, (0, 0, 255), -1)
eye_center =((shape.part(36).x + shape.part(45).x) * 1./2, # 计算两眼的中心坐标
(shape.part(36).y + shape.part(45).y) * 1./2)
dx = (shape.part(45).x - shape.part(36).x) # note: right - right
dy = (shape.part(45).y - shape.part(36).y)
angle = math.atan2(dy,dx) * 180. / math.pi # 计算角度
RotateMatrix = cv2.getRotationMatrix2D(eye_center, angle, scale=1) # 计算仿射矩阵
RotImg = cv2.warpAffine(face, RotateMatrix, (face.shape[0], face.shape[1])) # 进行仿射变换,即旋转
faces_aligned.append(RotImg)
return faces_aligned
def face_alignment_5(rgb_img, faces):
startTime = time.time()
faces_aligned = []
for face in faces:
# RotImg = dlib.get_face_chip(rgb_img, face)
RotImg = dlib.get_face_chip(np.uint8(rgb_img), np.uint8(face))
# RotImg = dlib.get_face_chip(rgb_img, face, size=224, padding=0.25)
faces_aligned.append(RotImg)
return faces_aligned
def demo(isAlignment_5=True):
image_path = "./data/"
image_file = "test_1988.jpg"
im_raw = cv2.imread(image_path + image_file).astype('uint8')
# detector = dlib.get_frontal_face_detector()
model_path = "./models/mmod_human_face_detector.dat" # 基于 Maximum-Margin Object Detector 的深度学习人脸检测方案
detector = dlib.cnn_face_detection_model_v1(model_path)
im_raw = resize(im_raw, width=1200)
gray = cv2.cvtColor(im_raw, cv2.COLOR_BGR2GRAY)
rects = detector(gray, 1)
src_faces = []
for (i, rect) in enumerate(rects):
(x, y, w, h) = rect_to_bb(rect.rect)
detect_face = im_raw[y:y+h,x:x+w]
src_faces.append(detect_face)
cv2.rectangle(im_raw, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(im_raw, "Face: {}".format(i + 1), (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
if isAlignment_5:
faces_aligned = face_alignment_5(im_raw, src_faces)
else:
faces_aligned = face_alignment_68(src_faces)
print("{} method, detect spend {}s ".format(("Alignment_5" if isAlignment_5 else "Alignment_68"), time.time()-startTime))
cv2.imshow("src", im_raw)
savePath = "./results/alignment/"
if not os.path.exists(savePath):
os.makedirs(savePath)
if isAlignment_5:
saveName = "_Align5.jpg"
else:
saveName = "_Align68.jpg"
i = 0
for face in faces_aligned:
cv2.imshow("det_{}".format(i), face)
cv2.imwrite(savePath + image_file[:-4] + "_{}".format(i) + saveName, face)
i = i + 1
cv2.waitKey(10)
if __name__ == "__main__":
isAlignment_5 = False
demo(isAlignment_5)
if isAlignment_5:
isAlignment_5 = not isAlignment_5
demo(isAlignment_5)
4. Reconocimiento facial
Este lugar pasa mucho tiempo, principalmente cuando el reconocimiento no es bueno, no me hundí el corazón para analizar el código, aquí se modifica de acuerdo al código en la referencia uno, no es necesario configurar manualmente la lista de candidatos, solo necesitamos para establecer las caras de los candidatos nosotros mismos. La biblioteca de candidatos de la carpeta lleva el nombre de la persona que se puede distinguir.
4.1 Proceso de preparación
(1) Candidatos-caras en la base de datos de candidatos, vamos a esta base de datos para consultar, cuáles son conocidas y tienen la identidad correcta.
(2) Asignación de nombres de las caras de los candidatos:
(3) Caras a consultar:
(4) Resultados
Processing file: ./data/candidate-faces\liushishi.jpg
Number of faces detected: 1
Processing file: ./data/candidate-faces\liuyifei.jpg
Number of faces detected: 1
Processing file: ./data/candidate-faces\tangyan.jpg
Number of faces detected: 1
Processing file: ./data/candidate-faces\tongliya.jpg
Number of faces detected: 1
Processing file: ./data/candidate-faces\yangzi.jpg
Number of faces detected: 1
Processing file: ./data/candidate-faces\zhaoliying.jpg
Number of faces detected: 1
c_d :[('tangyan', 0.45614611065543303), ('liushishi', 0.4777414300544273), ('yangzi', 0.520176500668875), ('tongliya', 0.547071465533885), ('zhaoliying', 0.64414064895386), ('liuyifei', 0.669962308077882)]
The person_test--./data/faces/tangyan.jpg is: tangyan
c_d :[('zhaoliying', 0.4041512584817519), ('liushishi', 0.4681194204229278), ('tangyan', 0.4728928349513442), ('yangzi', 0.47474913579746303), ('tongliya', 0.5446001882500634), ('liuyifei', 0.6104574640831666)]
The person_test--./data/faces/zhaoliying.jpg is: zhaoliying
4.2 Código
Los resultados se guardarán en el archivo ./results/recongnition/recognition_reslut.txt.
# encoding:utf-8
import dlib
import cv2
import numpy as np
import os, glob
def resize(image, width=1200): # 将待检测的image进行resize
r = width * 1.0 / image.shape[1]
dim = (width, int(image.shape[0] * r))
resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
return resized
def rect_to_bb(rect): # 获得人脸矩形的坐标信息
x = rect.left()
y = rect.top()
w = rect.right() - x
h = rect.bottom() - y
return (x, y, w, h)
def create_face_space():
# 对文件夹下的每一个人脸进行:
# 1.人脸检测
# 2.关键点检测
# 3.描述子提取
# 候选人脸文件夹
faces_folder_path = "./data/candidate-faces/"
# 候选人脸描述子list
descriptors = []
candidates = []
for f in glob.glob(os.path.join(faces_folder_path, "*.jpg")):
print("Processing file: {}".format(f))
img = cv2.imread(f)
# img = resize(img, width=300)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 1.人脸检测
dets = detector(img, 1)
print("Number of faces detected: {}".format(len(dets)))
candidate = f.split('\\')[-1][:-4]
for k, d in enumerate(dets):
# 2.关键点检测
shape = sp(img, d)
# 3.描述子提取,128D向量
face_descriptor = facerec.compute_face_descriptor(img, shape)
# 转换为numpy array
v = np.array(face_descriptor)
descriptors.append(v)
candidates.append(candidate)
return descriptors, candidates
def predict(descriptors, path):
# 对需识别人脸进行同样处理
# 提取描述子
img = cv2.imread(path)
# img = io.imread(path)
# img = resize(img, width=300)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
dets = detector(gray, 1)
dist = []
if len(dets) == 0:
pass
for k, d in enumerate(dets):
shape = sp(img, d)
face_descriptor = facerec.compute_face_descriptor(img, shape)
d_test = np.array(face_descriptor)
# 计算欧式距离
for i in descriptors:
dist_ = np.linalg.norm(i-d_test)
dist.append(dist_)
# print(dist)
return dist
def demo():
global detector, sp, facerec
# 加载正脸检测器
detector = dlib.get_frontal_face_detector()
# 加载人脸关键点检测器
sp = dlib.shape_predictor("./models/shape_predictor_68_face_landmarks.dat")
# 3. 加载人脸识别模型
facerec = dlib.face_recognition_model_v1("./models/dlib_face_recognition_resnet_model_v1.dat")
# 提取候选人特征与候选人名单
descriptors, candidates = create_face_space()
savePath = "./results/recongnition/"
if not os.path.exists(savePath):
os.makedirs(savePath)
fp = open(savePath + 'recognition_reslut.txt', 'a')
predict_path = "./data/faces/*.jpg"
for f in glob.glob(predict_path):
f = f.replace("\\", '/')
# print("f :{}".format(f))
dist = predict(descriptors, f)
# 候选人和距离组成一个dict
c_d = dict(zip(candidates, dist))
if not c_d:
print(str(c_d) + " is None")
continue
cd_sorted = sorted(c_d.items(), key=lambda d:d[1])
print("c_d :{}".format(cd_sorted))
print("The person_test--{} is: ".format(f), cd_sorted[0][0])
fp.write("\nThe person_test--{} is: with similar : {}".format(f, cd_sorted[0][0]))
fp.close()
if __name__ == "__main__":
demo()
referencia
2. [Herramienta] Aprendizaje de la interfaz Dlib e introducción de funciones comunes
4. Detección de puntos clave: leyenda de 68 puntos
5. Dlib extrae puntos de características faciales (68 puntos, dibujo opencv)