www.pudn.com > facedetectDLL_expressions.zip > facedetect2.cpp


/*M/////////////////////////////////////////////////////////////////////////////////////// 
// 
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 
// 
//  By downloading, copying, installing or using the software you agree to this license. 
//  If you do not agree to this license, do not download, install, 
//  copy or use the software. 
// 
// 
//                        Intel License Agreement 
//                For Open Source Computer Vision Library 
// 
// Copyright (C) 2000, Intel Corporation, all rights reserved. 
// Third party copyrights are property of their respective owners. 
// 
// Redistribution and use in source and binary forms, with or without modification, 
// are permitted provided that the following conditions are met: 
// 
//   * Redistribution's of source code must retain the above copyright notice, 
//     this list of conditions and the following disclaimer. 
// 
//   * Redistribution's in binary form must reproduce the above copyright notice, 
//     this list of conditions and the following disclaimer in the documentation 
//     and/or other materials provided with the distribution. 
// 
//   * The name of Intel Corporation may not be used to endorse or promote products 
//     derived from this software without specific prior written permission. 
// 
// This software is provided by the copyright holders and contributors "as is" and 
// any express or implied warranties, including, but not limited to, the implied 
// warranties of merchantability and fitness for a particular purpose are disclaimed. 
// In no event shall the Intel Corporation or contributors be liable for any direct, 
// indirect, incidental, special, exemplary, or consequential damages 
// (including, but not limited to, procurement of substitute goods or services; 
// loss of use, data, or profits; or business interruption) however caused 
// and on any theory of liability, whether in contract, strict liability, 
// or tort (including negligence or otherwise) arising in any way out of 
// the use of this software, even if advised of the possibility of such damage. 
// 
//M*/ 
 
#include "cvfltk.h" 
#include "highgui.h" 
#include "cv.h" 
#include "cvaux.h" 
#include  
#include  
#include  
 
class VideoWindow; 
 
Fl_Window *root_window=(Fl_Window *)0; 
VideoWindow* video_window = 0; 
CvCapture* capture = 0; 
CvAVIWriter* writer = 0; 
static int started = 0; 
double timeout = 0.005; 
IplImage* video_image = 0; 
double old_pos = 0; 
Fl_Value_Slider* video_pos = 0; 
int guard = 0; 
int is_avi = 0; 
int is_recorded = 0; 
double fps = -1; 
double fps_alpha = 0.1; 
char fps_buffer[100]; 
double cpu_freq = 0; 
double prev_frame_stamp = 0; 
int start_pos = 0; 
int total_frames0 = 0; 
int total_frames = 0; 
int is_loopy = 0; 
 
Fl_Button* stop_button = 0; 
Fl_Button* play_button = 0; 
Fl_Button* video_button = 0; 
Fl_Button* cam_button = 0; 
Fl_Button* record_button = 0; 
Fl_Box* fps_box = 0; 
 
#define ORIG_WIN_SIZE  24 
 
#define MIN_NEIGHBORS 2 
 
static CvMemStorage* storage = cvCreateMemStorage(); 
static CvHidHaarClassifierCascade* hid_cascade = 0; 
 
int InitFaceDetect( const char* classifier_cascade_path ) 
{ 
    CvHaarClassifierCascade* cascade = cvLoadHaarClassifierCascade( 
        classifier_cascade_path && strlen(classifier_cascade_path) > 0 ? 
        classifier_cascade_path : "", 
        cvSize( ORIG_WIN_SIZE, ORIG_WIN_SIZE )); 
    if( !cascade ) 
        return 0; 
    hid_cascade = cvCreateHidHaarClassifierCascade( cascade ); 
    cvReleaseHaarClassifierCascade( &cascade ); 
    return 1; 
} 
 
void DetectAndDrawFaces( IplImage* img ) 
{ 
    if( hid_cascade && img ) 
    { 
        int scale = 2; 
        CvSize img_size = cvGetSize( img ); 
        IplImage* temp = cvCreateImage( cvSize(img_size.width/2,img_size.height/2), 8, 3 ); 
        int i; 
 
        cvPyrDown( img, temp ); 
        cvClearMemStorage( storage ); 
 
        if( hid_cascade ) 
        { 
            CvSeq* faces = cvHaarDetectObjects( temp, hid_cascade, storage, 1.2, 2, 1 ); 
            for( i = 0; i < (faces ? faces->total : 0); i++ ) 
            { 
                CvRect r = *(CvRect*)cvGetSeqElem( faces, i ); 
                cvRectangle( img, 
                             cvPoint(r.x*scale,/*img->height - */r.y*scale), 
                             cvPoint((r.x+r.width)*scale,/*img->height - */(r.y+r.height)*scale), 
                             CV_RGB(0,255,0), 3 ); 
            } 
        } 
 
        cvReleaseImage( &temp ); 
    } 
} 
 
class VideoWindow : public Fl_Box 
{ 
public: 
    VideoWindow( int x, int y, int w, int h, const char* t = 0 ); 
    ~VideoWindow(); 
    void draw(); 
}; 
 
VideoWindow::VideoWindow( int x, int y, int w, int h, const char* t ): 
    Fl_Box( x, y, w, h, t ) 
{ 
} 
 
VideoWindow::~VideoWindow() 
{ 
} 
 
void VideoWindow::draw() 
{ 
} 
 
static void end_capture() 
{ 
    started = 0; 
    cvReleaseCapture( &capture ); 
} 
 
static void cb_Stop( Fl_Widget*, void* ); 
static void cb_StartStopRecord( Fl_Widget*, void* ); 
static void cb_Exit( Fl_Widget*, void* ); 
 
static double get_time_accurate(void) 
{ 
    return (double)cvGetTickCount()*1e-3/(cpu_freq+1e-10); 
} 
 
static void get_next_frame(void*) 
{ 
    static int repositioning = 0; 
    IplImage* frame = 0; 
    double new_pos = video_pos->value(); 
     
    if( (new_pos-old_pos >= 1e-10 || new_pos-old_pos <= -1e-10) && !repositioning) 
    { 
        video_window->redraw(); 
        cvSetCaptureProperty( capture, CV_CAP_PROP_POS_AVI_RATIO, new_pos ); 
        new_pos = cvGetCaptureProperty( capture, CV_CAP_PROP_POS_AVI_RATIO ); 
        printf("Repositioning\n"); 
        repositioning = 1; 
    } 
    else 
    { 
        new_pos = cvGetCaptureProperty( capture, CV_CAP_PROP_POS_AVI_RATIO ); 
        video_pos->value(new_pos); 
        repositioning = 0; 
    } 
    old_pos = new_pos; 
    frame = cvQueryFrame( capture ); 
 
    if( frame == 0 && is_avi ) 
    { 
        cb_Stop(0,0); 
        return; 
    } 
 
    if( video_window && frame ) 
    { 
        if( video_window->w() < frame->width || video_window->h() < frame->height ) 
            root_window->size( (short)(frame->width + 40), (short)(frame->height + 150)); 
 
        CvRect rect = { video_window->x(), video_window->y(), 
                        frame->width, frame->height }; 
         
        if( !video_image || video_image->width < rect.width || 
            video_image->height < rect.height ) 
        { 
            cvReleaseImage( &video_image ); 
            video_image = cvCreateImage( cvSize( rect.width, rect.height ), 8, 3 ); 
        } 
 
        cvSetImageROI( video_image, cvRect(0,0,rect.width, rect.height)); 
        if( frame->origin == 1 ) 
            cvFlip( frame, video_image, 0 ); 
        else 
            cvCopy( frame, video_image, 0 ); 
 
        DetectAndDrawFaces( video_image ); 
        if( writer && is_recorded ) 
        { 
            cvWriteToAVI( writer, video_image ); 
        } 
        cvCvtColor( video_image, video_image, CV_RGB2BGR ); 
 
        uchar* data = 0; 
        int step = 0; 
        CvSize size; 
        cvGetRawData( video_image, &data, &step, &size ); 
 
        video_window->redraw(); 
        fl_draw_image( (uchar*)data, video_window->x(), video_window->y(), 
                       size.width, size.height, 3, step ); 
    } 
 
    if( started ) 
    { 
        double cur_frame_stamp = get_time_accurate(); 
        // update fps 
        if( fps < 0 ) 
            fps = 1000/(cur_frame_stamp - prev_frame_stamp); 
        else 
            fps = (1-fps_alpha)*fps + fps_alpha*1000/(cur_frame_stamp - prev_frame_stamp); 
        prev_frame_stamp = cur_frame_stamp; 
        sprintf( fps_buffer, "FPS: %5.1f", fps ); 
        fps_box->label( fps_buffer ); 
        fps_box->redraw(); 
        if( total_frames > 0 ) 
        { 
            if( --total_frames == 0 ) 
                if( !is_loopy ) 
                    cb_Exit(0,0); 
                else 
                { 
                    total_frames = total_frames0; 
                    cvSetCaptureProperty( capture, CV_CAP_PROP_POS_FRAMES, start_pos ); 
                } 
        } 
        Fl::add_timeout( timeout, get_next_frame, 0 ); 
    } 
} 
 
static void cb_PauseResume( Fl_Widget*, void* ) 
{ 
    video_button->deactivate(); 
    cam_button->deactivate(); 
    stop_button->activate(); 
 
    if( !started ) 
    { 
        started = 1; 
        play_button->label("@||"); 
        play_button->activate(); 
        play_button->redraw(); 
        stop_button->activate(); 
        stop_button->redraw(); 
        record_button->activate(); 
 
        video_window->redraw(); 
        prev_frame_stamp = get_time_accurate(); 
        Fl::add_timeout( timeout, get_next_frame, 0 ); 
    } 
    else 
    { 
        started = 0; 
        play_button->label("@>"); 
        play_button->redraw(); 
    } 
} 
 
 
static void cb_Stop( Fl_Widget*, void* ) 
{ 
    if( started ) 
        cb_PauseResume(0,0); 
    if( is_recorded ) 
        cb_StartStopRecord(0,0); 
    cvSetCaptureProperty( capture, CV_CAP_PROP_POS_AVI_RATIO, 0 ); 
    video_button->activate(); 
    cam_button->activate(); 
    stop_button->deactivate(); 
    record_button->deactivate(); 
} 
 
static void cb_StartAVI( const char* newfile, int start_pos, int was_started ) 
{ 
    if( newfile != 0 ) 
    { 
        end_capture(); 
        capture = cvCaptureFromAVI( newfile ); 
        if( capture ) 
        { 
            was_started = 1; 
            if( start_pos != 0 ) 
                cvSetCaptureProperty( capture, CV_CAP_PROP_POS_FRAMES, start_pos ); 
        } 
        is_avi = 1; 
    } 
 
    if( was_started ) 
        cb_PauseResume(0,0); 
} 
 
 
static void cb_Open( Fl_Widget*, void* ) 
{ 
    char filename[1000]; 
    filename[0] = '\0'; 
    int was_started = 0; 
     
    if( started ) 
    { 
        was_started = 1; 
        cb_PauseResume(0,0); 
    } 
 
    char *newfile = fl_file_chooser("Open File?", "*", filename); 
    cb_StartAVI( newfile, 0, was_started ); 
} 
 
 
static void cb_StartCam( Fl_Widget*, void* ) 
{ 
    if( started ) 
        cb_PauseResume(0,0); 
    end_capture(); 
#ifdef WIN32     
    Sleep(10); 
#endif     
    is_avi = 0; 
    capture = cvCaptureFromCAM( -1 ); 
    cb_PauseResume(0,0); 
} 
 
 
static void cb_StartStopRecord( Fl_Widget*, void* ) 
{ 
    if( !is_recorded ) 
    { 
        if( video_image ) 
        { 
            writer = cvCreateAVIWriter( "c:\\test.avi", -1, 15, cvGetSize( video_image )); 
            if( writer ) 
            { 
                record_button->box( FL_DOWN_BOX ); 
                is_recorded = 1; 
            } 
        } 
    } 
    else 
    { 
        record_button->box( FL_UP_BOX ); 
        cvReleaseAVIWriter( &writer ); 
        is_recorded = 0; 
    } 
} 
 
static void cb_AutoRun( void* _aviname ) 
{ 
    char* aviname = (char*)_aviname; 
    char* ext_pos = strrchr( aviname, '.' ); 
    if( ext_pos ) 
    { 
        char* colon_pos = strchr( ext_pos, ':' ); 
        if( colon_pos ) 
        { 
            *colon_pos = '\0'; 
            start_pos = strtoul( colon_pos+1, &colon_pos, 10 ); 
            if( colon_pos && *colon_pos == ':' ) 
                total_frames0 = total_frames = strtoul( colon_pos+1, &colon_pos, 10 ); 
            if( colon_pos && *colon_pos == ':' ) 
                is_loopy = 1; 
        } 
    } 
 
    cb_StartAVI( aviname, start_pos, 0 ); 
} 
 
 
static void cb_Exit( Fl_Widget*, void* ) 
{ 
    cvReleaseCapture( &capture ); 
    cvReleaseAVIWriter( &writer ); 
    exit(0); 
} 
 
const int root_w = 400, root_h = 400; 
 
int main( int argc, char **argv ) 
{ 
    const char* facebaseopt="--facebase="; 
    char* classifierbase = 0; 
    char* aviname = 0; 
    int auto_run = 0; 
     
    if( argc > 1 && argv[argc-1][0] != '-' ) 
    { 
        aviname = argv[argc-1]; 
        auto_run = 1; 
        argc--; 
    } 
     
    if( argc > 1 && strncmp(argv[argc-1],facebaseopt,strlen(facebaseopt))==0 ) 
    { 
        classifierbase=argv[argc-1] + strlen(facebaseopt); 
        argc--; 
    } 
     
    if( !InitFaceDetect(classifierbase)) 
    { 
        fprintf( stderr, "Could not locate face classifier base at %s\n" 
                         "Use --facebase= option to specify the base\n", 
                 classifierbase ); 
        return -1; 
    } 
	 
    cpu_freq = cvGetTickFrequency();  
    printf("Tick frequency (*10^-6): %g\n", cpu_freq ); 
  
    Fl_Window* w; 
    { 
        Fl_Window* o = root_window = new Fl_Window( root_w, root_h ); 
        w = o; 
        { 
            Fl_Tabs* o = new Fl_Tabs( 10, 10, root_w - 20, root_h - 100 ); 
            // camera tab 
            { 
                Fl_Group* o = new Fl_Group( 10, 30, root_w - 20, root_h - 110, "Face Detection" ); 
                { 
                    VideoWindow* o = new VideoWindow( 15, 35, root_w - 30, root_h - 120 ); 
                    video_window = o; 
                    o->box( FL_BORDER_BOX ); 
                    o->color(0); 
                } 
                o->end(); 
            } 
            o->end(); 
            Fl_Group::current()->resizable(o); 
        } 
        { 
            const int bwidth = 30, bheight = 30; 
            play_button = new Fl_Button( 10, root_h - 35, bwidth, bheight, "@>" ); 
            play_button->callback((Fl_Callback*)cb_PauseResume); 
            play_button->deactivate(); 
            stop_button = new Fl_Button( 10 + bwidth, root_h - 35, bwidth, bheight, "@square" ); 
            stop_button->callback((Fl_Callback*)cb_Stop); 
            stop_button->deactivate(); 
            video_button = new Fl_Button( 10 + bwidth*2, root_h - 35, bwidth, bheight, "..." ); 
            video_button->callback((Fl_Callback*)cb_Open); 
            cam_button = new Fl_Button( 10 + bwidth*3, root_h - 35, bwidth, bheight, "[o]" ); 
            cam_button->callback((Fl_Callback*)cb_StartCam); 
            video_pos = new Fl_Value_Slider( 10 + bwidth*4 + 10, root_h - 35, 200, 20, "Position" ); 
            video_pos->type( FL_HOR_NICE_SLIDER ); 
            record_button = new Fl_Button( 10 + bwidth*4 + 230, root_h - 35, bwidth, bheight, "@circle" ); 
            record_button->labelcolor(FL_RED); 
            record_button->callback((Fl_Callback*)cb_StartStopRecord ); 
            record_button->deactivate(); 
            fps_box = new Fl_Box( 10, root_h - 75, bwidth*4, bheight, "" ); 
            fps_box->box( FL_DOWN_BOX ); 
        } 
        o->end(); 
    } 
    Fl::visual(FL_RGB); 
    w->show(argc, argv); 
    if( auto_run ) 
        Fl::add_timeout( 0.1, cb_AutoRun, aviname ); 
    Fl::run(); 
    cb_Exit(0,0); 
    return 0; 
}