人脸识别初探之人脸检测(一)

2022-06-16 14:08:48 浏览数 (1)

还记的这篇OpenCV即时上手可学习可商用的项目

接下来准备把其中的代码公开,欢迎一起交流学习

人脸识别是个说小不小的工程,在完成这个项目之前,先把人脸检测熟悉一下。人脸检测用到的函数如下:

代码语言:javascript复制
 void detectMultiScale( InputArray image,
                          CV_OUT std::vector<Rect>& objects,
                          double scaleFactor = 1.1,
                          int minNeighbors = 3, int flags = 0,
                          Size minSize = Size(),
                          Size maxSize = Size() );
 

Opencv中给出了四种人脸训练模型如下:

代码语言:javascript复制
1.haarcascade_frontalface_alt.xml

2.haarcascade_frontalface_alt_tree.xml

3.haarcascade_frontalface_alt2.xml

4.haarcascade_frontalface_default.xml

图片中的人脸检测:

代码语言:javascript复制

#include<opencv2/opencv.hpp>
#include<iostream>
 
using namespace std;
using namespace cv;
 
int main(int argc,char *argv[])
{
  Mat img = imread("../img/2.png");
  namedWindow("display");
  imshow("display", img);
  
  /*********************************** 1.加载人脸检测器  ******************************/
  // 建立级联分类器
  CascadeClassifier cascade;
  // 加载训练好的 人脸检测器(.xml)
  //const string path = "../haarcascades/haarcascade_frontalface_alt.xml";
  //还有两种模型自己检测
    const string path = "../haarcascades/haarcascade_frontalface_default.xml";
    //友好错误信息提示
  try{
    cascade.load(path);
  }
  catch (cv::Exception e){}
  if (cascade.empty())
  {
    std::cerr << "脸部检测器不能加载 (";
    std::cerr << path << ")!" << std::endl;
    exit(1);
  }

  //计时
  double t = 0;
  t = (double)getTickCount();
  /*********************************** 2.人脸检测 ******************************/
  vector<Rect> faces(0);
  cascade.detectMultiScale(img, faces, 1.1, 2, 0 ,Size(30,30));
 
  cout << "detect face number is :" << faces.size() << endl;
  /********************************  3.显示人脸矩形框 ******************************/
  
  if (faces.size() > 0)
  {
    for (size_t i = 0;i < faces.size();i  )
    {
      rectangle(img, faces[i], Scalar(150, 0, 0), 3, 8, 0);
 
    }
  }
  else cout << "未检测到人脸" << endl;
 
  t = (double)getTickCount() - t;  //getTickCount():  Returns the number of ticks per second.
  cout << "检测人脸用时:" << t * 1000 / getTickFrequency() << "ms (不计算加载模型的时间)" << endl;
 
  namedWindow("face_detect");
  imshow("face_detect", img);
  while(waitKey(0)!='k') ;
  destroyWindow("display");
  destroyWindow("face_detect");
    return 0;
}

效果如图:

打开相机进行人脸检测:

代码语言:javascript复制
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>
 
using namespace cv;
using namespace std;

void Pic2Gray(Mat camerFrame,Mat &gray)
{
  //普通台式机3通道BGR,移动设备为4通道
  if (camerFrame.channels() == 3)
  {
    cvtColor(camerFrame, gray, CV_BGR2GRAY);
  }
  else if (camerFrame.channels() == 4)
  {
    cvtColor(camerFrame, gray, CV_BGRA2GRAY);
  }
  else
    gray = camerFrame;
}
 
 
int main()
{
  //加载Haar或LBP对象或人脸检测器
  CascadeClassifier faceDetector;
  std::string faceCascadeFilename = "../haarcascades/haarcascade_frontalface_default.xml";

   if ( ! faceDetector.load(faceCascadeFilename))
  {
    cout << "cascade load failed!n";
  }

   if ( ! eyes_cascade.load(faceCascadeFilename))
  {
    cout << "cascade load failed!n";
  }
 
  //打开摄像头
  VideoCapture camera(0);
  while (true)
  {
    Mat camerFrame;
    camera >> camerFrame;
    if (camerFrame.empty())
    {
      std::cerr << "无法获取摄像头图像" << std::endl;
      getchar();
      exit(1);
    }
    Mat displayedFrame(camerFrame.size(),CV_8UC3);
 
 
    //人脸检测只试用于灰度图像
    Mat gray;
    Pic2Gray(camerFrame, gray);
 
    //直方图均匀化(改善图像的对比度和亮度)
    Mat equalizedImg;
    equalizeHist(gray, equalizedImg);
 
    //人脸检测用Cascade Classifier::detectMultiScale来进行人脸检测
 
    int flags = CASCADE_FIND_BIGGEST_OBJECT|CASCADE_DO_ROUGH_SEARCH;  //只检测脸最大的人
    //int flags = CASCADE_SCALE_IMAGE;  //检测多个人
    Size minFeatureSize(30, 30);
    float searchScaleFactor = 1.1f;
    int minNeighbors = 4;
    std::vector<Rect> faces;
    faceDetector.detectMultiScale(equalizedImg, faces, searchScaleFactor, minNeighbors, flags, minFeatureSize);
 
    //画矩形框
    cv::Mat face;
    cv::Point text_lb;
    for (size_t i = 0; i < faces.size(); i  )
    {

        
      if (faces[i].height > 0 && faces[i].width > 0)
      {
    
        cv::rectangle(equalizedImg, faces[i], cv::Scalar(255, 0, 0), 1, 8, 0);
        cv::rectangle(gray, faces[i], cv::Scalar(255, 0, 0), 1, 8, 0);
        cv::rectangle(camerFrame, faces[i], cv::Scalar(0, 255, 0), 1, 8, 0);
      }

    }
 
 
    imshow("junyihua", equalizedImg);
    imshow("huidu", gray);
    imshow("yuantu", camerFrame);
 
    waitKey(20);
  }
 
  getchar();
  return 0;
}

效果如下:

涉及到个人隐私,还是不贴图了巴拉巴拉

另外补充人脸 眼睛检测:

代码语言:javascript复制
#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"

#include <stdio.h>

using namespace std;
using namespace cv;

/** Function Headers */
void detectAndDisplay(Mat frame);

/** Global variables */
String face_cascade_name, eyes_cascade_name;
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
String window_name = "Capture - Face detection";

/** @function main */
int main(int argc, const char** argv)
{
  face_cascade_name = "../haarcascades/haarcascade_frontalface_default.xml";
  eyes_cascade_name = "../haarcascades/haarcascade_eye_tree_eyeglasses.xml";
  VideoCapture capture;
  Mat frame;

  //-- 1. Load the cascades
  if (!face_cascade.load(face_cascade_name)) { printf("--(!)Error loading face cascaden"); return -1; };
  if (!eyes_cascade.load(eyes_cascade_name)) { printf("--(!)Error loading eyes cascaden"); return -1; };

  //-- 2. Read the video stream
  capture.open(0); //打开摄像头
  if (!capture.isOpened()) { printf("--(!)Error opening video capturen"); return -1; }

  while (capture.read(frame)) //读取帧
  {
    if (frame.empty())
    {
      printf(" --(!) No captured frame -- Break!");
      break;
    }

    //-- 3. Apply the classifier to the frame
    detectAndDisplay(frame);

    if (waitKey(10) == 'k') { break; } // escape
  }
  return 0;
}

/** @function detectAndDisplay */
void detectAndDisplay(Mat frame)
{
  std::vector<Rect> faces;
  Mat frame_gray;

  cvtColor(frame, frame_gray, COLOR_BGR2GRAY);  //BGR 转化为灰度图
  equalizeHist(frame_gray, frame_gray);   //直方图均衡化

  //-- Detect faces
  face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(60, 60));

  for (size_t i = 0; i < faces.size(); i  )
  {
    Point center(faces[i].x   faces[i].width / 2, faces[i].y   faces[i].height / 2); // 人脸中心坐标
    ellipse(frame, center, Size(faces[i].width / 2, faces[i].height / 2), 0, 0, 360, Scalar(255, 0, 255), 4, 8, 0); // 椭圆

    Mat faceROI = frame_gray(faces[i]);
    std::vector<Rect> eyes;

    //-- In each face, detect eyes
    eyes_cascade.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));

    for (size_t j = 0; j < eyes.size(); j  )
    {
      Point eye_center(faces[i].x   eyes[j].x   eyes[j].width / 2, faces[i].y   eyes[j].y   eyes[j].height / 2); //眼睛的中心
      int radius = cvRound((eyes[j].width   eyes[j].height)*0.25); //取整
      circle(frame, eye_center, radius, Scalar(255, 0, 0), 4, 8, 0);
    }
  }
  //-- Show what you got
  imshow(window_name, frame);
}

0 人点赞