人脸特征点检测(二)

╰+攻爆jí腚メ 2022-06-16 14:20 356阅读 0赞

2.Dlib人脸特征点检测

Dlib库是一个集机器学习、计算机视觉、图像处理等众多算法的开源库,其代码简洁,注释清晰,支持C++和Python接口,库中很多头文件可以直接放在C++应用中。Dlib实现了2014年一篇非常经典的人脸特征点检测的论文:Face Alignment at 3000 FPS via Regression Local Binary Features,其人脸特征点检测又快又准。

这里写图片描述

这里不探讨dlib库的编译问题,请自行编译。使用Dlib库进行人脸特征点检测十分简单,可以参考官网的examples,下面是画出人脸特征点的python脚本和效果图。

  1. # coding: utf-8
  2. import cv2
  3. import dlib
  4. #draw_all_landmarks_id
  5. detector = dlib.get_frontal_face_detector()
  6. #predictor = dlib.shape_predictor('/home/tanhui/notebook/shape_predictor_68_face_landmarks.dat')
  7. predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
  8. img = cv2.imread('test.jpg')
  9. img_out = img.copy()
  10. dets = detector(img,0) #dlib人脸检测
  11. print dets[0]
  12. for i,d in enumerate(dets):
  13. cv2.rectangle(img_out,(d.left(),d.top()),(d.right(),d.bottom()),(0,255,0),3)
  14. shape = predictor(img,d) #dlib人脸特征点检测
  15. for k in range(0,68): #68个特征点
  16. cv2.circle(img_out,(shape.part(k).x,shape.part(k).y),2,(255,0,0),-1) #-1表示填充
  17. #cv2.putText(img_out,'%d' % k,(shape.part(k).x,shape.part(k).y),cv2.FONT_HERSHEY_SIMPLEX,0.4,(0,0,255),1) #标记点号
  18. print (shape.part(k).x,shape.part(k).y)
  19. cv2.imwrite('face_landmarks.jpg',img_out)
  20. print 'success'
  21. cv2.imshow('landmarks',img_out)
  22. cv2.waitKey(0)
  23. cv2.destroyAllWindows()

这里写图片描述
这里写图片描述

下面是用opencv调用摄像头、Dlib进行摄像头视频实时检测人脸和特征点python脚本。摄像头分辨率为640x480,在我的机器上(i7 6700K CPU @ 4.00GHz)测试人脸检测平均耗时44ms,人脸特征点检测平均耗时3ms。如果摄像头中人脸总是比较大(离镜头比较近),完全可以对图像下采样之后进行人脸检测,速度会提升很多,例如下采样一倍时,人脸检测平均耗时降低到11ms,因此在某些场景下达到实时检测也是完全可以的。

  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Thu Apr 06 20:52:04 2017
  4. @author: Administrator
  5. """
  6. import dlib
  7. import cv2
  8. import time
  9. detector = dlib.get_frontal_face_detector()
  10. predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
  11. def find_face_landmarks(img):
  12. time0 = time.time()
  13. points = []
  14. rects = detector(img,0)
  15. time1 = time.time()
  16. print (time1 - time0)*1000,'ms'
  17. if len(rects) == 0:
  18. return [],points
  19. shape = predictor(img,rects[0])
  20. time2 = time.time()
  21. print (time2 - time1)*1000,'ms'
  22. for i in range(0,68):
  23. points.append((shape.part(i).x,shape.part(i).y))
  24. return rects[0],points
  25. def draw_face_landmarks(img,rect,landmarks):
  26. img_dst = img.copy()
  27. cv2.rectangle(img_dst,(rect.left(),rect.top()),(rect.right(),rect.bottom()),(255,0,0),2)
  28. for i in range(0,68):
  29. cv2.circle(img_dst,points[i],2,(0,0,255),-1) #-1表示填充
  30. return img_dst
  31. video = cv2.VideoCapture(0)
  32. if video.isOpened():
  33. print 'width: %d' % video.get(cv2.CAP_PROP_FRAME_WIDTH)
  34. print 'height: %d' % video.get(cv2.CAP_PROP_FRAME_HEIGHT)
  35. success,frame = video.read()
  36. while success:
  37. rect,points = find_face_landmarks(frame)
  38. if not rect:
  39. success,frame = video.read()
  40. continue
  41. img = draw_face_landmarks(frame,rect,points)
  42. cv2.imshow('face_landmarks',img)
  43. if cv2.waitKey(1) > 0:
  44. break
  45. success,frame = video.read()
  46. video.release()
  47. cv2.destroyAllWindows()

3.libfacedetect人脸特征点检测

libfacedetect是深圳大学于仕祺老师提供的免费的人脸检测库,以二进制的方式免费发布可商用,可将这个库应用到系统中,无论是科研目的还是商业目的,无任何限制。该库调用非常简单,只有一个函数,纯C语言编译而成,不依赖任何第三方库。libfacedetect只提供了C++接口,其提供了四套接口,分别为frontal、frontal_surveillance、multiview、multiview_reinforce,其中multiview_reinforce效果最好,可以检测侧脸,速度比其它稍慢。
libfacedetect人脸检测和特征点检测的速度奇快,非常好用,对侧脸检测也有很好的效果。测试了一张500x750大小的图像,如果最小检测脸设置为48时,人脸检测和特征点检测总共耗时7ms左右。它和opencv一样,将灰度化的图像作为输入,且对灰度图做直方图均衡化可以改善极端情况下的检测。
在于仕祺老师的github主页上有libfacedetect库 github 里面也提供了examples,下面是修改后的代码。

  1. /*
  2. The MIT License (MIT)
  3. Copyright (c) 2015-2017 Shiqi Yu
  4. shiqi.yu@gmail.com
  5. Permission is hereby granted, free of charge, to any person obtaining a copy
  6. of this software and associated documentation files (the "Software"), to deal
  7. in the Software without restriction, including without limitation the rights
  8. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. copies of the Software, and to permit persons to whom the Software is
  10. furnished to do so, subject to the following conditions:
  11. The above copyright notice and this permission notice shall be included in all
  12. copies or substantial portions of the Software.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  19. SOFTWARE.
  20. */
  21. #include <stdio.h>
  22. #include <opencv2/opencv.hpp>
  23. #include "facedetect-dll.h"
  24. #include "time.h"
  25. using namespace std;
  26. //#pragma comment(lib,"libfacedetect.lib")
  27. #pragma comment(lib,"libfacedetect-x64.lib")
  28. //define the buffer size. Do not change the size!
  29. #define DETECT_BUFFER_SIZE 0x20000
  30. using namespace cv;
  31. int main()
  32. {
  33. //load an image and convert it to gray (single-channel)
  34. Mat image = imread("C:\\Users\\Administrator\\Desktop\\faces\\39649a2f070828388e658cb3ba99a9014d08f1cc.jpg");
  35. Mat gray;
  36. cvtColor(image, gray, CV_BGR2GRAY);
  37. clock_t start_t, end_t;
  38. start_t = clock();
  39. int * pResults = NULL;
  40. //pBuffer is used in the detection functions.
  41. //If you call functions in multiple threads, please create one buffer for each thread!
  42. unsigned char * pBuffer = (unsigned char *)malloc(DETECT_BUFFER_SIZE);
  43. if (!pBuffer)
  44. {
  45. fprintf(stderr, "Can not alloc buffer.\n");
  46. return -1;
  47. }
  48. int doLandmark = 1;
  49. ///////////////////////////////////////////
  50. // frontal face detection / 68 landmark detection
  51. // it's fast, but cannot detect side view faces
  52. //////////////////////////////////////////
  53. //!!! The input image must be a gray one (single-channel)
  54. //!!! DO NOT RELEASE pResults !!!
  55. pResults = facedetect_frontal(pBuffer, (unsigned char*)(gray.ptr(0)), gray.cols, gray.rows, (int)gray.step,
  56. 1.2f, 2, 48, 0, doLandmark);
  57. end_t = clock();
  58. cout << (double)(end_t - start_t) / CLOCKS_PER_SEC << "s" << endl;
  59. cout << gray.cols << "," << gray.rows << endl;
  60. printf("%d faces detected.\n", (pResults ? *pResults : 0));
  61. Mat result_frontal = image.clone();
  62. //print the detection results
  63. for (int i = 0; i < (pResults ? *pResults : 0); i++)
  64. {
  65. short * p = ((short*)(pResults + 1)) + 142 * i;
  66. int x = p[0];
  67. int y = p[1];
  68. int w = p[2];
  69. int h = p[3];
  70. int neighbors = p[4];
  71. int angle = p[5];
  72. printf("face_rect=[%d, %d, %d, %d], neighbors=%d, angle=%d\n", x, y, w, h, neighbors, angle);
  73. rectangle(result_frontal, Rect(x, y, w, h), Scalar(0, 255, 0), 2);
  74. if (doLandmark)
  75. {
  76. for (int j = 0; j < 68; j++)
  77. circle(result_frontal, Point((int)p[6 + 2 * j], (int)p[6 + 2 * j + 1]), 1, Scalar(0, 255, 0));
  78. }
  79. }
  80. imshow("Results_frontal", result_frontal);
  81. /////////////////////////////////////////////
  82. //// frontal face detection designed for video surveillance / 68 landmark detection
  83. //// it can detect faces with bad illumination.
  84. ////////////////////////////////////////////
  85. ////!!! the input image must be a gray one (single-channel)
  86. ////!!! do not release presults !!!
  87. //presults = facedetect_frontal_surveillance(pbuffer, (unsigned char*)(gray.ptr(0)), gray.cols, gray.rows, (int)gray.step,
  88. // 1.2f, 2, 48, 0, dolandmark);
  89. //printf("%d faces detected.\n", (presults ? *presults : 0));
  90. //mat result_frontal_surveillance = image.clone();;
  91. ////print the detection results
  92. //for (int i = 0; i < (presults ? *presults : 0); i++)
  93. //{
  94. // short * p = ((short*)(presults + 1)) + 142 * i;
  95. // int x = p[0];
  96. // int y = p[1];
  97. // int w = p[2];
  98. // int h = p[3];
  99. // int neighbors = p[4];
  100. // int angle = p[5];
  101. // printf("face_rect=[%d, %d, %d, %d], neighbors=%d, angle=%d\n", x, y, w, h, neighbors, angle);
  102. // rectangle(result_frontal_surveillance, rect(x, y, w, h), scalar(0, 255, 0), 2);
  103. // if (dolandmark)
  104. // {
  105. // for (int j = 0; j < 68; j++)
  106. // circle(result_frontal_surveillance, point((int)p[6 + 2 * j], (int)p[6 + 2 * j + 1]), 1, scalar(0, 255, 0));
  107. // }
  108. //}
  109. //imshow("results_frontal_surveillance", result_frontal_surveillance);
  110. /////////////////////////////////////////////
  111. //// multiview face detection / 68 landmark detection
  112. //// it can detect side view faces, but slower than facedetect_frontal().
  113. ////////////////////////////////////////////
  114. ////!!! the input image must be a gray one (single-channel)
  115. ////!!! do not release presults !!!
  116. //presults = facedetect_multiview(pbuffer, (unsigned char*)(gray.ptr(0)), gray.cols, gray.rows, (int)gray.step,
  117. // 1.2f, 2, 48, 0, dolandmark);
  118. //printf("%d faces detected.\n", (presults ? *presults : 0));
  119. //mat result_multiview = image.clone();;
  120. ////print the detection results
  121. //for (int i = 0; i < (presults ? *presults : 0); i++)
  122. //{
  123. // short * p = ((short*)(presults + 1)) + 142 * i;
  124. // int x = p[0];
  125. // int y = p[1];
  126. // int w = p[2];
  127. // int h = p[3];
  128. // int neighbors = p[4];
  129. // int angle = p[5];
  130. // printf("face_rect=[%d, %d, %d, %d], neighbors=%d, angle=%d\n", x, y, w, h, neighbors, angle);
  131. // rectangle(result_multiview, rect(x, y, w, h), scalar(0, 255, 0), 2);
  132. // if (dolandmark)
  133. // {
  134. // for (int j = 0; j < 68; j++)
  135. // circle(result_multiview, point((int)p[6 + 2 * j], (int)p[6 + 2 * j + 1]), 1, scalar(0, 255, 0));
  136. // }
  137. //}
  138. //imshow("results_multiview", result_multiview);
  139. /////////////////////////////////////////////
  140. //// reinforced multiview face detection / 68 landmark detection
  141. //// it can detect side view faces, better but slower than facedetect_multiview().
  142. ////////////////////////////////////////////
  143. ////!!! the input image must be a gray one (single-channel)
  144. ////!!! do not release presults !!!
  145. //presults = facedetect_multiview_reinforce(pbuffer, (unsigned char*)(gray.ptr(0)), gray.cols, gray.rows, (int)gray.step,
  146. // 1.2f, 3, 48, 0, dolandmark);
  147. //printf("%d faces detected.\n", (presults ? *presults : 0));
  148. //mat result_multiview_reinforce = image.clone();;
  149. ////print the detection results
  150. //for (int i = 0; i < (presults ? *presults : 0); i++)
  151. //{
  152. // short * p = ((short*)(presults + 1)) + 142 * i;
  153. // int x = p[0];
  154. // int y = p[1];
  155. // int w = p[2];
  156. // int h = p[3];
  157. // int neighbors = p[4];
  158. // int angle = p[5];
  159. // printf("face_rect=[%d, %d, %d, %d], neighbors=%d, angle=%d\n", x, y, w, h, neighbors, angle);
  160. // rectangle(result_multiview_reinforce, rect(x, y, w, h), scalar(0, 255, 0), 2);
  161. // if (dolandmark)
  162. // {
  163. // for (int j = 0; j < 68; j++)
  164. // circle(result_multiview_reinforce, point((int)p[6 + 2 * j], (int)p[6 + 2 * j + 1]), 1, scalar(0, 255, 0));
  165. // }
  166. //}
  167. //imshow("results_multiview_reinforce", result_multiview_reinforce);
  168. waitKey();
  169. //release the buffer
  170. free(pBuffer);
  171. return 0;
  172. }

发表评论

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

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

相关阅读

    相关 人脸特征检测--基于DLIB库

      Dlib是一个C++编写的工具包,它包含了机器学习算法以及一些用来解决现实复杂问题的工具,可以广泛应用于机器人、嵌入式设备、手机,甚至高性能计算中,可以在其官网了解更多。这

    相关 人脸关键检测总结

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