The Machine Perception Toolbox

[Introduction]- [News]- [Download]- [Screenshots]- [Manual (pdf)]- [Forums]- [API Reference]- [Repository ]

 

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Libraries/blinkDetector/src/main.cc

Go to the documentation of this file.
00001 /*
00002  *  main.cc
00003  *
00004  *  Authors: Ryan Dahl, Ian Fasel, Javier Movellan
00005  *  Fixes:
00006  *
00007  *  Copyright (c) 2003 Machine Perception Laboratory
00008  *  University of California San Diego.
00009  *
00010  * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
00011  *
00012  *    1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00013  *    2. Redistributions 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.
00014  *    3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
00017  *
00018  */
00019 
00020 #include "blink.h"
00021 
00022 #include <list>
00023 #include <Magick++.h>
00024 #include <iostream>
00025 
00026 extern "C" {
00027 #include <math.h>
00028 #include <string.h>
00029 #include <sys/time.h>
00030 #include <stdlib.h>
00031 #ifndef __APPLE_CC__  
00032 #include <argp.h> // argp is a linux specific library.  Doh!
00033 #else
00034 #include <sys/sysctl.h>
00035 #endif
00036 }
00037 
00038 #define FALSE 0
00039 #define TRUE 1 
00040 #define MAX_NUM_IMAGES 10
00041 
00042 #define BINARY
00043 
00044 #ifdef __APPLE_CC__  
00045 bool IsAltiVecAvailable( void )
00046 {
00047   int selectors[2] = { CTL_HW, HW_VECTORUNIT };
00048   int hasVectorUnit = 0;
00049   size_t length = sizeof(hasVectorUnit);
00050   int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0);
00051   if( 0 == error ) return hasVectorUnit != 0;
00052   return FALSE;
00053 }
00054 #endif
00055 
00056 
00057 
00059 #ifndef __APPLE_CC__
00060 const char *argp_program_version = "2.0";
00061 const char *argp_program_bug_address = "ianfasel@cogsci.ucsd.edu";
00062 static char doc[] = "Feature based Face detection, from the Machine Perception Lab at UCSD."
00063 "Previous version was called viola++, after Paul Viola, who described the original algorithm."
00064 "  To just run the face detector on an image file, accepting all defaults, "
00065 "type:\n\t mpisearch <image>\nwhere <image> is the name of the image file. "
00066 "You can also specify the following options:\vEnjoy!"
00067 ;
00068 static struct argp_option options[] = {
00069 //  {"matfile", 'm', "MATFILE", OPTION_ARG_OPTIONAL, "save faceboxes in MATFILE (default: out.m)"},
00070   {"cfile", 'x', "XMLFILE", 0, "Use classifier specified in the xml file XMLFILE"},
00071   {"emotion", 'e', 0, 0, "Use emotion recognition using convolutions on found faces"},
00072   {"nonconvemotion", 'o', 0, 0, "Use emotion recognition using other filters on found faces"},
00073   {"emofile", 'f', "EMOFILE", 0, "Use emotion recognizer weights specified in the xml file EMOFILE"},
00074   {0}
00075 };
00076 #endif //__APPLE_CC__
00077 struct arguments {
00078   char *args[MAX_NUM_IMAGES];   // up to xx images can be processed at once
00079   int matlab;
00080   char matfile[50], cfile[50], emofile[50];
00081   int emoFlag;
00082 };
00083 #ifndef __APPLE_CC__
00084 static error_t parse_opt (int key, char *arg, struct argp_state *state){
00085   // Get input argument from argp_parse, which is our
00086   // arguments pointer.
00087   struct arguments *arguments = static_cast<struct arguments *>(state->input);
00088   
00089   switch(key)
00090     {
00091     case 'm':
00092       arguments->matlab = 1;
00093       if(arg) strcpy(arguments->matfile, arg);
00094       break;
00095     case 'c':
00096       strcpy(arguments->cfile, arg);
00097       break;
00098     case 'e':
00099       arguments->emoFlag = 1;
00100       break;
00101     case 'o':
00102       arguments->emoFlag = 2;
00103       strcpy(arguments->emofile,"nonconvEmo.xml");
00104       break;
00105     case 'f':
00106       strcpy(arguments->emofile, arg);
00107       break;
00108     case ARGP_KEY_ARG:
00109       if(state->arg_num >= 10)   // too many arguments
00110         argp_usage (state);
00111       arguments->args[state->arg_num] = arg;
00112       break;
00113     case ARGP_KEY_NO_ARGS:
00114       argp_usage(state);
00115       break;
00116     case ARGP_KEY_END:
00117       if (state->arg_num <= 0) // not enough arguments
00118         argp_usage(state);
00119       break;
00120 
00121     default:
00122       return ARGP_ERR_UNKNOWN;
00123     }
00124   return 0;
00125 }
00126 
00127 static char args_doc[] = "image1 image2 ... imageN (N <= 10)";
00128 static struct argp argp = {options, parse_opt, args_doc, doc};
00129 #endif //__APPLE_CC__
00130 
00131 
00132 static inline double difftv(const struct timeval &t1, const struct timeval &t0)
00133 { return( (t1.tv_sec -t0.tv_sec )*1.0 +(t1.tv_usec-t0.tv_usec)*1e-6); }
00134 
00135 using namespace Magick;
00136 
00137 int main (int argc, char **argv)
00138 {  
00139   struct arguments arguments;
00140   // default values
00141   strcpy(arguments.matfile,"out.mat");
00142   strcpy(arguments.cfile,"ci.xml");
00143   strcpy(arguments.emofile,"emo.xml");
00144   arguments.emoFlag = 0;
00145   for(int i = 0; i<MAX_NUM_IMAGES; i++)
00146     arguments.args[i] = 0;
00147     
00148   // get values from command line
00149 #ifndef __APPLE_CC__
00150   argp_parse(&argp, argc, argv, 0, 0, &arguments);
00151 #else
00152   int opt_count = 0;
00153   arguments.args[0] = (char *)malloc(256 * sizeof(char));
00154   if(argc==2)
00155     strcpy(arguments.args[0],argv[1]);
00156   else{
00157     arguments.emoFlag = 1;
00158     strcpy(arguments.args[0],argv[2]);
00159   }
00160   if(IsAltiVecAvailable())
00161     cout << "AltiVec detected" << endl;
00162   else
00163     cout << "No AltiVec on this Mac" << endl;
00164   
00165 #endif
00166 
00167   //
00168   // Initialize the MPBlink object
00169   //
00170 
00171   MPBlink blink;
00172 
00173   // 
00174   // Loop through all images
00175   //
00176   int arg_count = -1;
00177   while(arguments.args[++arg_count]!=0){
00178     // Try and open the file.  
00179     try { 
00180       Image image( arguments.args[arg_count] );
00181 
00182       // 
00183       // allocate our buffer and write the pixels to it. 
00184       //
00185       RImage<float> pixels(image.columns(), image.rows());
00186 
00187       image.quantizeColors ( 256 ); // convert to 256 colors
00188       image.quantize( ); // convert to grayscale
00189 
00190       image.write(0,0, image.columns(), image.rows(), "I", FloatPixel, pixels.array);
00191       //image.display();
00192 
00193       cout << "Image: " << arguments.args[arg_count]
00194            << " - " << pixels.width 
00195            << "x" << pixels.height 
00196            << endl;
00197 
00198       FaceBoxList faces;
00199 
00200       // start the clock
00201       struct timeval tv_now, last, tv_first, final;
00202       gettimeofday(&last,0);
00203       int nframes = 31;
00204       double blinkness;
00205       // Search nframes times, using ROI
00206       for(int fc = 0; fc < nframes; ++fc){
00207         faces.clear();
00208         gettimeofday(&last,0);
00209         blinkness = blink.findBlinks(pixels, faces); // mpisearch.search(pixels, faces, 1);
00210         gettimeofday(&tv_now,0);
00211         if(fc == 0){
00212           cout << "blinkness: " << blinkness << endl;
00213           printf("\tThe first search took %g seconds. \n", difftv(tv_now, last));
00214           printf("Initially found %d faces in %s.\n", faces.size(), arguments.args[arg_count]);
00215         }
00216         faces.simplify( 0.2 ); //0.24);
00217         if(fc == 0){
00218           printf("Now found %d.\n", faces.size());
00219           gettimeofday(&tv_first,0);
00220         }
00221       }
00222       gettimeofday(&final,0);
00223       cout << "blinkness: " << blinkness << endl;
00224       printf("\tTheoretical frame rate for one-face tracking & blink detection: %g fps. \n", (nframes-1) / difftv(final, tv_first));
00225       
00226 
00227       if(faces.size() != 0) {
00228         image.strokeColor("white");
00229         image.strokeWidth(1);
00230         image.fillColor("none" );
00231 
00232         while(!faces.empty( ))
00233         {
00234           Square face = faces.front();  
00235           faces.pop_front();
00236 
00237           image.draw( DrawableRectangle(face.x, face.y, 
00238                 face.x + face.size, face.y + face.size));
00239        }        
00240         image.display();
00241       }
00242     }
00243     catch ( ErrorFileOpen &error ) {
00244       cerr << "Error opening file: " 
00245            <<  arguments.args[arg_count]
00246            << ". ImageMagick said: " 
00247            << error.what() 
00248            << endl;
00249     }
00250   } 
00251   return 0;
00252 }

Generated on Mon Nov 8 17:07:41 2004 for MPT by  doxygen 1.3.9.1