Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * faces.cpp - Faces classifier based on OpenCV 00004 * 00005 * Created: Mon Dec 10 15:47:11 2007 00006 * Copyright 2005-2007 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <fvclassifiers/faces.h> 00025 00026 #include <core/exception.h> 00027 #include <core/exceptions/software.h> 00028 #include <fvutils/color/colorspaces.h> 00029 #include <fvutils/color/conversions.h> 00030 #include <fvutils/adapters/iplimage.h> 00031 00032 #include <cstddef> 00033 #include <opencv/cv.h> 00034 00035 namespace firevision { 00036 #if 0 /* just to make Emacs auto-indent happy */ 00037 } 00038 #endif 00039 00040 /** @class FacesClassifier <fvclassifiers/faces.h> 00041 * Faces classifier. 00042 * This class provides a classifier that uses OpenCV to detect images in the given 00043 * image. The faces are reported back as regions of interest. Each ROI is considered 00044 * to contain a face. 00045 * 00046 * This code is based on the OpenCV example provided and works with the Haar cascade 00047 * files that come with OpenCV. The code is based on investigations by Stefan Schiffer. 00048 * 00049 * @author Tim Niemueller 00050 */ 00051 00052 /** Constructor. 00053 * @param haarcascade_file Haar cascade file to use 00054 * @param pixel_width width of images that will be processed 00055 * @param pixel_height height of images that will be processed 00056 * @param image Optional image that is used by the classifier. If this image is NULL 00057 * an internal IplImage is created and the buffer converted. If you need the buffer 00058 * anyway pass a pointer to this image to do the conversion only once. In that case 00059 * the classifier assume that the image has already been converted! 00060 * @param haar_scale_factor Haar scale factor 00061 * @param min_neighbours minimum neighbours 00062 * @param flags flags, can only be CV_HAAR_DO_CANNY_PRUNING at the moment. 00063 */ 00064 FacesClassifier::FacesClassifier(const char *haarcascade_file, 00065 unsigned int pixel_width, unsigned int pixel_height, 00066 IplImage *image, 00067 float haar_scale_factor, int min_neighbours, int flags) 00068 : Classifier("FacesClassifier") 00069 { 00070 __haar_scale_factor = haar_scale_factor; 00071 __min_neighbours = min_neighbours; 00072 __flags = flags; 00073 00074 __cascade = (CvHaarClassifierCascade *) cvLoad(haarcascade_file); 00075 if ( ! __cascade ) { 00076 throw fawkes::Exception("Could not load Haar casca via OpenCV"); 00077 } 00078 00079 __storage = cvCreateMemStorage(0); 00080 if ( ! __storage ) { 00081 cvReleaseHaarClassifierCascade(&__cascade); 00082 throw fawkes::Exception("Could not initialize OpenCV memory"); 00083 } 00084 00085 if ( image ) { 00086 __image = image; 00087 __own_image = false; 00088 } else { 00089 __image = cvCreateImage(cvSize(pixel_width, pixel_height), IPL_DEPTH_8U, 3); 00090 __own_image = true; 00091 } 00092 } 00093 00094 00095 /** Destructor. */ 00096 FacesClassifier::~FacesClassifier() 00097 { 00098 cvReleaseHaarClassifierCascade(&__cascade); 00099 cvReleaseMemStorage(&__storage); 00100 if ( __own_image ) { 00101 cvReleaseImage(&__image); 00102 } 00103 } 00104 00105 00106 std::list< ROI > * 00107 FacesClassifier::classify() 00108 { 00109 std::list< ROI > *rv = new std::list< ROI >(); 00110 00111 if ( __own_image ) { 00112 IplImageAdapter::convert_image_bgr(_src, __image); 00113 } 00114 00115 CvSeq *face_seq = cvHaarDetectObjects(__image, __cascade, __storage, 00116 __haar_scale_factor, __min_neighbours, __flags); 00117 00118 for ( int i = 0; i < face_seq->total; ++i) { 00119 CvAvgComp el = *(CvAvgComp*)cvGetSeqElem(face_seq, i); 00120 ROI r(el.rect.x, el.rect.y, el.rect.width, el.rect.height, _width, _height); 00121 r.num_hint_points = el.rect.width * el.rect.height; 00122 rv->push_back(r); 00123 } 00124 00125 // sort, smallest first, we define num_hint_points as area enclosed by the ROI 00126 rv->sort(); 00127 00128 return rv; 00129 } 00130 00131 } // end namespace firevision