使用opencv实现基于Haar特征的人脸检测

       

       此文章主要是学习的记录。使用opencv的版本是 3.4.6。实现了图片的人脸检测及人的眼睛、鼻子和嘴巴的检测。里面使用的窗口显示相关的代码都是opencv的函数。

 

人脸检测

        openCV的人脸识别主要通过Haar特征分类器实现的,haar特征分类器是一个xml文件,文件描述了检测物体的Haar特征值。Haar分类器需要通过大量的数据来训练,opecv的安装路径里面有已经预先训练好的分类器,路径为opencv\sources\data\haarcascades。看到其中的正脸的分类器如下:

                    使用opencv实现基于Haar特征的人脸检测_第1张图片

       此技术虽然适用于人脸检测,但不限于人脸检测,还可用于其他物体的检测(对对应的物体收集数据进行训练,得到其xml文件)。当然也可以对人脸识别进行更多的数据训练,提高人脸的检测精度。

 

      这个是只检测脸部的demo,因为这里是使用Qt创建的工程,图片的相对路径是Makefile的路径。

代码如下:

//只检测脸部的demo,直接调用
bool detectFace()
{
    /********************************** 1.打开图片 *************************************/
    string str = "face4.jpg";
    Mat img = imread(str);
    Mat imgGray;
    //转灰度图像
    cvtColor(img, imgGray, COLOR_BGR2GRAY);
    //显示窗口
    namedWindow("display");
    imshow("display", img);

    /*********************************** 2.加载检测器  ******************************/
    // 建立级联分类器
    // 加载训练好的 人脸检测器(.xml)
    CascadeClassifier cascade_face;
    const string path_face = "xml\\haarcascade_frontalface_alt.xml";
    if (!cascade_face.load(path_face))
    {
        cout << "cascade load failed!\n";
        return -1;
    }
    //计时
    double t = 0;
    t = (double)getTickCount();

    /*********************************** 3.人脸检测 ******************************/
    vector faces(0);
    cascade_face.detectMultiScale(imgGray,  //输入的原图
                             faces,    //表示检测到的人脸目标序列,输出的结果
                             1.1,    //每次图像尺寸减小的比例为1.1
                             3,      //每一个目标至少要被检测到3次才算是真的目标
                             0 ,   // 默认
                             Size(30, 30)  //最小的检测区域,根据使用场景来确定大小,比如太小的脸放弃
                             );


    cout << "detect face number is :" << faces.size() << endl;

    /********************************  4.显示人脸矩形框 ******************************/

    if (faces.size() > 0)
    {
        //对脸部进行循环
        for (size_t i = 0;i < faces.size();i++)
        {
            cout<<"face "<

 

结果如下,因为背景不算复杂,所以检测结果很准确。如果背景复杂的话就很可能检测到错误的人脸或漏掉人脸。

使用opencv实现基于Haar特征的人脸检测_第2张图片

人脸及眼睛、鼻子、嘴巴的检测

        如果检测的脸部区域比较大,且检测的是正脸,为了提高识别率,可以通过检测到人脸再检测判断是否有人眼睛、鼻子、嘴来加以判断。在opencv的安装路径下只能找到了脸和眼睛的分类器,而鼻子、嘴的分类器可以到opencv_contrib那里去找:https://github.com/opencv/opencv_contrib

        关于opencv_contrib:

2014年8月3.0 alpha发布,除大部分方法都使用OpenCL加速外,3.x默认包含以及使用IPP,同时,matlab bindings、Face Recognition、SIFT、SURF、 text detector、motion templates & simple flow 等都移到了opencv_contrib下(opencv_contrib不仅存放了尚未稳定的代码,同时也存放了涉及专利保护的技术实现),大量涌现的新方法也包含在其中。

       在contrib中的face模块里可以找到更多的分类器,比如嘴巴的路径是:

        modules/face/data/cascades/haarcascade_mcs_mouth.xml

 

       检测的方法还是和上面类似的。主要是先检测人脸,然后在人脸的特定区域里面检测 眼睛、鼻子和嘴巴,如果 眼睛、鼻子和嘴巴都存在,那是人脸的概率就特别大了。

       demo里面对眼睛、鼻子和嘴巴的检测做了些简单的限制,这个应该还有进一步细化研究。

代码:

#include
#include

using namespace std;
using namespace cv;

CascadeClassifier cascade_face;
CascadeClassifier cascade_eye;
CascadeClassifier cascade_mouth;
CascadeClassifier cascade_nose;

bool detectFaceDetail(Mat& img);

int main(int argc,char *argv[])
{

    /*********************************** 1.加载检测器  ******************************/
    // 建立级联分类器
    // 加载训练好的 人脸检测器(.xml)
    const string path_face = "xml\\haarcascade_frontalface_alt.xml";
    if (!cascade_face.load(path_face))
    {
        cout << "cascade load failed!\n";
        return -1;
    }

    // 加载训练好的 眼睛检测器(.xml)
    const string path_eye = "xml\\haarcascade_eye.xml";
    if (!cascade_eye.load(path_eye))
    {
        cout << "cascade_eye load failed!\n";
        return -1;
    }

    // 加载训练好的 嘴巴检测器(.xml)
    const string path_mouth = "xml\\haarcascade_mcs_mouth.xml";
    if (!cascade_mouth.load(path_mouth))
    {
        cout << "cascade_mouth load failed!\n";
        return -1;
    }

    // 加载训练好的 鼻子检测器(.xml)
    const string path_nose = "xml\\haarcascade_mcs_nose.xml";
    if ( ! cascade_nose.load(path_nose))
    {
        cout << "cascade_mouth load failed!\n";
        return -1;
    }

    //单个图片检测
    string str = "face4.jpg";
    Mat img = imread(str);//放到makefile文件下
    namedWindow("display");
    imshow("display", img);
    detectFaceDetail(img);
    destroyWindow("display");
    namedWindow("face_detect");
    imshow("face_detect", img);
    while(waitKey(0)!='k') ;
    destroyWindow("face_detect");


    return 0;
}


//检测脸部、眼睛、鼻子、嘴巴,传入需要检测的图像
bool detectFaceDetail(Mat& img)
{
    bool getFace = false;
    Mat imgGray;
    /* 因为用的是类haar特征,所以都是基于灰度图像的,这里要转换成灰度图像 */
    cvtColor(img, imgGray, COLOR_BGR2GRAY);


    //计时
    double t = 0;
    t = (double)getTickCount();
    /*********************************** 2.人脸检测 ******************************/
    vector faces(0);

    cascade_face.detectMultiScale(imgGray,
                             faces,
                             1.1,
                             3,
                             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++)
        {
            cout<<"face "< faces[i].height/4){
                        bGetNose = true;
                        rectangle(faceROI, noses[j], Scalar(150, 200, 200), 3, 8, 0);
                        cout<<"eyes "< faces[i].height/3)
                    {
                        bGetMouth = true;
                        rectangle(faceROI, mouths[j], Scalar(150, 150, 150), 3, 8, 0);
                        cout<<"eyes "<

结果如下(上面的图片脸好像太小了,换一张):

                                  使用opencv实现基于Haar特征的人脸检测_第3张图片

demo工程:

https://github.com/fengxieye/Qt-demo/tree/master/face

你可能感兴趣的:(opencv)