使用opencv和dlib库(C++代码)实现人脸活体检测(眨眼、张嘴、摇头检测)

这篇具有很好参考价值的文章主要介绍了使用opencv和dlib库(C++代码)实现人脸活体检测(眨眼、张嘴、摇头检测)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

  • 本文章使用opencv和dlib库,使用C++代码实现了人脸活体检测,包括眨眼检测、张嘴检测以及摇头检测,可以对静态图片和活体进行有效区分。

效果展示

  • opencv点头检测,安全,opencv,c++,目标检测,视觉检测

Dlib库介绍

  • dlib是一个开源的C++机器学习库,它提供了一系列用于图像处理、人脸检测、人脸识别、物体检测、图像标注等功能的算法和工具。dlib库使用了现代C++和模板元编程的技术,并且具有高度的可移植性和可扩展性。

  • dlib库的主要特点包括:

    • 提供了一系列高效的机器学习算法,如支持向量机、最大间隔分类器、随机森林等。
    • 提供了用于图像处理的算法,如图像滤波、图像变换、边缘检测等。
    • 提供了用于人脸检测和人脸识别的算法,具有较高的准确性和性能。
    • 提供了用于物体检测和跟踪的算法,如HOG特征和级联分类器。
    • 提供了用于图像标注和图像分割的算法,如条件随机场。
    • 支持多线程和并行计算,可以充分利用多核处理器的性能。
    • 具有丰富的文档和示例代码,易于学习和使用。
  • dlib库在计算机视觉、模式识别和机器学习领域被广泛应用,是一个功能强大且易用的机器学习库。对外提供了C++和python两种接口。文章来源地址https://www.toymoban.com/news/detail-851513.html

OpenCV库介绍

  • OpenCV是一个基于BSD许可发行的跨平台计算机视觉库。OpenCV作为较大众的开源库,拥有了丰富的常用图像处理函数库,采用C/C++语言编写,可以运行在Linux/Windows/Mac等操作系统上,能够快速的实现一些图像处理和识别的任务。
  • 本项目主要使用OpenCV来打开摄像头,读取视频帧。

人脸识别

  • Dlib库中有一个人脸特征点模型 shape_predictor_68_face_landmarks.dat,记录了人脸的68个特征点。可以通过这个模型识别人脸特征从而检测是否检测到人脸。
  • 人脸特征点opencv点头检测,安全,opencv,c++,目标检测,视觉检测

眨眼检测原理

  • 通过计算人眼纵横比(EAR),可以判断眼睛是张开还是闭合,从而判断是否眨眼。
  • opencv点头检测,安全,opencv,c++,目标检测,视觉检测 E A R = ∥ p 2 − p 6 ∥ + ∥ p 3 − p 5 ∥ 2 ∥ p 1 − p 4 ∥ EAR=\frac{\|p2-p6\| + \|p3-p5\|}{ 2\|p1-p4\|} EAR=2∥p1p4∥p2p6∥+p3p5∥
  • 分子计算的是眼睛的特征点在垂直方向上的距离,分母计算的是眼睛的特征点在水平方向上的距离,由于水平特征点只有一组,所以乘以2保证两组特征点的权重相同。
  • 眼睛闭合时,p2和p6、p3和p5之间的距离会减小,而p1和p4之间的距离基本保持不变。因此通过计算人眼纵横比EAR,可以判断眼睛的睁开和闭合状态。

张嘴检测原理

  • 张嘴检测的原理与眨眼检测一样,嘴部的特征点较多,可以自行选取六个特征点,计算嘴部的纵横比MAR
  • opencv点头检测,安全,opencv,c++,目标检测,视觉检测
  • 我这里选取的六个特征点是 49,55、51,59、53,57
  • 按照相同的方法,计算人嘴纵横比 MAR

摇头检测

  • 摇头时,鼻子中心点到左右脸颊的距离会发生变化,我们可以通过计算该距离变化,判断是否进行了摇头。
  • 比如通过计算鼻子中心点特征点31到左脸颊特征点2和右脸颊特征点16的距离变化,判断摇头动作。具体参考源代码。

Dlib和OpenCV库编译

  • 编译前需要安装Visual Studio 2015和CMake。
  • Dlib库编译
    • Dlib库下载地址。可以选择这个包下载 dlib-19.24.zip,同时需要下载这个人脸关键点检测器 shape_predictor_68_face_landmarks.dat
    • 源码下载后,需要进行编译。
    • 先在Dlib源码工程下 dlib/config.h文件末尾添加下面这一句
      •   #define DLIB__CMAKE_GENERATED_A_CONFIG_H_FILE
        
    • 然后在Dlib源码工程下,创建build_x86文件夹,进入该文件夹,执行命令
      •   cmake -G "Visual Studio 14 2015" ..
          cmake --build ./ --config Release
        
    • 编译完成后,会在build_x86\dlib\Release下生成静态库文件 dlib19.24.0_release_32bit_msvc1900.lib
  • OpenCV库编译
    • openCV库下载地址。选择一个版本的源码(Sources)进行下载,我下载的是4.5.0
    • 源码下载后,需要进行编译。在OpenCV源码工程下,创建build_x86文件夹,进入该文件夹,执行命令
      •   cmake -G "Visual Studio 14 2015" ..
          cmake --build ./ --config Release
        
    • 编译完成后,会在build_x86/lib/Release下生成静态库文件,会在build_x86/bin/Release下生成动态库文件。

创建工程

  • 先创建一个facec目录
  • 在facec目录下创建一个dlib-19.24目录,将dlib源码中的dlib目录拷贝到该目录下
  • 在facec目录下创建一个opencv-4.5.0目录,将opecv源码中的include和modules目录拷贝到该目录下
  • 在facec目录下创建一个lib目录,将编译好的dlib静态库和opencv静态库拷贝到该目录下。
  • 在facec目录下创建一个src目录,src目录下为main.cpp源代码。
  • 在facec目录下创建一个CMakeLists.txt文件。
  • 目录结构如下
  •   facec
      	├── dlib-19.24
      	│ 		└── dlib
      	├── opencv-4.5.0
      	│ 		├── include
      	│ 		└── modules
      	├── lib
      	├── src
      	│ 	└── main.cpp
      	└──CMakeLists.txt
    

编译工程

  • 在facec目录创建build_x86目录,进入该目录执行
  •   cmake -G "Visual Studio 14 2015" ..
      cmake --build ./ --config Release
    
  • 会在 bin\Release 下生成可执行程序,然后将opencv相关动态库和人脸关键点检测器shape_predictor_68_face_landmarks.dat拷贝过来,双击可执行程序就可以运行了。

相关源代码

  • main.cpp源代码
  •   #include <dlib/opencv.h>
      #include <dlib/image_processing/frontal_face_detector.h>
      #include <dlib/image_processing/render_face_detections.h>
      #include <dlib/image_processing.h>
      #include <dlib/gui_widgets.h>
      #include <stdio.h>
      #include <opencv2/opencv.hpp>
      
      using namespace dlib;
      using namespace std;
      
      int main()
      {
          try
          {
      		// 打开摄像头
              cv::VideoCapture cap(0, cv::CAP_DSHOW);
              if (!cap.isOpened())
              {
                  printf("open VideoCapture failed.\n");
                  return 1;
              }
      
      		printf("open VideoCapture success.\n");
      
              image_window win;
      
              // Load face detection and pose estimation models.
              frontal_face_detector detector = get_frontal_face_detector();
              shape_predictor pose_model;
              deserialize("shape_predictor_68_face_landmarks.dat") >> pose_model;
      
      		static int mouthIndex = 0;
      		static int leyeIndex = 0;
      		static int reyeIndex = 0;
      
      		int counter_mouth = 0;
      		int counter_leye = 0;
      		int counter_reye = 0;
      
              // Grab and process frames until the main window is closed by the user.
              while(!win.is_closed())
              {
                  // Grab a frame
                  cv::Mat frame;
                  if (!cap.read(frame))
                  {
                      break;
                  }
      
                  cv_image<bgr_pixel> cimg(frame);
      
      			// 保存图片
      			cv::Mat imgPng = dlib::toMat(cimg);
      			cv::imwrite("face.png", imgPng);
      
                  // Detect faces 
                  std::vector<rectangle> faces = detector(cimg);
                  // Find the pose of each face.
                  std::vector<full_object_detection> shapes;
      
      			printf("faces number is %d\n", faces.size());
      
      			for (unsigned long i = 0; i < faces.size(); ++i) {
      				shapes.push_back(pose_model(cimg, faces[i]));
      
      				//计算人眼纵横比
      				//左眼
      				dlib::point leyeLeft = shapes.at(i).part(37);
      				dlib::point leyeRight = shapes.at(i).part(40);
      
      				dlib::point leyeLeftUp = shapes.at(i).part(38);
      				dlib::point leyeLeftDowm = shapes.at(i).part(42);
      		
      				dlib::point leyeRightUp = shapes.at(i).part(39);
      				dlib::point leyeRightDowm = shapes.at(i).part(41);
      
      				float leyeA = sqrt(pow(leyeLeftUp.x() - leyeLeftDowm.x(), 2) + pow(leyeLeftUp.y() - leyeLeftDowm.y(), 2));
      				float leyeB = sqrt(pow(leyeRightUp.x() - leyeRightDowm.x(), 2) + pow(leyeRightUp.y() - leyeRightDowm.y(), 2));
      				float leyeC = sqrt(pow(leyeLeft.x() - leyeRight.x(), 2) + pow(leyeLeft.y() - leyeRight.y(), 2));
      
      				float leyeEVR = (leyeA + leyeB) / (2 * leyeC);
      
      				//右眼
      				dlib::point reyeLeft = shapes.at(i).part(43);
      				dlib::point reyeRight = shapes.at(i).part(46);
      
      				dlib::point reyeLeftUp = shapes.at(i).part(44);
      				dlib::point reyeLeftDowm = shapes.at(i).part(48);
      
      				dlib::point reyeRightUp = shapes.at(i).part(45);
      				dlib::point reyeRightDowm = shapes.at(i).part(47);
      
      				float reyeA = sqrt(pow(reyeLeftUp.x() - reyeLeftDowm.x(), 2) + pow(reyeLeftUp.y() - reyeLeftDowm.y(), 2));
      				float reyeB = sqrt(pow(reyeRightUp.x() - reyeRightDowm.x(), 2) + pow(reyeRightUp.y() - reyeRightDowm.y(), 2));
      				float reyeC = sqrt(pow(reyeLeft.x() - reyeRight.x(), 2) + pow(reyeLeft.y() - reyeRight.y(), 2));
      
      				float reyeEVR = (reyeA + reyeB) / (2 * reyeC);
      
      				//计算人嘴纵横比
                      dlib::point mouth_left = shapes.at(i).part(49);
      				dlib::point mouth_right = shapes.at(i).part(55);
      
      				dlib::point mouth_leftUp = shapes.at(i).part(51);
      				dlib::point mouth_leftDown = shapes.at(i).part(59);
      
      				dlib::point mouth_rightUp = shapes.at(i).part(53);
      				dlib::point mouth_rightDown = shapes.at(i).part(57);
      
      				float mouthA = sqrt(pow(mouth_leftUp.x() - mouth_leftDown.x(), 2) + pow(mouth_leftUp.y() - mouth_leftDown.y(), 2));
      				float mouthB = sqrt(pow(mouth_rightUp.x() - mouth_rightDown.x(), 2) + pow(mouth_rightUp.y() - mouth_rightDown.y(), 2));
      				float mouthC = sqrt(pow(mouth_left.x() - mouth_right.x(), 2) + pow(mouth_left.y() - mouth_right.y(), 2));
      
      				float mouthEVR = (mouthA + mouthB) / (2 * mouthC);
      
      
      				//摇头
      				//左脸边缘
      				dlib::point face_left = shapes.at(i).part(2);
      				//右脸边缘
      				dlib::point face_right = shapes.at(i).part(16);
      				//鼻子中心
      				dlib::point face_nose = shapes.at(i).part(31);
      
      				//鼻子到左脸边缘距离
      				float lfaceLength = sqrt(pow(face_nose.x() - face_left.x(), 2) + pow(face_nose.y() - face_left.y(), 2));
      				//鼻子到右脸边缘距离
      				float rfaceLength = sqrt(pow(face_nose.x() - face_right.x(), 2) + pow(face_nose.y() - face_right.y(), 2));
      				
      
      				//记录张嘴次数
      				if (mouthEVR < 0.62){
      					//闭嘴
      					counter_mouth += 1;
      				}else if(mouthEVR > 0.70){
      					//张嘴
      					if (counter_mouth >= 1) {
      						mouthIndex += 1;
      					}
      					counter_mouth = 0;
      				}
      				else {
      					//此区间处于临界区,不稳定,不做检测
      				}
      
      
      				// 显示张嘴次数
      				char mouthBuf[100] = { 0 };
      				sprintf(mouthBuf, "mouth couent : %d", mouthIndex);
      				cv::putText(frame, mouthBuf, cv::Point(0, 20), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 255), 2);
      
      
      				//记录左眼眨眼次数
      				if (leyeEVR > 2.9) {
      					//闭眼
      					counter_leye += 1;
      				}
      				else {
      					//睁眼
      					if (counter_leye >= 1) {
      						leyeIndex += 1;
      					}
      					counter_leye = 0;
      				}
      
      				//记录右眼眨眼次数
      				if (reyeEVR > 5.0) {
      					//闭眼
      					counter_reye += 1;
      				}
      				else {
      					//睁眼
      					if (counter_reye >= 1) {
      						reyeIndex += 1;
      					}
      					counter_reye = 0;
      				}
      
      				//取最小值
      				if (reyeIndex > leyeIndex) {
      					reyeIndex = leyeIndex;
      				}
      
      				//显示眨眼次数
      				char eyeBuf[100] = { 0 };
      				sprintf(eyeBuf, "eye count: %d", reyeIndex);
      				cv::putText(frame, eyeBuf, cv::Point(0, 45), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 255), 2);
      			}
      			
      
                  // Display it all on the screen
                  win.clear_overlay();
                  win.set_image(cimg);
                  win.add_overlay(render_face_detections(shapes));
              }
          }
          catch(serialization_error& e)
          {
              cout << endl << e.what() << endl;
          }
          catch(exception& e)
          {
              cout << e.what() << endl;
          }
      }
    
    
    
  • CMakeLists.txt文件内容
  •   cmake_minimum_required (VERSION 3.5)
      project (faceRecongize)
      
      MESSAGE(STATUS "PROJECT_SOURCE_DIR " ${PROJECT_SOURCE_DIR})
      SET(SRC_LISTS ${PROJECT_SOURCE_DIR}/src/main.cpp)
      
      set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
      # 配置头文件目录
      include_directories(${PROJECT_SOURCE_DIR}/dlib-19.24)
      include_directories(${PROJECT_SOURCE_DIR}/opencv-4.5.0/include)
      include_directories(${PROJECT_SOURCE_DIR}/opencv-4.5.0/modules/core/include)
      include_directories(${PROJECT_SOURCE_DIR}/opencv-4.5.0/modules/calib3d/include)
      include_directories(${PROJECT_SOURCE_DIR}/opencv-4.5.0/modules/features2d/include)
      include_directories(${PROJECT_SOURCE_DIR}/opencv-4.5.0/modules/flann/include)
      include_directories(${PROJECT_SOURCE_DIR}/opencv-4.5.0/modules/dnn/include)
      include_directories(${PROJECT_SOURCE_DIR}/opencv-4.5.0/modules/highgui/include)
      include_directories(${PROJECT_SOURCE_DIR}/opencv-4.5.0/modules/imgcodecs/include)
      include_directories(${PROJECT_SOURCE_DIR}/opencv-4.5.0/modules/videoio/include)
      include_directories(${PROJECT_SOURCE_DIR}/opencv-4.5.0/modules/imgproc/include)
      include_directories(${PROJECT_SOURCE_DIR}/opencv-4.5.0/modules/ml/include)
      include_directories(${PROJECT_SOURCE_DIR}/opencv-4.5.0/modules/objdetect/include)
      include_directories(${PROJECT_SOURCE_DIR}/opencv-4.5.0/modules/photo/include)
      include_directories(${PROJECT_SOURCE_DIR}/opencv-4.5.0/modules/stitching/include)
      include_directories(${PROJECT_SOURCE_DIR}/opencv-4.5.0/modules/video/include)
      
      # 设置不显示命令框
      if(MSVC)
      	#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
      endif()
      
      # 添加库文件
      set(PRO_OPENCV_LIB ${PROJECT_SOURCE_DIR}/lib/opencv_video450.lib
      	${PROJECT_SOURCE_DIR}/lib/opencv_core450.lib
      	${PROJECT_SOURCE_DIR}/lib/opencv_videoio450.lib
      	${PROJECT_SOURCE_DIR}/lib/opencv_calib3d450.lib
      	${PROJECT_SOURCE_DIR}/lib/opencv_dnn450.lib
      	${PROJECT_SOURCE_DIR}/lib/opencv_features2d450.lib
      	${PROJECT_SOURCE_DIR}/lib/opencv_flann450.lib
      	${PROJECT_SOURCE_DIR}/lib/opencv_highgui450.lib
      	${PROJECT_SOURCE_DIR}/lib/opencv_gapi450.lib
      	${PROJECT_SOURCE_DIR}/lib/opencv_imgcodecs450.lib
      	${PROJECT_SOURCE_DIR}/lib/opencv_imgproc450.lib
      )
      set(PRO_DLIB_LIB ${PROJECT_SOURCE_DIR}/lib/dlib19.24.0_release_32bit_msvc1900.lib)
      
      # 生成可执行程序
      ADD_EXECUTABLE(faceRecongize ${SRC_LISTS})
      # 链接库文件
      TARGET_LINK_LIBRARIES(faceRecongize ${PRO_OPENCV_LIB} ${PRO_DLIB_LIB})
    

到了这里,关于使用opencv和dlib库(C++代码)实现人脸活体检测(眨眼、张嘴、摇头检测)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 计算机视觉:使用dlib实现人脸检测

    Dlib是一个广泛使用的开源库,在计算机视觉和机器学习领域具有重要影响。它是由Davis King在2002年开发,主要用C++语言编写,但也提供了Python接口。Dlib结合了高效的算法和易用性,使其成为学术界和工业界的热门选择。 多样的机器学习算法:Dlib包含丰富的机器学习算法,如

    2024年04月28日
    浏览(49)
  • opencv、dlib、paddlehub人脸检测

    opencv、dlib、paddlehub检测效果对比。dlib和paddlehub的效果相对好一点。 说明:本文只做人脸检测不识别,找识别的不用看本文。 依赖(用1个就行) dlib需要C++编译器(gcc 或 vs) opencv检测     dlib检测  PaddleHub检测 APIPOST调接口测试     axios调用示例 jquery调用示例

    2024年02月08日
    浏览(47)
  • OpenCV笔记整理【人脸检测之Harr级联分类器&&dlib库】

    1. 级联分类器: OpenCV提供的级联分类器有Harr、HOG、LBP这3种,这些分类器以XML文件保存,这里主要演示Harr检测人脸(OpenCV提供的分类器不仅限于检测人脸,还包括下表特征检测,当然OpenCV还支持训练自己的级联分类器,这里不做说明。。。)。 2. 函数介绍: object = cv2.Casca

    2024年01月22日
    浏览(46)
  • 使用OpenCV工具包成功实现人脸检测与人脸识别,包括传统视觉和深度学习方法(附完整代码,吐血整理......)

    要实现人脸识别功能,首先要进行人脸检测,判断出图片中人脸的位置,才能进行下一步的操作。 参考链接: 1、OpenCV人脸检测 2、【OpenCV-Python】32.OpenCV的人脸检测和识别——人脸检测 3、【youcans 的图像处理学习课】23. 人脸检测:Haar 级联检测器 4、OpenCV实战5:LBP级联分类器

    2024年02月12日
    浏览(46)
  • 使用OpenCV工具包成功实现人脸检测与人脸识别,包括传统视觉和深度学习方法(附完整代码,模型下载......)

    要实现人脸识别功能,首先要进行人脸检测,判断出图片中人脸的位置,才能进行下一步的操作。 参考链接: 1、OpenCV人脸检测 2、【OpenCV-Python】32.OpenCV的人脸检测和识别——人脸检测 3、【youcans 的图像处理学习课】23. 人脸检测:Haar 级联检测器 4、OpenCV实战5:LBP级联分类器

    2024年02月08日
    浏览(45)
  • [C#]winform利用seetaface6实现C#人脸检测活体检测口罩检测年龄预测性别判断眼睛状态检测

    【官方框架地址】 https://github.com/ViewFaceCore/ViewFaceCore 【算法介绍】 SeetaFace6是由中国科技公司自主研发的一款人脸识别技术,它基于深度学习算法,能够快速、准确地识别出人脸,并且支持多种应用场景,如门禁系统、移动支付、安全监控等。SeetaFace6的识别准确率高达99%以上

    2024年01月21日
    浏览(54)
  • Python+OpenCV 简单实现人脸检测多个和人脸识别 2(附代码)

    如果dilb和face_recognition第三方包安装失败,请移步到Python 解决dilb和face_recognition第三方包安装失败_水w的博客-CSDN博客 上篇请移步到Python+dilb 简单实现人脸检测(附代码)_水w的博客-CSDN博客 本篇是在上篇的工作基础上进行的。 目录 6 人脸检测多个 7 视频检测 8 拍照保存 9 训练

    2024年01月16日
    浏览(55)
  • Python | 人脸识别系统 — 活体检测

    博客汇总:Python | 人脸识别系统 — 博客索引 GitHub地址:Su-Face-Recognition 注:阅读本博客前请先参考 工具安装、环境配置:Python | 人脸识别系统 — 简介 UI界面设计:Python | 人脸识别系统 — UI界面设计 UI事件处理:Python | 人脸识别系统 — UI事件处理 摄像头画面展示:Python

    2024年02月02日
    浏览(47)
  • 人脸检测实战:使用opencv加载深度学习模型实现人脸检测(1)

    import argparse import cv2 ap = argparse.ArgumentParser() ap.add_argument(“-i”, “–image”, required=True, help=“path to input image”) ap.add_argument(“-p”, “–prototxt”, required=True, help=“path to Caffe ‘deploy’ prototxt file”) ap.add_argument(“-m”, “–model”, required=True, help=“path to Caffe pre-trained model”)

    2024年04月16日
    浏览(58)
  • 基于opencv与mediapipe的面部跟踪(人脸检测追踪)python代码实现

            面部跟踪主要是从图像或视频中检测出人脸并输出人脸位置及其大小等有效信息,并在后续帧中继续捕获人脸的位置及其大小等信息,实时跟踪人脸。此技术可用于海关、机场、视频会议、拍照对焦、面部打码等业务场景。(与人脸识别是不同范畴)         本

    2024年01月17日
    浏览(72)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包