【人脸检测】试用python版本Dlib人脸检测、关键点、对齐、识别

迷南。 2022-12-22 11:25 366阅读 0赞

主要参考两篇:

https://blog.csdn.net/liuxiao214/article/details/83411820

https://www.jianshu.com/p/577af31ced74

0.环境

  1. windows
  2. python3.6
  3. Dlib
  4. numpy==1.14.5
  5. glob
  6. opencv-python==3.4.3.18

安装Dlib参考:https://blog.csdn.net/qq_35975447/article/details/109802787

0.1 文件结构

  1. .gitignore
  2. faceAlignment.py
  3. faceDetect.py
  4. faceLandmarks.py
  5. faceRecognition.py
  6. file.txt
  7. ├─data
  8. test_1988.jpg
  9. ├─candidate-faces
  10. liushishi.jpg
  11. liuyifei.jpg
  12. tangyan.jpg
  13. tongliya.jpg
  14. yangzi.jpg
  15. zhaoliying.jpg
  16. └─faces
  17. tangyan.jpg
  18. zhaoliying.jpg
  19. ├─models
  20. dlib_face_recognition_resnet_model_v1.dat
  21. mmod_human_face_detector.dat
  22. shape_predictor_5_face_landmarks.dat
  23. shape_predictor_68_face_landmarks.dat
  24. └─results
  25. ├─alignment
  26. test_1988_0_Align68.jpg
  27. test_1988_1_Align68.jpg
  28. test_1988_2_Align68.jpg
  29. test_1988_3_Align68.jpg
  30. test_1988_4_Align68.jpg
  31. test_1988_5_Align68.jpg
  32. ├─detect
  33. test_1988_HOG.jpg
  34. test_1988_MMOD.jpg
  35. ├─landmarks
  36. test_1988_5Landmarks.jpg
  37. test_1988_68Landmarks.jpg
  38. └─recongnition
  39. recognition_reslut.txt

0.2 模型下载

https://github.com/davisking/dlib-models

0.3 我的代码

https://download.csdn.net/download/qq_35975447/13129563

1.人脸检测两个方法对比

两种方法主要包括:Dlib自带与调用深度学习模型的方法。

1.1 时间












HOG

MMOD

1.437422513961792s

 

106.82666826248169s

1.2 效果

原图:

20201120111841856.png

HOG效果:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1OTc1NDQ3_size_16_color_FFFFFF_t_70

MMOD效果:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1OTc1NDQ3_size_16_color_FFFFFF_t_70 1

1.2 代码

这里代码主要参考第一个链接中的,然后根据Dlib自带与调用深度学习模型的方法,循环执行测试时间,并保存图片到results/detect/目录下:

  1. # encoding:utf-8
  2. import dlib
  3. import cv2
  4. import os
  5. import time
  6. def rect_to_bb(rect): # 获得人脸矩形的坐标信息
  7. x = rect.left()
  8. y = rect.top()
  9. w = rect.right() - x
  10. h = rect.bottom() - y
  11. return (x, y, w, h)
  12. def resize(image, width=1200): # 将待检测的image进行resize
  13. r = width * 1.0 / image.shape[1]
  14. dim = (width, int(image.shape[0] * r))
  15. resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
  16. return resized
  17. def detect(isHOG=False):
  18. image_path = "./data/"
  19. image_file = "test_1988.jpg"
  20. startTime = time.time()
  21. if isHOG:
  22. detector = dlib.get_frontal_face_detector() # 基于HOG+SVM分类
  23. else:
  24. model_path = "./models/mmod_human_face_detector.dat" # 基于 Maximum-Margin Object Detector 的深度学习人脸检测方案
  25. detector = dlib.cnn_face_detection_model_v1(model_path)
  26. image = cv2.imread(image_path + image_file)
  27. image = resize(image, width=1200)
  28. # image = resize(image, width=600)
  29. gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  30. rects = detector(gray, 1)
  31. print("{} method, detect spend {}s ".format(("HOG" if isHOG else "MMOD"), time.time()-startTime))
  32. for (i, rect) in enumerate(rects):
  33. if isHOG:
  34. (x, y, w, h) = rect_to_bb(rect)
  35. else:
  36. (x, y, w, h) = rect_to_bb(rect.rect)
  37. cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
  38. cv2.putText(image, "Face: {}".format(i + 1), (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
  39. cv2.imshow("Output", image)
  40. savePath = "./results/detect/"
  41. if not os.path.exists(savePath):
  42. os.makedirs(savePath)
  43. if isHOG:
  44. saveName = image_file[:-4] + "_HOG.jpg"
  45. else:
  46. saveName = image_file[:-4] + "_MMOD.jpg"
  47. cv2.imwrite(savePath + saveName, image)
  48. cv2.waitKey(10)
  49. if __name__ == "__main__":
  50. isHOG = True
  51. detect(isHOG)
  52. if isHOG:
  53. isHOG = not isHOG
  54. detect(isHOG)

2.人脸关键点检测两种对比

两种主要包括:5个关键点与68关键点。都需要调用模型。

2.1 时间












68Landmarks

5Landmarks

0.011994600296020508s

0.0030002593994140625s

2.2 性能效果

5个landmarks

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1OTc1NDQ3_size_16_color_FFFFFF_t_70 2

68个landmarks

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1OTc1NDQ3_size_16_color_FFFFFF_t_70 3

2.3 代码

这里代码主要也是参考第一个链接,分别执行两种方法,然后将结果保存至./results/landmarks/下:

  1. # encoding:utf-8
  2. import dlib
  3. import numpy as np
  4. import cv2
  5. import os
  6. import time
  7. def rect_to_bb(rect): # 获得人脸矩形的坐标信息
  8. x = rect.left()
  9. y = rect.top()
  10. w = rect.right() - x
  11. h = rect.bottom() - y
  12. return (x, y, w, h)
  13. def shape_to_np(shape, is68Landmarks=True, dtype="int"): # 将包含68个特征的的shape转换为numpy array格式
  14. if is68Landmarks:
  15. landmarkNum = 68
  16. else:
  17. landmarkNum = 5
  18. coords = np.zeros((landmarkNum, 2), dtype=dtype)
  19. for i in range(0, landmarkNum):
  20. coords[i] = (shape.part(i).x, shape.part(i).y)
  21. return coords
  22. def resize(image, width=1200): # 将待检测的image进行resize
  23. r = width * 1.0 / image.shape[1]
  24. dim = (width, int(image.shape[0] * r))
  25. resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
  26. return resized
  27. def feature(is68Landmarks=True):
  28. image_path = "./data/"
  29. image_file = "test_1988.jpg"
  30. detector = dlib.get_frontal_face_detector()
  31. if is68Landmarks:
  32. predictor = dlib.shape_predictor("./models/shape_predictor_68_face_landmarks.dat")
  33. else:
  34. predictor = dlib.shape_predictor("./models/shape_predictor_5_face_landmarks.dat")
  35. image = cv2.imread(image_path + image_file)
  36. image = resize(image, width=1200)# 1200
  37. gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  38. rects = detector(gray, 1)
  39. shapes = []
  40. startTime = time.time()
  41. for (i, rect) in enumerate(rects):
  42. shape = predictor(gray, rect)
  43. shape = shape_to_np(shape, is68Landmarks)
  44. shapes.append(shape)
  45. (x, y, w, h) = rect_to_bb(rect)
  46. cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
  47. cv2.putText(image, "Face: {}".format(i + 1), (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
  48. print("{} method, detect spend {}s ".format(("68Landmarks" if is68Landmarks else "5Landmarks"), time.time()-startTime))
  49. for shape in shapes:
  50. for (x, y) in shape:
  51. cv2.circle(image, (x, y), 2, (0, 0, 255), -1)
  52. cv2.imshow("Output", image)
  53. savePath = "./results/landmarks/"
  54. if not os.path.exists(savePath):
  55. os.makedirs(savePath)
  56. if is68Landmarks:
  57. saveName = image_file[:-4] + "_68Landmarks.jpg"
  58. else:
  59. saveName = image_file[:-4] + "_5Landmarks.jpg"
  60. cv2.imwrite(savePath + saveName, image)
  61. cv2.waitKey(10)
  62. if __name__ == "__main__":
  63. is68Landmarks = True
  64. feature(is68Landmarks)
  65. if is68Landmarks:
  66. is68Landmarks = not is68Landmarks
  67. feature(is68Landmarks)

3.人脸对齐

本来这里也要测试两种方法的,但是5个关键点的好像不太好改,就放弃了,不过参考代码还是放在里面了,可以自行删去。

3.1 时间










Alignment

0.04295229911804199s

3.2 效果

由于图太模糊了,挑出几张来:

2020112011551833.png20201120115444592.png20201120115453440.png202011201155051.png

3.3 代码

这里的关键点是根据:

在这里插入图片描述

结果会保存至./results/alignment/:

  1. # encoding:utf-8
  2. import dlib
  3. import cv2
  4. import numpy as np
  5. import math
  6. import os
  7. import time
  8. def rect_to_bb(rect): # 获得人脸矩形的坐标信息
  9. x = rect.left()
  10. y = rect.top()
  11. w = rect.right() - x
  12. h = rect.bottom() - y
  13. return (x, y, w, h)
  14. def resize(image, width=1200): # 将待检测的image进行resize
  15. r = width * 1.0 / image.shape[1]
  16. dim = (width, int(image.shape[0] * r))
  17. resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
  18. return resized
  19. def face_alignment_68(faces):
  20. # 使用68点关键点模型,根据关键点信息求解变换矩阵,然后把变换矩阵应用到整个图像上。
  21. predictor = dlib.shape_predictor("./models/shape_predictor_68_face_landmarks.dat") # 用来预测关键点
  22. faces_aligned = []
  23. global startTime
  24. startTime = time.time()
  25. for face in faces:
  26. rec = dlib.rectangle(0,0,face.shape[0],face.shape[1])
  27. shape = predictor(np.uint8(face),rec) # 注意输入的必须是uint8类型
  28. order = [36,45,30,48,54] # left eye, right eye, nose, left mouth, right mouth 注意关键点的顺序,这个在网上可以找
  29. for j in order:
  30. x = shape.part(j).x
  31. y = shape.part(j).y
  32. cv2.circle(face, (x, y), 2, (0, 0, 255), -1)
  33. eye_center =((shape.part(36).x + shape.part(45).x) * 1./2, # 计算两眼的中心坐标
  34. (shape.part(36).y + shape.part(45).y) * 1./2)
  35. dx = (shape.part(45).x - shape.part(36).x) # note: right - right
  36. dy = (shape.part(45).y - shape.part(36).y)
  37. angle = math.atan2(dy,dx) * 180. / math.pi # 计算角度
  38. RotateMatrix = cv2.getRotationMatrix2D(eye_center, angle, scale=1) # 计算仿射矩阵
  39. RotImg = cv2.warpAffine(face, RotateMatrix, (face.shape[0], face.shape[1])) # 进行仿射变换,即旋转
  40. faces_aligned.append(RotImg)
  41. return faces_aligned
  42. def face_alignment_5(rgb_img, faces):
  43. startTime = time.time()
  44. faces_aligned = []
  45. for face in faces:
  46. # RotImg = dlib.get_face_chip(rgb_img, face)
  47. RotImg = dlib.get_face_chip(np.uint8(rgb_img), np.uint8(face))
  48. # RotImg = dlib.get_face_chip(rgb_img, face, size=224, padding=0.25)
  49. faces_aligned.append(RotImg)
  50. return faces_aligned
  51. def demo(isAlignment_5=True):
  52. image_path = "./data/"
  53. image_file = "test_1988.jpg"
  54. im_raw = cv2.imread(image_path + image_file).astype('uint8')
  55. # detector = dlib.get_frontal_face_detector()
  56. model_path = "./models/mmod_human_face_detector.dat" # 基于 Maximum-Margin Object Detector 的深度学习人脸检测方案
  57. detector = dlib.cnn_face_detection_model_v1(model_path)
  58. im_raw = resize(im_raw, width=1200)
  59. gray = cv2.cvtColor(im_raw, cv2.COLOR_BGR2GRAY)
  60. rects = detector(gray, 1)
  61. src_faces = []
  62. for (i, rect) in enumerate(rects):
  63. (x, y, w, h) = rect_to_bb(rect.rect)
  64. detect_face = im_raw[y:y+h,x:x+w]
  65. src_faces.append(detect_face)
  66. cv2.rectangle(im_raw, (x, y), (x + w, y + h), (0, 255, 0), 2)
  67. cv2.putText(im_raw, "Face: {}".format(i + 1), (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
  68. if isAlignment_5:
  69. faces_aligned = face_alignment_5(im_raw, src_faces)
  70. else:
  71. faces_aligned = face_alignment_68(src_faces)
  72. print("{} method, detect spend {}s ".format(("Alignment_5" if isAlignment_5 else "Alignment_68"), time.time()-startTime))
  73. cv2.imshow("src", im_raw)
  74. savePath = "./results/alignment/"
  75. if not os.path.exists(savePath):
  76. os.makedirs(savePath)
  77. if isAlignment_5:
  78. saveName = "_Align5.jpg"
  79. else:
  80. saveName = "_Align68.jpg"
  81. i = 0
  82. for face in faces_aligned:
  83. cv2.imshow("det_{}".format(i), face)
  84. cv2.imwrite(savePath + image_file[:-4] + "_{}".format(i) + saveName, face)
  85. i = i + 1
  86. cv2.waitKey(10)
  87. if __name__ == "__main__":
  88. isAlignment_5 = False
  89. demo(isAlignment_5)
  90. if isAlignment_5:
  91. isAlignment_5 = not isAlignment_5
  92. demo(isAlignment_5)

4.人脸识别

这个地方的时间花的比较多,主要出现识别不好时,没有沉下心来去分析代码,这里根据参考一中的代码进行了修改,无需人为去设置candidate列表,只需要我们自己将candidate-faces文件夹中的候选人库以可区分的该人命名就好。

4.1 准备过程

(1)候选人库candidate-faces,就是我们去这个库查询,是已知的、且有正确身份的。

20201120113653385.pngwatermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1OTc1NDQ3_size_16_color_FFFFFF_t_70 420201120113805459.png2020112011381482.png20201120113851200.png2020112011390471.png

(2)候选人库candidate-faces图片命名:

20201120114012293.png

(3)待查询的faces:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1OTc1NDQ3_size_16_color_FFFFFF_t_70 5tangyan.jpg

zhaoliying.jpg zhaoliying.jpg

(4)结果

  1. Processing file: ./data/candidate-faces\liushishi.jpg
  2. Number of faces detected: 1
  3. Processing file: ./data/candidate-faces\liuyifei.jpg
  4. Number of faces detected: 1
  5. Processing file: ./data/candidate-faces\tangyan.jpg
  6. Number of faces detected: 1
  7. Processing file: ./data/candidate-faces\tongliya.jpg
  8. Number of faces detected: 1
  9. Processing file: ./data/candidate-faces\yangzi.jpg
  10. Number of faces detected: 1
  11. Processing file: ./data/candidate-faces\zhaoliying.jpg
  12. Number of faces detected: 1
  13. c_d :[('tangyan', 0.45614611065543303), ('liushishi', 0.4777414300544273), ('yangzi', 0.520176500668875), ('tongliya', 0.547071465533885), ('zhaoliying', 0.64414064895386), ('liuyifei', 0.669962308077882)]
  14. The person_test--./data/faces/tangyan.jpg is: tangyan
  15. c_d :[('zhaoliying', 0.4041512584817519), ('liushishi', 0.4681194204229278), ('tangyan', 0.4728928349513442), ('yangzi', 0.47474913579746303), ('tongliya', 0.5446001882500634), ('liuyifei', 0.6104574640831666)]
  16. The person_test--./data/faces/zhaoliying.jpg is: zhaoliying

4.2 代码

其中结果会存到./results/recongnition/recognition_reslut.txt文件中。

  1. # encoding:utf-8
  2. import dlib
  3. import cv2
  4. import numpy as np
  5. import os, glob
  6. def resize(image, width=1200): # 将待检测的image进行resize
  7. r = width * 1.0 / image.shape[1]
  8. dim = (width, int(image.shape[0] * r))
  9. resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
  10. return resized
  11. def rect_to_bb(rect): # 获得人脸矩形的坐标信息
  12. x = rect.left()
  13. y = rect.top()
  14. w = rect.right() - x
  15. h = rect.bottom() - y
  16. return (x, y, w, h)
  17. def create_face_space():
  18. # 对文件夹下的每一个人脸进行:
  19. # 1.人脸检测
  20. # 2.关键点检测
  21. # 3.描述子提取
  22. # 候选人脸文件夹
  23. faces_folder_path = "./data/candidate-faces/"
  24. # 候选人脸描述子list
  25. descriptors = []
  26. candidates = []
  27. for f in glob.glob(os.path.join(faces_folder_path, "*.jpg")):
  28. print("Processing file: {}".format(f))
  29. img = cv2.imread(f)
  30. # img = resize(img, width=300)
  31. img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  32. # 1.人脸检测
  33. dets = detector(img, 1)
  34. print("Number of faces detected: {}".format(len(dets)))
  35. candidate = f.split('\\')[-1][:-4]
  36. for k, d in enumerate(dets):
  37. # 2.关键点检测
  38. shape = sp(img, d)
  39. # 3.描述子提取,128D向量
  40. face_descriptor = facerec.compute_face_descriptor(img, shape)
  41. # 转换为numpy array
  42. v = np.array(face_descriptor)
  43. descriptors.append(v)
  44. candidates.append(candidate)
  45. return descriptors, candidates
  46. def predict(descriptors, path):
  47. # 对需识别人脸进行同样处理
  48. # 提取描述子
  49. img = cv2.imread(path)
  50. # img = io.imread(path)
  51. # img = resize(img, width=300)
  52. gray = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  53. dets = detector(gray, 1)
  54. dist = []
  55. if len(dets) == 0:
  56. pass
  57. for k, d in enumerate(dets):
  58. shape = sp(img, d)
  59. face_descriptor = facerec.compute_face_descriptor(img, shape)
  60. d_test = np.array(face_descriptor)
  61. # 计算欧式距离
  62. for i in descriptors:
  63. dist_ = np.linalg.norm(i-d_test)
  64. dist.append(dist_)
  65. # print(dist)
  66. return dist
  67. def demo():
  68. global detector, sp, facerec
  69. # 加载正脸检测器
  70. detector = dlib.get_frontal_face_detector()
  71. # 加载人脸关键点检测器
  72. sp = dlib.shape_predictor("./models/shape_predictor_68_face_landmarks.dat")
  73. # 3. 加载人脸识别模型
  74. facerec = dlib.face_recognition_model_v1("./models/dlib_face_recognition_resnet_model_v1.dat")
  75. # 提取候选人特征与候选人名单
  76. descriptors, candidates = create_face_space()
  77. savePath = "./results/recongnition/"
  78. if not os.path.exists(savePath):
  79. os.makedirs(savePath)
  80. fp = open(savePath + 'recognition_reslut.txt', 'a')
  81. predict_path = "./data/faces/*.jpg"
  82. for f in glob.glob(predict_path):
  83. f = f.replace("\\", '/')
  84. # print("f :{}".format(f))
  85. dist = predict(descriptors, f)
  86. # 候选人和距离组成一个dict
  87. c_d = dict(zip(candidates, dist))
  88. if not c_d:
  89. print(str(c_d) + " is None")
  90. continue
  91. cd_sorted = sorted(c_d.items(), key=lambda d:d[1])
  92. print("c_d :{}".format(cd_sorted))
  93. print("The person_test--{} is: ".format(f), cd_sorted[0][0])
  94. fp.write("\nThe person_test--{} is: with similar : {}".format(f, cd_sorted[0][0]))
  95. fp.close()
  96. if __name__ == "__main__":
  97. demo()

参考

1.【Dlib】人脸检测、特征点检测、人脸对齐、人脸识别

2.【Tool】Dlib 接口学习和常见功能介绍

3.dlib-models

4.关键点检测——68点图例

5.Dlib提取人脸特征点(68点,opencv画图)

发表评论

表情:
评论列表 (有 0 条评论,366人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Python实现人脸关键检测

    Python实现人脸关键点检测 人脸关键点是人脸识别、表情识别、虚拟化妆等应用的基础。本文将介绍如何使用Python实现人脸关键点检测。 首先,我们需要安装dlib和Ope

    相关 人脸识别系统_人脸检测

    项目:基于人脸识别的无卡ATM机模拟系统 主要实现内容: 包括实现AMT机模拟人脸识别和密码输入、PC端模拟实现储户数据库服务器系统。 1. ATM模拟端实现采用手

    相关 人脸关键检测总结

    概述 人脸关键点检测也称为人脸关键点检测、定位或者人脸对齐,是指给定人脸图像,定位出人脸面部的关键区域位置,包括眉毛、眼睛、鼻子、嘴巴、脸部轮廓等。 人脸关键点检测方法