posts - 112, comments - 215, trackbacks - 0, articles - 34
  IT博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

人脸检测的C/C++源代码

Posted on 2006-12-25 10:10 济公 阅读(4168) 评论(8)  编辑 收藏 引用 所属分类: ImageProc
人脸检测的C/C++源代码,曾发表于 OPENCV 的 MAILING LIST,主要是对OPENCV 3.1 版本发布的代码做了一些速度上的优化,并且解决了内存泄漏的问题。这个程序所使用的 Paul Viola 提出(该论文“Rapid Object Detection using a Boosted Cascade of Simple Features”发表在 CVPR01)的 Ada Boosted Cascade 算法可以说是目前最好最快的目标检测算法。

下面是算法的简单描述:

Rapid Object Detection using a Boosted Cascade of Simple Features

This method entails a machine learning approach for visual object detection, which is capable of processing images extremely rapidly and achieving high detection rates.

First it introduces a new image representation called “ Integral Image” which allows the features used by detector to be computed very quickly. The integral image can be computed from an image using a few operations per pixel. Once computed, any one of these Harr-like features can be computed at any scale or location in constant time.

The second is a learning algorithm, based on AdaBoost, which selects a small number of critical visual features from a large set and yields extremely efficient classifiers.

The third is a method for combining increasingly more complex classifiers in a “cascade” which allows background regions of the image to be quickly discarded while spending more computation on promising object-like regions.

The object detection classifies images based on the value of simple features. The simple features used are reminiscent of Haar basis functions. Here it uses three kinds of features: two-rectangle feature, three-rectangle feature and four-rectangle. Rectangle features are somewhat primitive when compared with alternatives such as steerable filters. Steerable filters are excellent for the detailed analysis of boundaries, image compression, and texture analysis. In order to use a small number of features to form an effective classifier, the weak learning algorithm is designed to select the single rectangle feature which best separates the positive and negative examples. For each feature, the weak learner determines the optimal threshold classification function, such that the minimum
number of examples is misclassified. The overall form of the detection process is that of a degenerate decision tree, called a “cascade”.

A positive result from the first classifier triggers the evaluation of a second classifier, which has also been adjusted to achieve very high detection rates. A positive result from the second classifier triggers a third classifiers, and so on. The cascade training process involves two types of tradeoffs. In most cases classifiers with more features will achieve higher detection rates and lower false positive rates. At the same time classifiers with more features require more time to compute.


在OPENCV 3.1 版本,VC6.0下编译通过

====

===
#ifdef _CH_
#define WIN32
#error The file needs cvaux, which is not wrapped yet. Sorry
#endif

#ifndef _EiC
#include cv.h
#include cvaux.h
#include highgui.h

#endif

#ifdef _EiC
#define WIN32
#endif

#define ORIG_WIN_SIZE  24
static CvMemStorage* storage = 0;
static CvHidHaarClassifierCascade* hid_cascade = 0;

#define WINNAME  Result

void detect_and_draw( IplImage* image, IplImage* TempImage );

int main( int argc, char** argv )
{
    CvCapture* capture = 0;

    CvHaarClassifierCascade* cascade =
    cvLoadHaarClassifierCascade( ,
                         cvSize( ORIG_WIN_SIZE, ORIG_WIN_SIZE ));
    hid_cascade = cvCreateHidHaarClassifierCascade( cascade, 0, 0, 0, 1 );
    cvReleaseHaarClassifierCascade( &cascade );

    cvNamedWindow( WINNAME, 1 );
    storage = cvCreateMemStorage(0);
   
    if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
        capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - 0 : 0 );
    else if( argc == 2 )
        capture = cvCaptureFromAVI( argv[1] );

    if( capture )
    {
        IplImage *frame, *temp;
        cvGrabFrame( capture );
        frame = cvRetrieveFrame( capture );
       
        temp = cvCreateImage( cvSize(frame->width/2,frame->height/2), 8, 3 );

        for(;;)
        {
            if( !cvGrabFrame( capture ))
                break;
            frame = cvRetrieveFrame( capture );
            if( !frame )
                break;

            detect_and_draw( frame, temp );

            if( cvWaitKey( 10 ) >= 0 )
            {
                //cvReleaseImage( &frame );
                //cvReleaseImage( &temp );
                cvReleaseCapture( &capture );
                cvDestroyWindow(WINNAME);
                return  0;
            }
        }
    }
    else 
    {
        char* filename = argc == 2 ? argv[1] : (char*)lena.jpg;
        IplImage* image = cvLoadImage( filename, 1 );
        IplImage* temp = cvCreateImage( cvSize(image->width/2,image->height/2), 8, 3 );

        if( image )
        {
            cvFlip( image, image, 0 );
            image->origin = IPL_ORIGIN_BL;
            detect_and_draw( image, temp );
            cvWaitKey(0);
            cvReleaseImage( &image );
            cvReleaseImage( &temp );
        }
        cvDestroyWindow(WINNAME);
        return 0;
    }
    return 0;
}

void detect_and_draw( IplImage* img, IplImage* temp )
{
    int scale = 2;
    CvPoint pt1, pt2;
    int i;

    cvPyrDown( img, temp, CV_GAUSSIAN_5x5 );
#ifdef WIN32
    cvFlip( temp, temp, 0 );
#endif   
    cvClearMemStorage( storage );

    if( hid_cascade )
    {
        CvSeq* faces = cvHaarDetectObjects( temp, hid_cascade, storage,
                                            1.2, 2, CV_HAAR_DO_CANNY_PRUNING );
        for( i = 0; i < (faces ? faces->total : 0); i++ )
        {
            CvRect* r = (CvRect*)cvGetSeqElem( faces, i, 0 );
            pt1.x = r->x*scale;
            pt2.x = (r->x+r->width)*scale;
#ifdef WIN32           
            pt1.y = img->height - r->y*scale;
            pt2.y = img->height - (r->y+r->height)*scale;
#else
            pt1.y = r->y*scale;
            pt2.y = (r->y+r->height)*scale;
#endif           
            cvRectangle( img, pt1, pt2, CV_RGB(255,255,0), 3 );
        }
    }

    cvShowImage(WINNAME, img );
    //cvReleaseImage( &temp );
}

#ifdef _EiC
main(1,facedetect.c);
#endif

Feedback

# re: 人脸检测的C/C++源代码  回复  更多评论   

2006-12-25 14:27 by E代青蛙
TO:帅玲玲
你说的好像是Simulink模型仿真方面的吧,不好意思,我对那个不熟悉,我只用过MATLAB的图像处理。我到群里面给你问下,看看有没有高手在,如果可以找到答案再告诉你。

# re: 人脸检测的C/C++源代码  回复  更多评论   

2006-12-28 13:36 by fvgfbgb
貌似代码比较少,不过应该没有人脸定位吧(就是把人眼的位置标定出来)

# re: 人脸检测的C/C++源代码  回复  更多评论   

2007-12-06 10:33 by wxguan
怎么都没有matlab的阿~~~~我得用matlab实现这段代码哦

# re: 人脸检测的C/C++源代码  回复  更多评论   

2007-12-11 20:24 by 376507954
有没有MATLAB人脸检测?我想要。QQ:376507954

# re: 人脸检测的C/C++源代码  回复  更多评论   

2007-12-11 20:40 by 济公
TO:376507954。不好意思,我没有Matlab的代码,你自己去网上搜索下吧,我想肯定有的。

# re: 人脸检测的C/C++源代码  回复  更多评论   

2011-05-30 10:49 by liuyang
cvLoadHaarClassifierCascade( ,
cvSize( ORIG_WIN_SIZE, ORIG_WIN_SIZE ));
这个函数好像有待你问题啊
只有注册用户登录后才能发表评论。