FaceDetector.C

00001 /*!@file Robots2/Beobot2/HumanRobotInteraction/FaceDetector.C Ice Module to
00002 detect faces    */
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // University of Southern California (USC) and the iLab at USC.         //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Dicky Sihite <sihite@usc.edu>
00034 // $HeadURL: svn://ilab.usc.edu/trunk/saliency/src/Robots/Beobot2/HumanRobotInteaction/FaceDetector.C
00035 // $ $Id: FaceDetector.C 12962 2010-03-06 02:13:53Z irock $
00036 //////////////////////////////////////////////////////////////////////
00037 
00038 #include "Robots/Beobot2/HumanRobotInteraction/FaceDetector.H"
00039 #include "Ice/BeobotEvents.ice.H"
00040 
00041 #include "Raster/Raster.H"
00042 #include "Util/sformat.H"
00043 #include "Image/Image.H"
00044 #include "Ice/IceImageUtils.H"
00045 
00046 #include <sys/stat.h>
00047 
00048 //#define  LOG_FOLDER "../data/logs/"
00049 
00050 // ######################################################################
00051 FaceDetector::FaceDetector(OptionManager& mgr,
00052                const std::string& descrName, const std::string& tagName) :
00053   RobotBrainComponent(mgr, descrName, tagName),
00054   itsOfs(new OutputFrameSeries(mgr)),
00055   itsTimer(1000000),
00056   itsCurrImgID(-1),
00057   itsPrevProcImgID(-1)
00058 {
00059   addSubComponent(itsOfs);
00060 }
00061 
00062 // ######################################################################
00063 FaceDetector::~FaceDetector()
00064 { }
00065 
00066 // ######################################################################
00067 void FaceDetector::start1()
00068 {
00069   // set start time
00070   itsTimer.reset();
00071 }
00072 
00073 
00074 // ######################################################################
00075 void FaceDetector::registerTopics()
00076 {
00077   // subscribe to all sensor data
00078   this->registerSubscription("CameraMessageTopic");
00079 
00080   this->registerPublisher("FacesMessageTopic");
00081 }
00082 
00083 // ######################################################################
00084 void FaceDetector::evolve()
00085 {
00086   // check if the current image is updated
00087   its_Curr_Img_mutex.lock();
00088   bool newImageFlag = (itsPrevProcImgID < itsCurrImgID);
00089   its_Curr_Img_mutex.unlock();
00090 
00091   // if so, process
00092   if(newImageFlag)
00093     {
00094       itsTimer.reset();
00095 
00096       its_Curr_Img_mutex.lock();
00097       itsProcImg = itsCurrImg;
00098       itsPrevProcImgID = itsCurrImgID;
00099       its_Curr_Img_mutex.unlock();
00100 
00101       // find faces
00102       Image<PixRGB<byte> > res = findFaces(itsProcImg);
00103 
00104       // display the image
00105       itsOfs->writeRGB(res, "display");
00106       itsOfs->updateNext();
00107       LINFO("time: %15.3f", itsTimer.get()/1000.0);
00108 
00109       // publish FacesMessage
00110       BeobotEvents::FacesMessagePtr msg =
00111         new BeobotEvents::FacesMessage;
00112       msg->RequestID = itsPrevProcImgID;
00113 
00114       its_Curr_Res_mutex.lock();
00115       LINFO("Number of faces detected : %"ZU, itsCurrentFacesFound.size());
00116       for(uint i = 0; i < itsCurrentFacesFound.size(); i++)
00117         {
00118           ImageIceMod::RectangleIce rect;
00119           rect.tl.i = itsCurrentFacesFound[i].top();
00120           rect.tl.j = itsCurrentFacesFound[i].left();
00121           rect.br.i = itsCurrentFacesFound[i].bottomO();
00122           rect.br.j = itsCurrentFacesFound[i].rightO();
00123           msg->faces.push_back(rect);
00124           LINFO("[%3d,%3d,%3d,%3d]", rect.tl.i,rect.tl.j,rect.br.i,rect.br.j );
00125         }
00126       its_Curr_Res_mutex.unlock();
00127 
00128       // publish the message
00129       LINFO("[%6d] Publishing Faces Message", itsCurrMessageID++);
00130       publish("FacesMessageTopic", msg);
00131     }
00132 }
00133 
00134 // ######################################################################
00135 void FaceDetector::updateMessage(const RobotSimEvents::EventMessagePtr& eMsg,
00136     const Ice::Current&)
00137 {
00138   // reset the timer
00139   // itsTimer.reset();
00140   // camera message
00141   if(eMsg->ice_isA("::BeobotEvents::CameraMessage"))
00142   {
00143     // store the image
00144     BeobotEvents::CameraMessagePtr cameraMsg =
00145       BeobotEvents::CameraMessagePtr::dynamicCast(eMsg);
00146 
00147     int currRequestID = cameraMsg->RequestID;
00148     LINFO("Got a CameraMessage with Request ID = %d",
00149           currRequestID);
00150     Image<PixRGB<byte> > ima = Ice2Image<PixRGB<byte> >(cameraMsg->image);
00151 
00152     // this line was to find face, moved up to evolve
00153     its_Curr_Img_mutex.lock();
00154     itsCurrImg = ima;
00155     itsCurrImgID = cameraMsg->RequestID;
00156     its_Curr_Img_mutex.unlock();
00157 
00158     LINFO("time: %15.3f", itsTimer.get()/1000.0);
00159   }
00160 }
00161 
00162 // ######################################################################
00163 Image<PixRGB<byte> > FaceDetector::findFaces(Image<PixRGB<byte> > ima)
00164 {
00165   Image<PixRGB<byte> > res;
00166   IplImage *img = img2ipl(ima);
00167 
00168 
00169   int scale = 1;
00170 
00171   // Create a string that contains the cascade name
00172   const char* cascade_name =
00173     "haarcascade_frontalface_alt.xml";
00174 
00175   // Load a HaarClassifierCascde
00176   CvHaarClassifierCascade* cascade =
00177     (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
00178 
00179   // Check whether the cascade has loaded successfully.
00180   // Else report and error and quit
00181   if( !cascade )
00182     LFATAL("ERROR: Could not load classifier cascade");
00183 
00184   // Create a new image based on the input image
00185   IplImage* temp =
00186     cvCreateImage( cvSize(img->width/scale,img->height/scale), 8, 3 );
00187 
00188   // Create two points to represent the face locations
00189   CvPoint pt1, pt2;
00190   int i;
00191 
00192   // Clear the memory storage which was used before
00193   CvMemStorage* storage = 0;
00194   storage = cvCreateMemStorage(0);
00195   cvClearMemStorage( storage );
00196 
00197   std::vector<Rectangle> tempResults;
00198 
00199   // Find whether the cascade is loaded, to find the faces. If yes, then:
00200   if( cascade )
00201     {
00202 
00203       // There can be more than one face in an image.
00204       // So create a growable sequence of faces.
00205       // Detect the objects and store them in the sequence
00206       CvSeq* faces = cvHaarDetectObjects( img, cascade, storage,
00207                                           1.1, 2, CV_HAAR_DO_CANNY_PRUNING,
00208                                           cvSize(40, 40) );
00209 
00210       // Loop the number of faces found.
00211       for( i = 0; i < (faces ? faces->total : 0); i++ )
00212         {
00213           // Create a new rectangle for drawing the face
00214           CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
00215 
00216           // Find the dimensions of the face,and scale it if necessary
00217           pt1.x = r->x*scale;
00218           pt2.x = (r->x+r->width)*scale;
00219           pt1.y = r->y*scale;
00220           pt2.y = (r->y+r->height)*scale;
00221 
00222           // Draw the rectangle in the input image
00223           cvRectangle( img, pt1, pt2, CV_RGB(255,0,0), 3, 8, 0 );
00224 
00225           // store rectangle to publish later
00226           tempResults.push_back
00227             (Rectangle::tlbrO(pt1.y,pt1.x,pt2.y,pt2.x));
00228         }
00229     }
00230 
00231   // Release the temp image created.
00232   cvReleaseImage( &temp );
00233 
00234   // storing data
00235   its_Curr_Res_mutex.lock();
00236   itsCurrentFacesFound.clear();
00237   itsCurrentFacesFound = tempResults;
00238   // for (uint j = 0; j < tempResults.size(); j++)
00239   //   {
00240   //     //      itsCurrentFacesFound
00241   //   }
00242   its_Curr_Res_mutex.unlock();
00243 
00244   res = ipl2rgb(img);
00245   return res;
00246 }
00247 
00248 // ######################################################################
00249 /* So things look consistent in everyone's emacs... */
00250 /* Local Variables: */
00251 /* indent-tabs-mode: nil */
00252 /* End: */
Generated on Sun May 8 08:41:17 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3