00001 #include<cob_people_detection/face_recognizer_algorithms.h>
00002
00003 bool ipa_PeopleDetector::FaceRecognizerBaseClass::input_param_check(std::vector<cv::Mat>& imgs, std::vector<int>& labels, int& target_dim)
00004 {
00005 if (imgs.size() != labels.size())
00006 return false;
00007 if (imgs.size() == 0)
00008 return false;
00009 if (labels.size() == 0)
00010 return false;
00011 if (target_dim == 0)
00012 return false;
00013
00014
00015 }
00016 void ipa_PeopleDetector::FaceRecognizer1D::calc_threshold(cv::Mat& data, double& thresh)
00017 {
00018 thresh = std::numeric_limits<double>::max();
00019 std::vector<double> P(num_classes_, std::numeric_limits<double>::max());
00020 std::vector<double> D(num_classes_, std::numeric_limits<double>::min());
00021 std::vector<double> Phi(num_classes_, std::numeric_limits<double>::max());
00022
00023 for (int i = 0; i < data.rows; i++)
00024 {
00025 cv::Mat i_row = data.row(i);
00026 for (int n = 0; n < data.rows; n++)
00027 {
00028 if (n == i)
00029 continue;
00030 cv::Mat n_row = data.row(n);
00031 double dist = cv::norm(i_row, n_row, cv::NORM_L2);
00032 if (model_label_vec_[n] == model_label_vec_[i])
00033 {
00034 D[model_label_vec_[i]] = std::max(dist, D[model_label_vec_[i]]);
00035 }
00036 else
00037 {
00038 P[model_label_vec_[i]] = std::min(dist, P[model_label_vec_[i]]);
00039 }
00040 }
00041 }
00042
00043
00044 if (num_classes_ == 1)
00045 {
00046 P[0] = D[0];
00047 }
00048
00049 for (int c = 0; c < num_classes_; c++)
00050 {
00051 thresh = std::min(thresh, (P[c] + D[c]) * 0.5);
00052 }
00053 std::cout << "THRESH for db: " << thresh << std::endl;
00054
00055 }
00056
00057 void ipa_PeopleDetector::FaceRecognizer1D::model_data_mat(std::vector<cv::Mat>& input_data, cv::Mat& data_mat)
00058 {
00059
00060
00061
00062 for (int i = 0; i < input_data.size(); i++)
00063 {
00064 cv::Mat src_mat;
00065 src_mat = input_data[i];
00066 src_mat = src_mat.reshape(1, 1);
00067 cv::Mat dst_row = data_mat.row(i);
00068 src_mat.copyTo(dst_row);
00069 }
00070
00071 return;
00072 }
00073
00074 void ipa_PeopleDetector::FaceRecognizer1D::extractFeatures(cv::Mat& src_mat, cv::Mat& proj_mat, cv::Mat& coeff_mat)
00075 {
00076
00077
00078 cv::gemm(src_mat, proj_mat, 1.0, cv::Mat(), 0.0, coeff_mat, cv::GEMM_2_T);
00079
00080 }
00081
00082 void ipa_PeopleDetector::FaceRecognizer1D::classifyImage(cv::Mat& probe_mat, int& max_prob_index)
00083 {
00084 cv::Mat classification_probabilities;
00085 classifyImage(probe_mat, max_prob_index, classification_probabilities);
00086 }
00087 void ipa_PeopleDetector::FaceRecognizer1D::classifyImage(cv::Mat& probe_mat, int& max_prob_index, cv::Mat& classification_probabilities)
00088 {
00089
00090
00091 cv::Mat feature_arr = cv::Mat(1, target_dim_, CV_64FC1);
00092
00093 cv::Mat probe_arr = cv::Mat(1, probe_mat.total(), probe_mat.type());
00094 SubspaceAnalysis::mat2arr(probe_mat, probe_arr);
00095
00096 extractFeatures(probe_arr, projection_mat_, feature_arr);
00097
00098
00099 double minDIFS;
00100 cv::Mat minDIFScoeffs;
00101 int minDIFSindex;
00102 calcDIFS(feature_arr, minDIFSindex, minDIFS, classification_probabilities);
00103 max_prob_index = (int)model_label_vec_[minDIFSindex];
00104
00105
00106 if (use_unknown_thresh_)
00107 {
00108 if (!is_known(minDIFS, unknown_thresh_))
00109 max_prob_index = -1;
00110 }
00111 return;
00112 }
00113
00114 void ipa_PeopleDetector::FaceRecognizer1D::calcDIFS(cv::Mat& probe_mat, int& minDIFSindex, double& minDIFS, cv::Mat& probabilities)
00115 {
00116
00117 double norm;
00118 minDIFS = std::numeric_limits<float>::max();
00119 probabilities = cv::Mat(1, num_classes_, CV_64FC1);
00120 probabilities *= std::numeric_limits<float>::max();
00121 for (int r = 0; r < model_features_.rows; r++)
00122 {
00123 cv::Mat model_mat = model_features_.row(r);
00124
00125
00126 norm = cv::norm(probe_mat, model_mat, cv::NORM_L2);
00127
00128
00129 if (norm < minDIFS)
00130 {
00131 minDIFSindex = r;
00132 minDIFS = norm;
00133 }
00134
00135 }
00136
00137
00138 double min_cost, max_cost;
00139 probabilities = 1 / (probabilities.mul(probabilities));
00140 cv::minMaxLoc(probabilities, &min_cost, &max_cost, 0, 0);
00141 probabilities /= max_cost;
00142
00143 return;
00144 }
00145
00146 void ipa_PeopleDetector::FaceRecognizer2D::classifyImage(cv::Mat& probe_mat, int& max_prob_index)
00147 {
00148 cv::Mat classification_probabilities;
00149 classifyImage(probe_mat, max_prob_index, classification_probabilities);
00150 }
00151 void ipa_PeopleDetector::FaceRecognizer2D::classifyImage(cv::Mat& probe_mat, int& max_prob_index, cv::Mat& classification_probabilities)
00152 {
00153
00154
00155
00156
00157
00158
00159
00160 cv::Mat feature_mat;
00161 extractFeatures(probe_mat, projection_mat_, feature_mat);
00162
00163
00164 double minDIFS;
00165 cv::Mat minDIFScoeffs;
00166 int minDIFSindex;
00167 calcDIFS(feature_mat, minDIFSindex, minDIFS, classification_probabilities);
00168 max_prob_index = (int)model_label_vec_[minDIFSindex];
00169
00170
00171 if (use_unknown_thresh_)
00172 {
00173 if (!is_known(minDIFS, unknown_thresh_))
00174 max_prob_index = -1;
00175 }
00176 return;
00177 }
00178 void ipa_PeopleDetector::FaceRecognizer2D::extractFeatures(std::vector<cv::Mat>& src_vec, cv::Mat& proj_mat, std::vector<cv::Mat>& coeff_mat_vec)
00179 {
00180
00181 for (int i = 0; i < src_vec.size(); i++)
00182 {
00183 cv::Mat src_mat = cv::Mat(src_vec[0].rows, src_vec[0].cols, CV_64FC1);
00184 src_vec[i].convertTo(src_mat, CV_64FC1);
00185 cv::Mat coeff_mat = cv::Mat(src_mat.rows, src_mat.cols, CV_64FC1);
00186 cv::gemm(src_mat, proj_mat, 1.0, cv::Mat(), 0.0, coeff_mat, cv::GEMM_2_T);
00187 coeff_mat_vec[i] = coeff_mat;
00188 }
00189 }
00190 void ipa_PeopleDetector::FaceRecognizer2D::extractFeatures(cv::Mat& src_mat, cv::Mat& proj_mat, cv::Mat& coeff_mat)
00191 {
00192
00193 coeff_mat = cv::Mat(target_dim_, target_dim_, CV_64FC1);
00194 cv::gemm(src_mat, proj_mat, 1.0, cv::Mat(), 0.0, coeff_mat, cv::GEMM_2_T);
00195 }
00196
00197 void ipa_PeopleDetector::FaceRecognizer2D::calcDIFS(cv::Mat& probe_mat, int& minDIFSindex, double& minDIFS, cv::Mat& probabilities)
00198 {
00199 minDIFS = std::numeric_limits<double>::max();
00200 probabilities = cv::Mat(1, num_classes_, CV_32FC1);
00201 probabilities *= std::numeric_limits<float>::max();
00202 for (int m = 0; m < model_features_.size(); m++)
00203 {
00204
00205 cv::Mat work_mat;
00206 cv::subtract(probe_mat, model_features_[m], work_mat);
00207 cv::pow(work_mat, 2, work_mat);
00208 cv::Mat tmp_vec = cv::Mat::zeros(1, probe_mat.cols, CV_64FC1);
00209 cv::reduce(work_mat, tmp_vec, 0, CV_REDUCE_SUM);
00210
00211 cv::Scalar norm = cv::sum(tmp_vec);
00212
00213 if ((double)norm[0] < minDIFS)
00214 {
00215 minDIFSindex = m;
00216 minDIFS = (double)norm[0];
00217 }
00218
00219 probabilities.at<float>(model_label_vec_[m]) = std::min(probabilities.at<float>(model_label_vec_[m]), (float)norm[0]);
00220 }
00221
00222
00223 double min_cost, max_cost;
00224 probabilities = 1 / (probabilities.mul(probabilities));
00225 cv::minMaxLoc(probabilities, &min_cost, &max_cost, 0, 0);
00226 probabilities /= max_cost;
00227
00228 return;
00229 }
00230
00231 void ipa_PeopleDetector::FaceRecognizer2D::calc_threshold(std::vector<cv::Mat>& data, double& thresh)
00232 {
00233 thresh = std::numeric_limits<double>::max();
00234 std::vector<double> P(num_classes_, std::numeric_limits<double>::max());
00235 std::vector<double> D(num_classes_, std::numeric_limits<double>::min());
00236 std::vector<double> Phi(num_classes_, std::numeric_limits<double>::max());
00237
00238 for (int i = 0; i < data.size(); i++)
00239 {
00240 for (int n = 0; n < data.size(); n++)
00241 {
00242 if (n == i)
00243 continue;
00244
00245
00246 cv::Mat work_mat = cv::Mat(data[0].rows, data[0].cols, CV_64FC1);
00247 cv::subtract(data[i], data[n], work_mat);
00248 cv::pow(work_mat, 2, work_mat);
00249
00250 cv::Mat tmp_vec = cv::Mat::zeros(1, data[i].cols, CV_64FC1);
00251 cv::reduce(work_mat, tmp_vec, 0, CV_REDUCE_SUM);
00252
00253 cv::Scalar temp = cv::sum(tmp_vec);
00254 double dist = temp.val[0];
00255 if (model_label_vec_[n] == model_label_vec_[i])
00256 {
00257 D[model_label_vec_[i]] = std::max(dist, D[model_label_vec_[i]]);
00258 }
00259 else
00260 {
00261 P[model_label_vec_[i]] = std::min(dist, P[model_label_vec_[i]]);
00262 }
00263 }
00264 }
00265
00266
00267 if (num_classes_ == 1)
00268 {
00269 P[0] = D[0];
00270 }
00271
00272 for (int c = 0; c < num_classes_; c++)
00273 {
00274 thresh = std::min(thresh, (P[c] + D[c]) * 0.2);
00275 }
00276 std::cout << "THRESH for db: " << thresh << std::endl;
00277 }
00278
00279 bool ipa_PeopleDetector::FaceRecognizer1D::loadModel(boost::filesystem::path& model_file)
00280 {
00281
00282
00283
00284 std::cout << "FaceRecognizer1D::loadModel() from " << model_file.string() << std::endl;
00285 cv::FileStorage fs(model_file.string(), cv::FileStorage::READ);
00286
00287 fs["projection_matrix"] >> projection_mat_;
00288 fs["eigenvalues"] >> eigenvalues_;
00289 fs["unknown_threshold"] >> unknown_thresh_;
00290 fs["average_image"] >> average_arr_;
00291 fs["model_features"] >> model_features_;
00292
00293
00294 cv::FileNode fn = fs["numeric_labels"];
00295 cv::FileNodeIterator it = fn.begin(), it_end = fn.end();
00296 int idx = 0;
00297 model_label_vec_.resize(model_features_.rows);
00298 for (; it != it_end; ++it, idx++)
00299 {
00300 model_label_vec_[idx] = (int)(*it);
00301 }
00302
00303 target_dim_ = model_features_.cols;
00304 trained_ = true;
00305
00306 }
00307
00308 bool ipa_PeopleDetector::FaceRecognizer1D::saveModel(boost::filesystem::path& model_file)
00309 {
00310
00311 std::cout << "FaceRecognizer2D::saveModel() to " << model_file.string() << std::endl;
00312 cv::FileStorage fs(model_file.string(), cv::FileStorage::WRITE);
00313
00314 fs << "projection_matrix" << projection_mat_;
00315 fs << "eigenvalues" << eigenvalues_;
00316 fs << "unknown_threshold" << unknown_thresh_;
00317 fs << "average_image" << average_arr_;
00318 fs << "model_features" << model_features_;
00319 fs << "numeric_labels" << "[";
00320 for (int i = 0; i < model_label_vec_.size(); i++)
00321 {
00322 fs << model_label_vec_[i];
00323 }
00324 fs << "]";
00325 fs.release();
00326
00327 }
00328
00329 bool ipa_PeopleDetector::FaceRecognizer2D::loadModel(boost::filesystem::path& model_file)
00330 {
00331
00334 std::cout << "FaceRecognizer2D::loadModel() from " << model_file.string() << std::endl;
00335 cv::FileStorage fs(model_file.string(), cv::FileStorage::READ);
00336
00337 fs["projection_matrix"] >> projection_mat_;
00338 fs["eigenvalues"] >> eigenvalues_;
00339 fs["unknown_threshold"] >> unknown_thresh_;
00340
00341
00342
00343 cv::FileNode fnm = fs["model_features"];
00344 cv::FileNodeIterator itm = fnm.begin(), itm_end = fnm.end();
00345 int idm = 0;
00346 for (; itm != itm_end; ++itm, idm++)
00347 {
00348 cv::Mat temp;
00349 (*itm) >> temp;
00350 model_features_.push_back(temp);
00351 }
00352
00353
00354 cv::FileNode fn = fs["numeric_labels"];
00355 cv::FileNodeIterator it = fn.begin(), it_end = fn.end();
00356 int idx = 0;
00357 model_label_vec_.resize(model_features_.size());
00358 for (; it != it_end; ++it, idx++)
00359 {
00360 model_label_vec_[idx] = (int)(*it);
00361 }
00362
00363 target_dim_ = model_features_[0].cols;
00364 trained_ = true;
00365
00366 }
00367
00368 bool ipa_PeopleDetector::FaceRecognizer2D::saveModel(boost::filesystem::path& model_file)
00369 {
00370
00371 std::cout << "FaceRecognizer1D::saveModel() to " << model_file.string() << std::endl;
00372 cv::FileStorage fs(model_file.string(), cv::FileStorage::WRITE);
00373
00374 fs << "projection_matrix" << projection_mat_;
00375 fs << "eigenvalues" << eigenvalues_;
00376 fs << "unknown_threshold" << unknown_thresh_;
00377 fs << "average_image" << average_mat_;
00378
00379 fs << "model_features" << "[";
00380 for (int i = 0; i < model_features_.size(); i++)
00381 fs << model_features_[i];
00382 fs << "]";
00383
00384 fs << "numeric_labels" << "[";
00385 for (int i = 0; i < model_label_vec_.size(); i++)
00386 {
00387 fs << model_label_vec_[i];
00388 }
00389 fs << "]";
00390 fs.release();
00391
00392 }
00393 bool ipa_PeopleDetector::FaceRecognizer_Eigenfaces::trainModel(std::vector<cv::Mat>& img_vec, std::vector<int>& label_vec, int& target_dim)
00394 {
00395
00396 input_param_check(img_vec, label_vec, target_dim);
00397
00398 std::cout << "Training Eigenfaces" << std::endl;
00399 std::vector<int> unique_labels;
00400 SubspaceAnalysis::unique_elements(label_vec, num_classes_, unique_labels);
00401 SubspaceAnalysis::condense_labels(label_vec);
00402
00403 SubspaceAnalysis::PCA PCA;
00404
00405 if (target_dim > num_classes_)
00406 target_dim_ = num_classes_;
00407 else
00408 target_dim_ = target_dim;
00409
00410
00411 cv::Mat model_data_arr = cv::Mat(img_vec.size(), img_vec[0].total(), CV_64FC1);
00412 model_label_vec_.resize(img_vec.size());
00413 average_arr_ = cv::Mat(1, img_vec[0].total(), CV_64FC1);
00414 projection_mat_ = cv::Mat(target_dim_, img_vec[0].total(), CV_64FC1);
00415 eigenvalues_ = cv::Mat(1, target_dim_ - 1, CV_64FC1);
00416 model_features_ = cv::Mat(model_data_arr.rows, target_dim_, CV_64FC1);
00417
00418 model_label_vec_ = label_vec;
00419 model_data_mat(img_vec, model_data_arr);
00420
00421 PCA = SubspaceAnalysis::PCA(model_data_arr, target_dim_);
00422
00423
00424 projection_mat_ = PCA.eigenvecs;
00425 eigenvalues_ = PCA.eigenvals;
00426 average_arr_ = PCA.mean;
00427
00428 extractFeatures(model_data_arr, projection_mat_, model_features_);
00429
00430 calc_threshold(model_features_, unknown_thresh_);
00431
00432
00433 this->trained_ = true;
00434 return true;
00435 }
00436
00437 bool ipa_PeopleDetector::FaceRecognizer_Fisherfaces::trainModel(std::vector<cv::Mat>& img_vec, std::vector<int>& label_vec, int& target_dim)
00438 {
00439 input_param_check(img_vec, label_vec, target_dim);
00440
00441 std::cout << "Training Fisherfaces" << std::endl;
00442 std::vector<int> unique_labels;
00443 SubspaceAnalysis::unique_elements(label_vec, num_classes_, unique_labels);
00444
00445 if (num_classes_ < 2)
00446 {
00447 std::cout << "[FaceRecognizerAlgorithm] Fisherfaces needs more than single class in training data.Aborting." << std::endl;
00448 return false;
00449 }
00450 SubspaceAnalysis::condense_labels(label_vec);
00451
00452 SubspaceAnalysis::PCA PCA;
00453 SubspaceAnalysis::LDA LDA;
00454
00455
00456
00457 target_dim_ = num_classes_ - 1;
00458 int target_dim_PCA = label_vec.size() - num_classes_;
00459 if (target_dim_PCA < 1)
00460 target_dim_PCA = num_classes_;
00461
00462
00463 cv::Mat model_data_arr = cv::Mat(img_vec.size(), img_vec[0].total(), CV_64FC1);
00464 model_label_vec_.resize(img_vec.size());
00465 average_arr_ = cv::Mat(1, img_vec[0].total(), CV_64FC1);
00466 projection_mat_ = cv::Mat(target_dim_, img_vec[0].total(), CV_64FC1);
00467 eigenvalues_ = cv::Mat(1, target_dim_ - 1, CV_64FC1);
00468 model_features_ = cv::Mat(model_data_arr.rows, target_dim_, CV_64FC1);
00469
00470
00471 cv::Mat P_PCA = cv::Mat(target_dim_PCA, img_vec[0].total(), CV_64FC1);
00472 cv::Mat model_features_PCA = cv::Mat(model_data_arr.rows, target_dim_PCA, CV_64FC1);
00473
00474
00475 cv::Mat P_LDA = cv::Mat(target_dim_, target_dim_PCA, CV_64FC1);
00476
00477 model_label_vec_ = label_vec;
00478 model_data_mat(img_vec, model_data_arr);
00479
00480
00481 PCA = SubspaceAnalysis::PCA(model_data_arr, target_dim_PCA);
00482 P_PCA = PCA.eigenvecs;
00483
00484 extractFeatures(model_data_arr, P_PCA, model_features_PCA);
00485
00486
00487 LDA = SubspaceAnalysis::LDA(model_features_PCA, model_label_vec_, num_classes_, target_dim_);
00488 P_LDA = LDA.eigenvecs;
00489
00490
00491 cv::gemm(P_PCA.t(), P_LDA.t(), 1.0, cv::Mat(), 0.0, projection_mat_);
00492
00493
00494 projection_mat_ = projection_mat_.t();
00495 eigenvalues_ = LDA.eigenvals;
00496 average_arr_ = PCA.mean;
00497
00498 extractFeatures(model_data_arr, projection_mat_, model_features_);
00499
00500 calc_threshold(model_features_, unknown_thresh_);
00501
00502
00503 this->trained_ = true;
00504 return true;
00505 }
00506
00507 bool ipa_PeopleDetector::FaceRecognizer_PCA2D::trainModel(std::vector<cv::Mat>& img_vec, std::vector<int>& label_vec, int& target_dim)
00508 {
00509
00510 input_param_check(img_vec, label_vec, target_dim);
00511
00512 std::cout << "Training PCA2D" << std::endl;
00513 std::vector<int> unique_labels;
00514 SubspaceAnalysis::unique_elements(label_vec, num_classes_, unique_labels);
00515 SubspaceAnalysis::condense_labels(label_vec);
00516
00517
00518
00519 target_dim_ = target_dim;
00520
00521
00522 model_label_vec_.resize(img_vec.size());
00523 average_mat_ = cv::Mat(img_vec[0].rows, img_vec[0].cols, CV_64FC1);
00524 projection_mat_ = cv::Mat(target_dim_, img_vec[0].cols, CV_64FC1);
00525 eigenvalues_ = cv::Mat(1, target_dim_ - 1, CV_64FC1);
00526 model_features_.resize(img_vec.size());
00527
00528 model_label_vec_ = label_vec;
00529
00530 SubspaceAnalysis::PCA2D PCA2D(img_vec, model_label_vec_, num_classes_, target_dim_);
00531
00532
00533 projection_mat_ = PCA2D.eigenvecs;
00534 eigenvalues_ = PCA2D.eigenvals;
00535 average_mat_ = PCA2D.mean;
00536
00537 extractFeatures(img_vec, projection_mat_, model_features_);
00538 calc_threshold(model_features_, unknown_thresh_);
00539
00540
00541 this->trained_ = true;
00542 return true;
00543
00544 }
00545
00546 bool ipa_PeopleDetector::FaceRecognizer_LDA2D::trainModel(std::vector<cv::Mat>& img_vec, std::vector<int>& label_vec, int& target_dim)
00547 {
00548
00549 input_param_check(img_vec, label_vec, target_dim);
00550
00551 std::cout << "Training LDA2D" << std::endl;
00552 std::vector<int> unique_labels;
00553 SubspaceAnalysis::unique_elements(label_vec, num_classes_, unique_labels);
00554 SubspaceAnalysis::condense_labels(label_vec);
00555
00556 if (num_classes_ < 2)
00557 {
00558 std::cout << "[FaceRecognizerAlgorithm] LDA 2D needs more than single class in training data.Aborting." << std::endl;
00559 return false;
00560 }
00561
00562
00563
00564 source_dim_ = cv::Size(img_vec[0].rows, img_vec[0].cols);
00565 target_dim_ = target_dim;
00566
00567
00568 model_label_vec_.resize(img_vec.size());
00569 average_mat_ = cv::Mat(img_vec[0].rows, img_vec[0].cols, CV_64FC1);
00570 projection_mat_ = cv::Mat(target_dim_, img_vec[0].cols, CV_64FC1);
00571 eigenvalues_ = cv::Mat(1, target_dim_ - 1, CV_64FC1);
00572 model_features_.resize(img_vec.size());
00573
00574 model_label_vec_ = label_vec;
00575 for (int i = 0; i < model_label_vec_.size(); i++)
00576 {
00577 std::cout << model_label_vec_[i];
00578 }
00579
00580 SubspaceAnalysis::LDA2D LDA2D(img_vec, model_label_vec_, num_classes_, target_dim_);
00581
00582
00583 projection_mat_ = LDA2D.eigenvecs;
00584 eigenvalues_ = LDA2D.eigenvals;
00585 average_mat_ = LDA2D.mean;
00586
00587 extractFeatures(img_vec, projection_mat_, model_features_);
00588 calc_threshold(model_features_, unknown_thresh_);
00589
00590
00591 this->trained_ = true;
00592 return true;
00593 }