人脸检测库函数的效果比较

本文对比了OpenCV自带的人脸检测库与Shiqi Yu发布的高性能人脸检测库,通过VS2010和OpenCV 2.4.11实现,允许调整图像的旋转、缩放和平移,并提供了不同检测函数的切换。测试涵盖多种级联分类器及Shiqi Yu的检测函数,如lbpcascade_frontalface.xml和facedetect_frontal()等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

年前在OpenCV论坛上看到Shiqi Yu发布的免费的高性能的人脸检测库,于是down下来做了一下效果测试。感兴趣的同学,也可以做一下检测速度的比较。
本人才疏学浅,只是将它与OpenCV自带的人脸检测库函数做了一个粗浅的比较,欢迎各位大神提点。


程序功能简介:

程序实现环境:VS2010 + OpenCV 2.4.11
程序退出:在窗口中敲击回车键即可;
旋转图像:鼠标拖动窗口中的Angle轴滑块即可;
缩放图像:鼠标拖动窗口中的Scale轴滑块即可;
平移图像:在窗口中任意位置,鼠标左键拖拽图像即可;
平移图像后复原:在窗口中任意位置,单击鼠标右键即可;
切换人脸检测库函数:鼠标拖动窗口中的Mode轴滑块即可。

对于Mode值的说明:
  • 0Mode4 时,检测函数采用的是OpenCV自带的级联检测模块CascadeClassifier(如何使用级联分类器做人脸检测,可以参见OpenCV的Tutorial,这里有相应的中文翻译版)。具体说明如下:

当mode=0时,加载的是lbpcascade_frontalface.xml;
当mode=1时,加载的是haarcascade_frontalface_alt.xml;
当mode=2时,加载的是haarcascade_frontalface_alt2.xml;
当mode=3时,加载的是haarcascade_frontalface_default.xml;
当mode=4时,加载的是haarcascade_frontalface_alt_tree.xml;

  • 5Mode8 时,检测函数采用的是Shiqi Yu发布的[免费的高性能的人脸检测库](使用方法可参见它自带的示例程序)。具体说明如下:

当mode=5时,调用的是facedetect_frontal();
当mode=6时,调用的是facedetect_frontal_surveillance();
当mode=7时,调用的是facedetect_multiview();
当mode=8时,调用的是facedetect_multiview_reinforce();


程序代码:

#include <time.h>
#include <stdio.h>
#include <vector>
#include <iostream>
#include <opencv.hpp>
#include "facedetect-dll.h"

using namespace cv;
using namespace std;

#pragma comment(lib,"libfacedetect.lib")
//#pragma comment(lib,"libfacedetect-x64.lib")

//Do not change the buffer size!
#define DETECT_BUFFER_SIZE 0xC004

static Mat onRot(int pos, int rat, Mat* im);
static Mat onAffine(Mat* im, Point2f dif);
static void onMouse(int Event, int x, int y, int drag, Mat* im);
static int Detect_Display(Mat& im, int mod);

void main(int argc, char* argv[])
{
    cout<<"Hello, VS10. I'm back!"<<endl;
    Mat Pic = imread("Friends2.jpg"), Cam(Pic), dst;

    namedWindow("Video");   int pos = 36, rat = 10, mod = 0;
    createTrackbar("Angle","Video", &pos,72);
    createTrackbar("Scale","Video", &rat,40);
    createTrackbar("Mode","Video", &mod,8);
    setMouseCallback("Video", (MouseCallback)onMouse, &Cam);

    //VideoCapture cap(0);
    while((waitKey(100)&255)!=13) //Enter=13
    {
        dst = onRot(pos, rat, &Cam);
        Detect_Display(dst, mod);
        imshow("Video", dst);
    }//end while
}//end main

static int Detect_Display(Mat& im, int mod)
{
    Mat gray;   cvtColor(im, gray, CV_BGR2GRAY); //must gray
    vector<Rect> faces, eyes;   equalizeHist(gray, gray); //normalization

    int *pResults = NULL; //!!! DO NOT RELEASE pResults !!!
    //pBuffer is used in the facedetect_XXX functions:
    unsigned char* pBuffer = (unsigned char*)malloc(DETECT_BUFFER_SIZE);
    if(!pBuffer)    {fprintf(stderr, "Can not alloc buffer.\n");    return 0;}
    CascadeClassifier Eyes("haarcascade_eye_tree_eyeglasses.xml"), Face;

    switch(mod)
    {
    case 0: if(!Face.load("lbpcascade_frontalface.xml"))    return 0;
        Face.detectMultiScale(gray, faces, 1.1, 2, CV_HAAR_SCALE_IMAGE|0, Size(30,30)); break;
    case 1: if(!Face.load("haarcascade_frontalface_alt.xml"))   return 0;
        Face.detectMultiScale(gray, faces, 1.1, 2, CV_HAAR_SCALE_IMAGE|0, Size(30,30)); break;
    case 2: if(!Face.load("haarcascade_frontalface_alt2.xml"))  return 0;
        Face.detectMultiScale(gray, faces, 1.1, 2, CV_HAAR_SCALE_IMAGE|0, Size(30,30)); break;
    case 3: if(!Face.load("haarcascade_frontalface_default.xml"))   return 0;
        Face.detectMultiScale(gray, faces, 1.1, 2, CV_HAAR_SCALE_IMAGE|0, Size(30,30)); break;
    case 4: if(!Face.load("haarcascade_frontalface_alt_tree.xml"))  return 0;
        Face.detectMultiScale(gray, faces, 1.1, 2, CV_HAAR_SCALE_IMAGE|0, Size(30,30)); break;
    //frontal face detection: it's fast, but cannot detect side view faces.
    case 5: pResults = facedetect_frontal(pBuffer, (unsigned char*)(gray.ptr(0)),
                                  gray.cols, gray.rows, (int)gray.step, 1.2f, 2, 48);   break;
    //frontal face detection for video surveillance: it can detect faces with bad illumination.
    case 6: pResults = facedetect_frontal_surveillance(pBuffer, (unsigned char*)(gray.ptr(0)),
                                  gray.cols, gray.rows, (int)gray.step, 1.2f, 2, 48);   break;
    //multiview face detection: it can detect side view faces, but slower than facedetect_frontal().
    case 7: pResults = facedetect_multiview(pBuffer, (unsigned char*)(gray.ptr(0)),
                                  gray.cols, gray.rows, (int)gray.step, 1.2f, 2, 48);   break;
    //reinforced multiview face detection: it's better but slower than facedetect_multiview().
    case 8: pResults = facedetect_multiview_reinforce(pBuffer, (unsigned char*)(gray.ptr(0)),
                                  gray.cols, gray.rows, (int)gray.step, 1.2f, 2, 48);   break;
    }//end switch
    if(mod>4)   faces.resize(pResults?(*pResults):0); //for facedetect_XXX functions

    cout<<faces.size()<<" faces detected!\n";
    for(int i=0; i<faces.size(); ++i) //mark each face
    {
        if(mod>4) //for facedetect_XXX functions
        {   short* p = ((short*)(pResults+1)) + 6*i;
            faces[i].x = p[0];  faces[i].width = p[2];
            faces[i].y = p[1];  faces[i].height = p[3];
            cout<<"face_rect = "<<faces[i]<<", neighbors = "<<p[4]<<".\n";
        }//end if
        rectangle(im, faces[i], Scalar(255,0,255), 2); //mark with rectangle

        Mat faceROI = gray(faces[i]); //In each face, detect eyes
        Eyes.detectMultiScale(faceROI, eyes, 1.1, 2, CV_HAAR_SCALE_IMAGE|0, Size(30,30));
        for(int j=0; j<eyes.size(); ++j) //mark each eye
        {
            Point center(faces[i].x + eyes[j].x + eyes[j].width*0.5, faces[i].y + eyes[j].y + eyes[j].height*0.5);
            int radius = cvRound((eyes[j].width + eyes[j].height)/4);
            circle(im, center, radius, Scalar(255,0,0), 2); //mark with circle
        }//end for
    }//end for
    free(pBuffer);  return faces.size(); //release pBuffer
}//end Detect_Display

static Mat onRot(int pos, int rat, Mat* im)
{
    Point center(im->cols/2, im->rows/2);
    double angle = 5*pos-180, scale = 0.1*rat;
    Mat rot = getRotationMatrix2D(center, angle, scale), dst;
    warpAffine(*im, dst, rot, im->size());  return dst;
}//end onRot

static void onMouse(int Event, int x, int y, int drag, Mat* im)
{ //only effective for Picture, not fit for Cam.
    static Mat res = im->clone();   static const Point ini(0,0);
    static Point seed(ini), tdf(ini);   Point now(x,y);

    switch(Event)
    {
    case CV_EVENT_LBUTTONDOWN:  seed = now; break;
    case CV_EVENT_LBUTTONUP:    tdf += (now-seed);  break;
    case CV_EVENT_RBUTTONUP:    res.copyTo(*im);    tdf = ini;  break;
    }//end switch

    if(drag==CV_EVENT_FLAG_LBUTTON) *im = onAffine(&res, tdf+(now-seed));
}//end onMouse

static Mat onAffine(Mat* im, Point2f dif)
{
    Point2f org[3],tri[3];  org[1] = Point2f(im->cols/2, 0);
    org[0] = Point2f(0,0);  org[2] = Point2f(0, im->rows/2);
    for(int i=0; i<3; ++i)  tri[i] = org[i] + dif;

    Mat warp = getAffineTransform(org, tri), dst;
    warpAffine(*im, dst, warp, im->size()); return dst;
}//end onAffine

程序效果图:

mode=0
mode=0


mode=1
mode=1


mode=2
mode=2


mode=3
mode=3


mode=4
mode=4


mode=5
mode=5


mode=6
mode=6


mode=7
mode=7


mode=8
mode=8

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值