OpenCV人脸检测Demo程序

我现在的角色只是一个软件开发人员,所以暂时不深究算法问题,我的目的只有一个:以最快的方式完成项目框架搭建,从而进行进度评估。

说明
进行人脸鉴别(不关心是谁的脸)从代码量上来讲可以说非常少,我不再作具体说明,源码的注释已经足够详细,这里我使用的CascadeClassifier,大体分为三步:

  1. 加载级联分类器,一般以xml格式的文件存在,一般都是以大量的数据进行训练从而得到该文件,这里我们使用opencv提供的haarcascade_frontalface_alt.xml,这个文件在源码包里可以找到。
  2. 获取原始图像数据,需要cv::Mat数据类型,设置一些参数,然后开始鉴别,只需调用detectMultiScale即可。
  3. 输出经过识别的图像,一般经过识别的图像我们都会做一些标记,比如画个圆圈,加几个字之类的。
    代码
    我也做了一个在Linux下的Qt Creator的可执行项目(点我下载)
int main( int argc, const char** argv )
{
    test();
    return 0;
}



void test()
{
    VideoCapture cap(0);//为了方便,使用opencv自带的函数驱动摄像头,之后会移植v4l2过来
    if(!cap.isOpened())
    {
        perror("fail to open camera");
        return;
    }

    Mat image;
    bool tryflip = false;
    CascadeClassifier cascade, nestedCascade;
    cascade.load( "/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml" );//加载主级联分类器
    nestedCascade.load("/usr/local/share/OpenCV/haarcascades/haarcascade_eye_tree_eyeglasses.xml");//加载辅助级联分类器
    double scale = 1.5;
    image = imread( "./lena.jpg", 1 );//加载图片

    while(1)
    {
        cap >> image;//获取一帧图像
        detectAndDraw( image, cascade, nestedCascade, scale, tryflip );
        waitKey(30);//每30ms检测一次
    }
    //detectAndDraw( image, cascade, nestedCascade, scale, tryflip );
    //waitKey(0);
}

void detectAndDraw( Mat& img, CascadeClassifier& cascade,
                    CascadeClassifier& nestedCascade,
                    double scale, bool tryflip )
{
    double t = 0;
    vector faces, faces2;
    const static Scalar colors[] =
    {
        Scalar(255,0,0),
        Scalar(255,128,0),
        Scalar(255,255,0),
        Scalar(0,255,0),
        Scalar(0,128,255),
        Scalar(0,255,255),
        Scalar(0,0,255),
        Scalar(255,0,255)
    };//定义一些颜色备用
    Mat gray, smallImg;

    cvtColor( img, gray, COLOR_BGR2GRAY );//转换颜色空间
    double fx = 1 / scale;
    resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR );//重新调整大小
    equalizeHist( smallImg, smallImg );

    t = (double)getTickCount();//用于计算检测时间
    cascade.detectMultiScale( smallImg, faces,
        1.1, 2, 0
        //|CASCADE_FIND_BIGGEST_OBJECT
        //|CASCADE_DO_ROUGH_SEARCH
        |CASCADE_SCALE_IMAGE,
        Size(30, 30) );//主鉴别器进行检测,检测到的脸部位置保存在faces里
    if( tryflip )//如果设置了翻转检测,就先翻转再检测
    {
        flip(smallImg, smallImg, 1);
        cascade.detectMultiScale( smallImg, faces2,
                                 1.1, 2, 0
                                 //|CASCADE_FIND_BIGGEST_OBJECT
                                 //|CASCADE_DO_ROUGH_SEARCH
                                 |CASCADE_SCALE_IMAGE,
                                 Size(30, 30) );
        for( vector::const_iterator r = faces2.begin(); r != faces2.end(); ++r )
        {
            faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height));
        }
    }
    t = (double)getTickCount() - t;
    printf( "detection time = %g ms\n", t*1000/getTickFrequency());
    for ( size_t i = 0; i < faces.size(); i++ )//对每一个脸的位置画上圆圈标记
    {
        Rect r = faces[i];
        Mat smallImgROI;
        vector nestedObjects;
        Point center;
        Scalar color = colors[i%8];
        int radius;

        double aspect_ratio = (double)r.width/r.height;
        if( 0.75 < aspect_ratio && aspect_ratio < 1.3 )
        {
            center.x = cvRound((r.x + r.width*0.5)*scale);
            center.y = cvRound((r.y + r.height*0.5)*scale);
            radius = cvRound((r.width + r.height)*0.25*scale);
            circle( img, center, radius, color, 3, 8, 0 );
        }
        else
            rectangle( img, cvPoint(cvRound(r.x*scale), cvRound(r.y*scale)),
                       cvPoint(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)),
                       color, 3, 8, 0);
        if( nestedCascade.empty() )
            continue;
        smallImgROI = smallImg( r );
        nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
            1.1, 2, 0
            //|CASCADE_FIND_BIGGEST_OBJECT
            //|CASCADE_DO_ROUGH_SEARCH
            //|CASCADE_DO_CANNY_PRUNING
            |CASCADE_SCALE_IMAGE,
            Size(30, 30) );
        for ( size_t j = 0; j < nestedObjects.size(); j++ )
        {
            Rect nr = nestedObjects[j];
            center.x = cvRound((r.x + nr.x + nr.width*0.5)*scale);
            center.y = cvRound((r.y + nr.y + nr.height*0.5)*scale);
            radius = cvRound((nr.width + nr.height)*0.25*scale);
            circle( img, center, radius, color, 3, 8, 0 );
        }
    }
    imshow( "result", img );//显示这一帧的检测结果
}

你可能感兴趣的:(OpenCV)