C++ OpenCV 调用摄像头进行人脸检测

正文索引 [隐藏]

级联分类器实现人脸检测

CascadeClassifier,是OpenCV中做人脸检测时的一个级联分类器,有两种选择:一是使用老版本的CvHaarClassifierCascade函数,一是使用新版本的CascadeClassifier类。老版本的分类器只支持类Haar特征,而新版本的分类器既可以使用Haar,也可以使用LBP特征。我这里用到的是OpenCV-4.5.1的CascadeClassifier类。具体步骤如下:

  1. 加载 Opencv 自带的人脸检测 haarcascade_frontalface_alt.xml 分类器。
  2. 图像预处理 cvtColor(灰度化) equalizeHist(直方图均衡化)。
  3. 使用 detectMultiScale 函数进行识别。
  4. 使用 rectangle 函数绘制找到的目标矩形框。

OpenCV的sources文件夹里有已经训练好的人脸识别训练件”haarcascade_frontalface_alt.xml”,位置是在”opencv-4.5.1\sources\data\haarcascades\”目录下。

#include "cv.hpp"

Mat TydCV::faceDetection(Mat& image) {
    //定义并加载训练文件
    cv::String detectfile = "D:/Code/OpenCV/opencv-4.5.1/sources/data/haarcascades/haarcascade_frontalface_alt.xml";
    cv::CascadeClassifier faceCascade;
    if(!faceCascade.load(detectfile)) {
        cout << "could not load the detectfile!" << endl;
    } else {
        cout << "fine" << endl;
        Mat _gray;
        GpuMat src, gray;
        src.upload(image);
        cuda::cvtColor(src, gray, COLOR_BGR2GRAY);
        cuda::equalizeHist(gray, gray);
        gray.download(_gray);
        vector<Rect> faces;
        faceCascade.detectMultiScale(_gray,faces,1.1,3,0);
        cout << faces.size() << endl;
        for(int i = 0; i < faces.size(); i++) {
            cv::rectangle(image, faces[i], cv::Scalar(0, 0, 255));
        }
        imshow("result",image);
    }
    return image;
}

运行界面如下,可以看到人脸附近还是被矩阵标记了出来。

调用摄像头进行人脸标识

调用摄像头来将视频分帧再进行人脸标识吧,代码如下:

void TydCV::cameraFaceDetection() {
    cv::CascadeClassifier faceCascade;
    cv::String detectfile = "D:/Code/OpenCV/opencv-4.5.1/sources/data/haarcascades/haarcascade_frontalface_alt.xml";
    faceCascade.load(detectfile);   //加载分类器,注意文件路径
    Mat camera, gray;
    vector<Rect> faces;
    VideoCapture capture(0);
    while(capture.read(camera)) {
        int key = waitKey(10);
        if(key == 27) {  //退出
        break;
    }
    if(camera.channels() ==3) {
        cv::cvtColor(camera, gray, CV_RGB2GRAY);
    } else {
        gray = camera;
    }
    faceCascade.detectMultiScale(gray, faces, 1.1, 3, 0);   //检测人脸
    if(faces.size()>0) {
        for(int i = 0; i < faces.size(); i++) {
            rectangle(camera, Point(faces[i].x, faces[i].y), Point(faces[i].x + faces[i].width, faces[i].y + faces[i].height), 
                Scalar(0, 0, 255), 1, 8);    //框出人脸位置
        }
    }
    imshow("Camera", camera);
}

运行结果如下(打一下码):