00001 #include "FaceOperator.H"
00002 #include <Logger.H>
00003 #include <string>
00004
00005 #include "cv.h"
00006 #include "highgui.h"
00007 #include "cvaux.h"
00008
00009 #include "cvtypes.h"
00010
00011 #include "MyHaar.H"
00012
00013
00014 using namespace std;
00015 using namespace RobotObjects;
00016 using namespace RobotVision;
00017
00018 FaceOperator::FaceOperator(std::string pName) : VisionOperator(pName), mRangeFinder(STRAT_ASSIGNED, "LaserClient"), mPtu(STRAT_ASSIGNED, "PTUClient"), mFaceDetector(pName) {
00019 m_state = STATE_RUN;
00020 g_debug("Registering a SickLaser consumer");
00021 registerConsumer(&mRangeFinder);
00022 g_debug("Registering a PTU consumer");
00023 registerConsumer(&mPtu);
00024 g_debug("Registering a FaceDetector supplier");
00025 registerSupplier(&mFaceDetector);
00026 count = 0;
00027 }
00028
00029 void FaceOperator::initOperator() {
00030 g_debug("Initializing Face Detector");
00031
00032 g_debug("Creating HAAR Cascade");
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 std::string configfile;
00044
00045 if(g_globalConfiguration.haveModuleOption(m_name,"HAARCascadeFile")){
00046 configfile=g_globalConfiguration.getModuleOption(m_name,"HAARCascadeFile");
00047 if(configfile[0]!='/'){
00048 configfile=g_globalConfiguration.getConfigDirectory()+"/"+configfile;
00049 }
00050 }else if(g_globalConfiguration.haveOption("HAARCascadeFile")){
00051 configfile=g_globalConfiguration.getOption("HAARCascadeFile");
00052 if(configfile[0]!='/'){
00053 configfile=g_globalConfiguration.getConfigDirectory()+"/"+configfile;
00054 }
00055 }else{
00056 configfile=g_globalConfiguration.getConfigDirectory()+"/"+"haarcascade_frontalface_default.xml";
00057 }
00058
00059
00060 mCascade = (CvHaarClassifierCascade*)cvLoad( configfile.c_str(), 0, 0, 0 );
00061
00062 if(!g_globalConfiguration.haveModuleOption(m_name,"MinHeight")||
00063 !g_globalConfiguration.haveModuleOption(m_name,"MaxHeight")){
00064 mMinHeight=1;
00065 mMaxHeight=2;
00066 }else{
00067 mMinHeight = atof(g_globalConfiguration.getModuleOption(m_name,"MinHeight").c_str());
00068 mMaxHeight = atof(g_globalConfiguration.getModuleOption(m_name,"MaxHeight").c_str());
00069 }
00070
00071
00072 if(!g_globalConfiguration.haveModuleOption(m_name,"MinSize")||
00073 !g_globalConfiguration.haveModuleOption(m_name,"MaxSize")){
00074 mMinSize=0.08;
00075 mMaxSize=0.4;
00076 }else{
00077 mMinSize = atof(g_globalConfiguration.getModuleOption(m_name,"MinSize").c_str());
00078 mMaxSize = atof(g_globalConfiguration.getModuleOption(m_name,"MaxSize").c_str());
00079 }
00080
00081
00082 mStorage = cvCreateMemStorage(0);
00083
00084 m_state = STATE_RUN;
00085
00086
00087 m_format=FORMAT_CHAR_1_GRAY;
00088 m_stereo=false;
00089
00090
00091
00092 mFrames = 0;
00093 g_debug("Done initializing FD");
00094 }
00095
00096 struct pixel {
00097 char b,g,r;
00098 };
00099
00100 void ColorPixel(void * pImg, int pX, int pY, char pR, char pG, char pB) {
00101 pixel *img = (pixel *)pImg;
00102 if(pX >= 0 && pX < 320 && pY >= 0 && pY < 240) {
00103 img[pY * 320 + pX].r = pR;
00104 img[pY * 320 + pX].g = pG;
00105 img[pY * 320 + pX].b = pB;
00106 }
00107 }
00108 void FaceOperator::DrawLaserDataDots(IplImage *pImg, double *pData, unsigned char r, unsigned char g, unsigned char b) {
00109
00110 double pan, tilt;
00111
00112 GetPTUData(&pan, &tilt);
00113
00114 for(int i = 0; i < 181; i++) {
00115 double radians = i / 180.0 * 3.141592 - (3.141592 / 2.0);
00116
00117 double cp = cos(pan);
00118 double sp = sin(pan);
00119 double ct = cos(tilt);
00120 double st = sin(tilt);
00121
00122 double wx = cos(radians) * pData[i];
00123 double wy = sin(radians) * pData[i];
00124 double wz = 0.38;
00125
00126 double camx = ct * cp * wx + ct * sp * wy + st * wz - .13 * cp * ct ;
00127 double camy = -sp * wx + cp * wy + sp * 0.13 - 0.09;
00128 double camz = -st * cp * wx + -st * sp * wy + ct * wz + 0.13 * cp * st - 1.48 * ct;
00129
00130 int xpix = 320 - int(387.5 * tan(atan2(camy, camx)) + 160);
00131 int ypix = 240 - int(387.5 * tan(atan2(camz, camx)) + 120);
00132
00133 ColorPixel(pImg->imageData, xpix, ypix, r, g, b);
00134 ColorPixel(pImg->imageData, xpix+1, ypix, r, g, b);
00135 ColorPixel(pImg->imageData, xpix-1, ypix, r, g, b);
00136 ColorPixel(pImg->imageData, xpix, ypix+1, r, g, b);
00137 ColorPixel(pImg->imageData, xpix, ypix-1, r, g, b);
00138 }
00139
00140 }
00141
00142
00143 bool done = false;
00144
00145 void FaceOperator::runOperator(RoleImage mImage) {
00146 if(mFrames == 0) {
00147 mBegin.now();
00148 }
00149 mFrames++;
00150
00151 CvPoint pt1, pt2;
00152 char buff[256];
00153
00154 cvClearMemStorage( mStorage );
00155
00156 CvSize imgSize;
00157 imgSize.width = 320;
00158 imgSize.height = 240;
00159
00160
00161
00162
00163
00164
00165
00166
00167 double ranges[181];
00168 for(int i =0; i < 181; i++) { ranges[i] = 99999999; }
00169 GetLaserData(ranges);
00170
00171 GetClosedLaserData(ranges);
00172
00173 double pan, tilt;
00174 GetPTUData(&pan, &tilt);
00175
00176 CvSeq* faces = myHaarDetectObjects( mImage.second, mCascade, mStorage,1.1, 2, CV_HAAR_DO_CANNY_PRUNING, cvSize(20, 20), ranges, pan, tilt, mMinHeight, mMaxHeight, mImage.second,mMinSize,mMaxSize);
00177
00178
00179 mFaceDetector.data.foundFaces.clear();
00180
00181
00182
00183
00184
00185 mFaceDetector.data.foundFaces.clear();
00186
00187
00188 g_logdebug << "Found "<<faces->total<< " faces."<<endl;
00189
00190 for( int i = 0; i < (faces ? faces->total : 0); i++ ){
00191 CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
00192 FaceLocation f;
00193 f.width = r->width;
00194 f.height = r->height;
00195 f.origin.x(r->x);
00196 f.origin.y(r->y);
00197 f.centroid.x(r->x + r->width / 2.0);
00198 f.centroid.y(r->y + r->height / 2.0);
00199 mFaceDetector.data.foundFaces.push_back(f);
00200 g_logdebug << "Just added a face." << endl;
00201
00202 pt1.x = r->x;
00203 pt2.x = (r->x+r->width);
00204 pt1.y = r->y;
00205 pt2.y = (r->y+r->height);
00206
00207 }
00208 mFaceDetector.publishData();
00209 g_logdebug << "Just published some faces" << endl;
00210
00211
00212
00213 ++count;
00214
00215
00216
00217
00218
00219 }
00220
00221 void FaceOperator::quitOperator() {
00222
00223
00224
00225
00226 mEnd.now();
00227 double seconds = mEnd.getSeconds() - mBegin.getSeconds();
00228
00229 g_loginfo << "Frames per second: " << (mFrames / seconds) << endl;
00230 }
00231
00232 void FaceOperator::GetLaserData(double *data) {
00233 bool gotdata = false;
00234
00235 while(mRangeFinder.newInfo()) {
00236 mRangeFinder.getNextInfo();
00237 }
00238 while(mRangeFinder.newData()) {
00239 mRangeFinder.getNextData();
00240 }
00241 if(mRangeFinder.data.ranges.size()) {
00242 for(int i = 0; i < 181; i++) {
00243 data[i] = mRangeFinder.data.ranges[i];
00244 }
00245 }
00246 }
00247
00248 void FaceOperator::GetPTUData(double *pPan, double *pTilt) {
00249 bool gotdata = false;
00250 while(mPtu.newInfo()) {
00251 mPtu.getNextInfo();
00252 gotdata = true;
00253 }
00254 (*pPan) = mPtu.info.pan.getValue();
00255 (*pTilt) = mPtu.info.tilt.getValue();
00256 }
00257 void FaceOperator::GetClosedLaserData(double *pOut) {
00258
00259
00260 double r = 0.3;
00261 PTUnit ptu("safeTomPTUserver");
00262 double data[181];
00263 GetLaserData(data);
00264
00265 float angleMin = mRangeFinder.info.angle_min.getValue();
00266 float angleSep = mRangeFinder.info.theta_separation.getValue();
00267
00268
00269
00270 for (int i = 0; i < 180; i++){
00271 double x = 9999999;
00272 int w = int(asin(r / data[i]) * 180 / 3.14159265358);
00273
00274 if(w == 0) {
00275 pOut[i] = data[i];
00276 }
00277 for (int j = 0; j < w; j++){
00278
00279 float theta = j * 3.1415927 / 180.0;
00280 float xtemp;
00281 if (i+j >= 0 && i+j < 180){
00282 float l = data[i+j];
00283 xtemp = l * cos(theta) - sqrt( r*r - pow(l*sin(theta),2));
00284 if (xtemp < x) {
00285 x = xtemp;
00286 }
00287 }
00288 if (i-j >= 0 && i-j < 180){
00289 double l = data[i-j];
00290 xtemp = l * cos(-theta) - sqrt( r*r - pow(l*sin(-theta),2));
00291 if (xtemp < x){
00292 x = xtemp;
00293 }
00294 }
00295 pOut[i] = x;
00296 }
00297 }
00298 }
00299
00300 extern "C" {
00301 VisionOperator *FaceOperator_factory(std::string name) {
00302 return new FaceOperator(name);
00303 }
00304
00305 class FaceOperatorProxy {
00306 public:
00307 FaceOperatorProxy(){
00308 operatorFactory["FaceOperator"] = FaceOperator_factory;
00309 }
00310 };
00311
00312 FaceOperatorProxy p_Faceoperator;
00313 }
00314
00315