00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "FaceDetection.h"
00031 #include "XMLTag.h"
00032
00033 #include <iostream>
00034 #include <cstdio>
00035
00036
00037 #include "IplImageReading.h"
00038
00039 #include "ImageSubscription.h"
00040
00041 #include "DetectedFace.h"
00042
00043 #define XML_ATTRIBUTE_CASCADE_NAME "cascade_name"
00044 #define XML_ATTRIBUTE_NESTED_CASCADE_NAME "nested_cascade_name"
00045 #define XML_ATTRIBUTE_SCALE "scale"
00046
00047
00048 using namespace cop;
00049
00050 FaceDetection::FaceDetection()
00051 {
00052 printf("FaceDetection created\n");
00053 }
00054
00055 FaceDetection::~FaceDetection(void)
00056 {
00057 }
00058
00059 XMLTag* FaceDetection::Save()
00060 {
00061 XMLTag* tag = new XMLTag(GetName());
00062 return tag;
00063 }
00064
00065
00066 void FaceDetection::SetData(XMLTag* tag)
00067 {
00068 if(tag != NULL)
00069 {
00070 cascade_name_ = tag->GetProperty(XML_ATTRIBUTE_CASCADE_NAME, "");
00071 nested_cascade_name_ = tag->GetProperty(XML_ATTRIBUTE_NESTED_CASCADE_NAME, "");
00072 scale_ = tag->GetPropertyDouble(XML_ATTRIBUTE_SCALE, 1.5);
00073
00074 if( !nested_cascade_.load( nested_cascade_name_ ) )
00075 cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;
00076
00077 if( !cascade_.load( cascade_name_ ) )
00078 {
00079 cerr << "ERROR: Could not load classifier cascade" << endl;
00080 cerr << "Usage: facedetect [--cascade=\"<cascade_path>\"]\n"
00081 " [--nested-cascade[=\"nested_cascade_path\"]]\n"
00082 " [--scale[=<image scale>\n"
00083 " [filename|camera_index]\n" ;
00084
00085 }
00086 }
00087 }
00088
00089 double angle_two_pixel(double x1, double y1, double x2, double y2, MinimalCalibration& calib)
00090 {
00091 double X1 = (x1 - calib.proj_center_x)*calib.pix_size_x;
00092 double Y1 = (y1 - calib.proj_center_y)*calib.pix_size_y;
00093 double Z1 = calib.focal_length;
00094 double X2 = (x2 - calib.proj_center_x)*calib.pix_size_x;
00095 double Y2 = (y2 - calib.proj_center_y)*calib.pix_size_y;
00096 double Z2 = calib.focal_length;
00097
00098 printf("in: x1 %f, y1 %f, x2 %f,y2 %f\n", x1, y1, x2, y2);
00099 printf("3d: x1 %f, y1 %f,z1 %f, x2 %f,y2 %f, z2 %f\n", X1, Y1, Z1, X2, Y2, Z2);
00100 double ret = (((X1 * X2) + (Y1 * Y2) + (Z1 * Z2)) / (sqrt( X1*X1 + Y1*Y1 + Z1*Z1) * sqrt(X2*X2 + Y2*Y2 + Z2*Z2)));
00101 printf("res: acos(%f)\n", ret);
00102 ret = acos(ret);
00103 printf("res: %f\n", ret);
00104 return ret;
00105 }
00106
00107 RelPose* distance_to_3d(RelPose *sensor_pose, MinimalCalibration &calib, double length_min,
00108 double length_max, double x, double y, double cov_width, double cov_height)
00109 {
00110 printf("istance_to_3d with lmin %f lmax %f x %f y %f co_w %f co_h%f\n ",
00111 length_min, length_max, x, y, cov_width, cov_height);
00112 Matrix m(4,4), cov(6,6);
00113 double X, Y, Z;
00114 X = (x - calib.proj_center_x)*calib.pix_size_x;
00115 Y = (y - calib.proj_center_y)*calib.pix_size_y;
00116 Z = calib.focal_length;
00117 double norm = sqrt( X*X + Y*Y + Z*Z);
00118
00119 X *= (length_max + length_min)/(2*norm);
00120 Y *= (length_max + length_min)/(2*norm);
00121 Z *= (length_max + length_min)/(2*norm);
00122
00123 m << 1.0 << 0.0 << 0.0 << X
00124 << 0.0 << 1.0 << 0.0 << Y
00125 << 0.0 << 0.0 << 1.0 << Z
00126 << 0.0 << 0.0 << 0.0 << 1.0;
00127
00128 cov << cov_width / 2 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0
00129 << 0.0 << cov_height / 2<< 0.0 << 0.0 << 0.0 << 0.0
00130 << 0.0 << 0.0 << (length_max - length_min)/2 << 0.0 << 0.0 << 0.0
00131 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0
00132 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0
00133 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0;
00134 return RelPoseFactory::FRelPose(sensor_pose, m, cov);
00135 }
00136
00137
00138
00139
00140
00141 std::vector<RelPose*> FaceDetection::Perform(std::vector<Sensor*> sensors, RelPose* pose, Signature& object, int &numOfObjects, double& qualityMeasure)
00142 {
00143 std::vector<RelPose*> results;
00144 int i = 0;
00145 double t = 0;
00146 vector<Rect> faces;
00147 DetectedFace* face_descr = (DetectedFace*)object.GetElement(0, DESCRIPTOR_DETECTEDFACE);
00148 try
00149 {
00150 ScopedCvMat_t image (sensors, ReadingType_IplImage);
00151
00152 RelPose* sensor_pose = image.sensor_pose_at_capture_time;
00153
00154 Mat gray, smallImg( cvRound ((*image).rows/scale_), cvRound((*image).cols/scale_), CV_8UC1 );
00155 cvtColor( (*image), gray, CV_BGR2GRAY );
00156 resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );
00157 equalizeHist( smallImg, smallImg );
00158
00159 t = (double)cvGetTickCount();
00160 cascade_.detectMultiScale( smallImg, faces,
00161 1.1, 2, 0
00162
00163
00164 |CV_HAAR_SCALE_IMAGE
00165 ,
00166 Size(30, 30) );
00167 t = (double)cvGetTickCount() - t;
00168 printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );
00169 for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
00170 {
00171 Mat smallImgROI;
00172 vector<Rect> nestedObjects;
00173 Point center;
00174 int radius;
00175
00176 printf("Enter inner loop\n");
00177
00178 center.x = cvRound((r->x + r->width*0.5)*scale_);
00179 center.y = cvRound((r->y + r->height*0.5)*scale_);
00180 radius = cvRound((r->width + r->height)*0.25*scale_);
00181
00182 if( nested_cascade_.empty() )
00183 continue;
00184 smallImgROI = smallImg(*r);
00185 nested_cascade_.detectMultiScale( smallImgROI, nestedObjects,
00186 1.1, 2, 0
00187
00188
00189
00190 |CV_HAAR_SCALE_IMAGE
00191 ,
00192 Size(30, 30) );
00193 double max_face_height = 0.30;
00194 double min_face_height = 0.20;
00195 double max_face_width = 0.25;
00196 double min_face_width = 0.15;
00197 printf("After nested cascade\n");
00198
00199 vector<Rect>::const_iterator nr = nestedObjects.begin();
00200 if(nr == nestedObjects.end())
00201 {
00202
00203 double alpha = angle_two_pixel(r->x ,
00204 r->y + r->height*0.5,
00205 r->x + r->width,
00206 r->y + r->height*0.5, image.calib);
00207
00208 double beta = angle_two_pixel(r->x + r->width*0.5,
00209 r->y,
00210 r->x + r->width*0.5,
00211 r->y + r->height, image.calib);
00212
00213 double length_min = min_face_height / (2* tan(alpha));
00214 double length_max = max_face_height / (2* tan(alpha));
00215
00216 length_min = max(length_min, min_face_width / (2* tan(beta)));
00217 length_max = min(length_max, max_face_width / (2* tan(beta)));
00218
00219 RelPose* pose = distance_to_3d(sensor_pose, image.calib, length_min, length_max,
00220 center.x, center.y, max_face_width - min_face_width,
00221 max_face_height - min_face_height);
00222 pose->m_qualityMeasure = 1.0;
00223 qualityMeasure = 1.0;
00224 results.push_back(pose);
00225 std::vector<double> vec;
00226 vec.push_back(center.x);
00227 vec.push_back(center.y);
00228 vec.push_back((r->width + r->height)*0.25*scale_);
00229 face_descr->m_lastlyDetectedFaces[pose->m_uniqueID] = (vec);
00230 if(results.size() == (unsigned)numOfObjects)
00231 break;
00232 }
00233
00234 for( ; nr != nestedObjects.end(); nr++ )
00235 {
00236
00237 printf("Innerst loop\n");
00238
00239 center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale_);
00240 center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale_);
00241
00242
00243 double alpha = angle_two_pixel(r->x + nr->x,
00244 r->y + nr->y + nr->height*0.5,
00245 r->x + nr->x + nr->width,
00246 r->y + nr->y + nr->height*0.5, image.calib);
00247
00248 double beta = angle_two_pixel(r->x + nr->x + nr->width*0.5,
00249 r->y + nr->y,
00250 r->x + nr->x + nr->width*0.5,
00251 r->y + nr->y + nr->height, image.calib);
00252
00253 double length_min = min_face_height / (2* tan(alpha));
00254 double length_max = max_face_height / (2* tan(alpha));
00255
00256 length_min = max(length_min, min_face_width / (2* tan(beta)));
00257 length_max = min(length_max, max_face_width / (2* tan(beta)));
00258
00259 RelPose* pose = distance_to_3d(sensor_pose, image.calib, length_min, length_max,
00260 center.x, center.y, max_face_width - min_face_width,
00261 max_face_height - min_face_height);
00262 pose->m_qualityMeasure = 1.0;
00263 qualityMeasure = 1.0;
00264 results.push_back(pose);
00265 std::vector<double> vec;
00266 vec.push_back(center.x);
00267 vec.push_back(center.y);
00268 vec.push_back((nr->width + nr->height)*0.25*scale_);
00269 face_descr->m_lastlyDetectedFaces[pose->m_uniqueID] = (vec);
00270 if(results.size() == (unsigned)numOfObjects)
00271 break;
00272 }
00273 }
00274 }
00275 catch(const char* exception)
00276 {
00277 printf("FaceDetection failed: %s\n", exception);
00278 }
00279 if(results.size() != (unsigned)numOfObjects)
00280 numOfObjects = results.size();
00281
00282 return results;
00283 }
00284
00285 double FaceDetection::CheckSignature(const Signature& object, const std::vector<Sensor*> &sensors)
00286 {
00287 printf("FaceDetection::CheckSignature\n");
00288 if(object.GetElement(0, DESCRIPTOR_DETECTEDFACE) != NULL)
00289 {
00290 for(size_t i = 0; i < sensors.size(); i++)
00291 {
00292 printf("Yes\n");
00293
00294 return 1.0;
00295 }
00296 }
00297 printf("No\n");
00298 return 0.0;
00299 }
00300