faces.cpp

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 <classifiers/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 <classifiers/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

Generated on Tue Feb 22 13:32:15 2011 for Fawkes API by  doxygen 1.4.7