00001 #include <opencv/cv.h>
00002 #include <opencv/cvaux.h>
00003 #include <opencv/highgui.h>
00004 #include <opencv/ml.h>
00005
00006 #include <iostream>
00007 #include <boost/lexical_cast.hpp>
00008
00009 using namespace cv;
00010
00011 namespace FACE
00012 {
00013 enum FEATURE_TYPE
00014 {
00015 LEFTEYE, RIGHTEYE, NOSE, MOUTH,
00016 };
00017
00019 template<class T>
00020 class FaceFeatures
00021 {
00022 public:
00023
00025 FaceFeatures<T>()
00026 {
00027 }
00028 ;
00029
00031 ~FaceFeatures<T>()
00032 {
00033 }
00034 ;
00035
00036 T lefteye;
00037 T righteye;
00038 T nose;
00039 T mouth;
00040
00044 void sub_offset(int& ox, int& oy)
00045 {
00046 this->lefteye.x -= ox;
00047 this->lefteye.y -= oy;
00048 this->righteye.x -= ox;
00049 this->righteye.y -= oy;
00050 this->mouth.x -= ox;
00051 this->mouth.y -= oy;
00052 this->nose.x -= ox;
00053 this->nose.y -= oy;
00054 }
00055
00059 void add_offset(int& ox, int& oy)
00060 {
00061 this->lefteye.x += ox;
00062 this->lefteye.y += oy;
00063 this->righteye.x += ox;
00064 this->righteye.y += oy;
00065 this->mouth.x += ox;
00066 this->mouth.y += oy;
00067 this->nose.x += ox;
00068 this->nose.y += oy;
00069 }
00070
00073 void scale(double scale)
00074 {
00075 lefteye *= scale;
00076 righteye *= scale;
00077 nose *= scale;
00078 mouth *= scale;
00079 }
00080
00082
00083 std::vector<T> as_vector()
00084 {
00085 std::vector<T> vec;
00086 vec.push_back(lefteye);
00087 vec.push_back(righteye);
00088 vec.push_back(nose);
00089 vec.push_back(mouth);
00090 return vec;
00091 }
00092 ;
00093
00095 bool valid()
00096 {
00097 if (std::isnan(lefteye.x) || std::isnan(lefteye.y))
00098 return false;
00099 if (std::isnan(righteye.x) || std::isnan(righteye.y))
00100 return false;
00101 if (std::isnan(nose.x) || std::isnan(nose.y))
00102 return false;
00103
00104 else
00105 return true;
00106 }
00107 };
00108
00109 }
00110 ;
00111
00112 class FaceNormalizer
00113 {
00114
00115 public:
00121 struct FNConfig
00122 {
00123 bool eq_ill;
00124 bool align;
00125 bool resize;
00126 bool cvt2gray;
00127 bool extreme_illumination_condtions;
00128 };
00129
00131 FaceNormalizer()
00132 {
00133 }
00134 ;
00135
00137 ~FaceNormalizer();
00138
00141 void init();
00142
00146 void init(FNConfig& i_config);
00147
00152 void init(std::string i_classifier_directory, FNConfig& i_config);
00153
00162 void init(std::string i_classifier_directory, std::string i_storage_directory, FNConfig& i_config, int i_epoch_ctr, bool i_debug, bool i_record_scene);
00163
00169 bool normalizeFace(cv::Mat & RGB, cv::Size& norm_size);
00170
00178 bool normalizeFace(cv::Mat& RGB, cv::Mat& XYZ, cv::Size& norm_size, cv::Mat& DM);
00179
00186 bool normalizeFace(cv::Mat & RGB, cv::Mat& XYZ, cv::Size& norm_size);
00187
00188
00190 bool synthFace(cv::Mat &RGB, cv::Mat& XYZ, cv::Size& norm_size, std::vector<cv::Mat>& synth_images);
00191 bool synth_head_poses(cv::Mat& img, cv::Mat& depth, std::vector<cv::Mat>& synth_images);
00192 bool synth_head_poses_relative(cv::Mat& img, cv::Mat& depth, std::vector<cv::Mat>& synth_images);
00193 bool eliminate_background(cv::Mat& RGB, cv::Mat& XYZ, float background_thresh);
00194 bool isolateFace(cv::Mat& RGB, cv::Mat& XYZ);
00195 bool interpolate_head(cv::Mat& RGB, cv::Mat& XYZ);
00196 bool recordFace(cv::Mat&RGB, cv::Mat& XYZ);
00197
00203 bool save_scene(cv::Mat& RGB, cv::Mat& XYZ, std::string path);
00204
00210 bool read_scene(cv::Mat& RGB, cv::Mat& XYZ, std::string path);
00211
00212 FNConfig config_;
00213 protected:
00214
00220 bool normalize_geometry_depth(cv::Mat& img, cv::Mat& depth);
00221
00227 bool rotate_head(cv::Mat& img, cv::Mat& depth);
00228
00233 bool features_from_color(cv::Mat& img);
00234
00239 bool features_from_depth(cv::Mat& depth);
00240
00247 bool detect_feature(cv::Mat& img, cv::Point2f& coords, FACE::FEATURE_TYPE type);
00248
00256 bool projectPointCloud(cv::Mat& RGB, cv::Mat& XYZ, cv::Mat& img_res, cv::Mat& depth_res);
00257
00264 bool projectPoint(cv::Point3f& xyz, cv::Point2f& uv);
00265
00270 void create_DM(cv::Mat& XYZ, cv::Mat& DM);
00271
00276 bool normalize_radiometry(cv::Mat& img);
00277
00283 void extractVChannel(cv::Mat& img, cv::Mat& V);
00284
00289 void subVChannel(cv::Mat& img, cv::Mat& V);
00290
00296 void GammaDCT(cv::Mat& img);
00297
00305 void GammaDoG(cv::Mat& img);
00306
00311 bool normalize_img_type(cv::Mat& in, cv::Mat& out);
00312
00316 void dump_features(cv::Mat& img);
00317
00321 void dump_img(cv::Mat& data, std::string name);
00322
00323 bool initialized_;
00324 int epoch_ctr_;
00325 bool debug_;
00326 bool record_scene_;
00327
00328 std::string storage_directory_;
00329 std::string classifier_directory_;
00330
00331
00332 cv::Mat cam_mat_;
00333 cv::Mat dist_coeffs_;
00334
00335 CvHaarClassifierCascade* nose_cascade_;
00336 CvMemStorage* nose_storage_;
00337
00338 CvHaarClassifierCascade* eye_l_cascade_;
00339 CvMemStorage* eye_l_storage_;
00340
00341 CvHaarClassifierCascade* eye_r_cascade_;
00342 CvMemStorage* eye_r_storage_;
00343
00344 FACE::FaceFeatures<cv::Point2f> f_det_img_;
00345 FACE::FaceFeatures<cv::Point3f> f_det_xyz_;
00346
00347 cv::Size norm_size_;
00348 cv::Size input_size_;
00349
00350
00356 template<class T>
00357 void despeckle(cv::Mat& src, cv::Mat& dst)
00358 {
00359 if (src.channels() == 1)
00360 {
00361 T* lptr = src.ptr<T>(1, 0);
00362 T* rptr = src.ptr<T>(1, 2);
00363 T* mptr = src.ptr<T>(1, 1);
00364 T* uptr = src.ptr<T>(0, 1);
00365 T* dptr = src.ptr<T>(2, 1);
00366
00367 int normalizer = 4;
00368
00369 for (int px = 2 * src.cols + 2; px < (dst.rows * src.cols); ++px)
00370 {
00371 if (*mptr == 0)
00372 {
00373 normalizer = 4;
00374 if (*lptr == 0)
00375 normalizer -= 1;
00376 if (*rptr == 0)
00377 normalizer -= 1;
00378 if (*uptr == 0)
00379 normalizer -= 1;
00380 if (*dptr == 0)
00381 normalizer -= 1;
00382 if (normalizer > 1)
00383 *mptr = (*lptr + *rptr + *uptr + *dptr) / normalizer;
00384 else
00385 *mptr = 75;
00386 }
00387 ++lptr;
00388 ++rptr;
00389 ++mptr;
00390 ++uptr;
00391 ++dptr;
00392 }
00393 }
00394
00395 if (src.channels() == 3)
00396 {
00397 cv::Vec<T, 3>* lptr = src.ptr<cv::Vec<T, 3> >(1, 0);
00398 cv::Vec<T, 3>* rptr = src.ptr<cv::Vec<T, 3> >(1, 2);
00399 cv::Vec<T, 3>* mptr = src.ptr<cv::Vec<T, 3> >(1, 1);
00400 cv::Vec<T, 3>* uptr = src.ptr<cv::Vec<T, 3> >(0, 1);
00401 cv::Vec<T, 3>* dptr = src.ptr<cv::Vec<T, 3> >(2, 1);
00402
00403 int normalizer = 4;
00404 for (int px = 2 * src.cols + 2; px < (dst.rows * src.cols); ++px)
00405 {
00406 if ((*mptr)[0] == 0)
00407 {
00408 normalizer = 4;
00409 if ((*lptr)[0] == 0)
00410 normalizer -= 1;
00411 if ((*rptr)[0] == 0)
00412 normalizer -= 1;
00413 if ((*uptr)[0] == 0)
00414 normalizer -= 1;
00415 if ((*dptr)[0] == 0)
00416 normalizer -= 1;
00417 if (normalizer > 1)
00418 cv::divide((*lptr + *rptr + *uptr + *dptr), normalizer, *mptr);
00419 else
00420 *mptr = 75;
00421 }
00422 ++lptr;
00423 ++rptr;
00424 ++mptr;
00425 ++uptr;
00426 ++dptr;
00427 }
00428 }
00429 }
00430 };