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
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #include "cob_people_detection/face_detection.h"
00056 #include <pluginlib/class_list_macros.h>
00057
00058 #ifdef __LINUX__
00059 #include "cob_vision_utils/GlobalDefines.h"
00060 #include "cob_vision_utils/VisionUtils.h"
00061 #else
00062 #include "cob_common/cob_vision_utils/common/include/cob_vision_utils/GlobalDefines.h"
00063 #include "cob_common/cob_vision_utils/common/include/cob_vision_utils/VisionUtils.h"
00064 #endif
00065
00066 #include <opencv2/opencv.hpp>
00067
00068 PLUGINLIB_EXPORT_CLASS(ipa_PeopleDetector::CobFaceDetectionNodelet, nodelet::Nodelet);
00069
00070 using namespace ipa_PeopleDetector;
00071
00072
00073 void voidDeleter(sensor_msgs::PointCloud2* const )
00074 {
00075 }
00076
00077
00078
00079 CobFaceDetectionNodelet::CobFaceDetectionNodelet()
00080 {
00081 it_ = 0;
00082 sync_pointcloud_ = 0;
00083 people_detector_ = 0;
00084 train_continuous_server_ = 0;
00085 train_capture_sample_server_ = 0;
00086 recognize_server_ = 0;
00087 load_server_ = 0;
00088 save_server_ = 0;
00089 show_server_ = 0;
00090 occupied_by_action_ = false;
00091 recognize_server_running_ = false;
00092 train_continuous_server_running_ = false;
00093 number_training_images_captured_ = 0;
00094 do_recognition_ = true;
00095 display_ = false;
00096 directory_ = ros::package::getPath("cob_people_detection") + "/common/files/windows/";
00097 }
00098
00099 CobFaceDetectionNodelet::~CobFaceDetectionNodelet()
00100 {
00101 if (people_detector_ != 0)
00102 delete people_detector_;
00103 if (train_continuous_server_ != 0)
00104 delete train_continuous_server_;
00105 if (train_capture_sample_server_ != 0)
00106 delete train_capture_sample_server_;
00107 if (recognize_server_ != 0)
00108 delete recognize_server_;
00109 if (load_server_ != 0)
00110 delete load_server_;
00111 if (save_server_ != 0)
00112 delete save_server_;
00113 if (show_server_ != 0)
00114 delete show_server_;
00115 if (it_ != 0)
00116 delete it_;
00117 if (sync_pointcloud_ != 0)
00118 delete sync_pointcloud_;
00119 }
00120
00121 void CobFaceDetectionNodelet::onInit()
00122 {
00123 sync_pointcloud_ = new message_filters::Synchronizer<message_filters::sync_policies::ApproximateTime<sensor_msgs::PointCloud2, sensor_msgs::Image> >(2);
00124 node_handle_ = getNodeHandle();
00125 it_ = new image_transport::ImageTransport(node_handle_);
00126 face_position_publisher_ = node_handle_.advertise<cob_perception_msgs::DetectionArray>("face_position_array", 1);
00127 face_detection_image_pub_ = it_->advertise("face_detection_image", 1);
00128
00129 recognize_server_ = new RecognizeServer(node_handle_, "recognize_server", boost::bind(&CobFaceDetectionNodelet::recognizeServerCallback, this, _1), false);
00130 recognize_server_->start();
00131
00132 recognize_service_server_ = node_handle_.advertiseService("recognize_service_server", &CobFaceDetectionNodelet::recognizeServiceServerCallback, this);
00133
00134 train_continuous_server_ = new TrainContinuousServer(node_handle_, "train_continuous_server", boost::bind(&CobFaceDetectionNodelet::trainContinuousServerCallback, this, _1),
00135 false);
00136 train_continuous_server_->start();
00137
00138 train_capture_sample_server_ = new TrainCaptureSampleServer(node_handle_, "train_capture_sample_server",
00139 boost::bind(&CobFaceDetectionNodelet::trainCaptureSampleServerCallback, this, _1), false);
00140 train_capture_sample_server_->start();
00141
00142 load_server_ = new LoadServer(node_handle_, "load_server", boost::bind(&CobFaceDetectionNodelet::loadServerCallback, this, _1), false);
00143 load_server_->start();
00144
00145 save_server_ = new SaveServer(node_handle_, "save_server", boost::bind(&CobFaceDetectionNodelet::saveServerCallback, this, _1), false);
00146 save_server_->start();
00147
00148 show_server_ = new ShowServer(node_handle_, "show_server", boost::bind(&CobFaceDetectionNodelet::showServerCallback, this, _1), false);
00149 show_server_->start();
00150
00151
00152 std::cout << "\n--------------------------\nFace Detection Parameters:\n--------------------------\n";
00153 node_handle_.param("face_size_min_m", face_size_min_m_, FACE_SIZE_MIN_M);
00154 std::cout << "face_size_min_m = " << face_size_min_m_ << "\n";
00155 node_handle_.param("face_size_max_m", face_size_max_m_, FACE_SIZE_MAX_M);
00156 std::cout << "face_size_max_m = " << face_size_max_m_ << "\n";
00157 node_handle_.param("max_face_z_m", max_face_z_m_, MAX_FACE_Z_M);
00158 std::cout << "max_face_z_m = " << max_face_z_m_ << "\n";
00159 node_handle_.param("data_directory", directory_, directory_);
00160 std::cout << "data_directory = " << directory_ << "\n";
00161 node_handle_.param("fill_unassigned_depth_values", fill_unassigned_depth_values_, true);
00162 std::cout << "fill_unassigned_depth_values = " << fill_unassigned_depth_values_ << "\n";
00163 node_handle_.param("reason_about_3dface_size", reason_about_3dface_size_, true);
00164 std::cout << "reason_about_3dface_size = " << reason_about_3dface_size_ << "\n";
00165
00166
00167 init();
00168
00169
00170 }
00171
00172 unsigned long CobFaceDetectionNodelet::init()
00173 {
00174 std::cout << "CobFaceDetectionNodelet::init()..." << std::endl;
00175
00176 shared_image_sub_.subscribe(node_handle_, "pointcloud", 1);
00177 color_camera_image_sub_.subscribe(*it_, "colorimage", 1);
00178
00179
00180
00181 sync_pointcloud_->connectInput(shared_image_sub_, color_camera_image_sub_);
00182 sync_pointcloud_callback_connection_ = sync_pointcloud_->registerCallback(boost::bind(&CobFaceDetectionNodelet::recognizeCallback, this, _1, _2));
00183
00184 std::cout << " inputs connected." << std::endl;
00185
00186 #ifdef __LINUX__
00187 #else
00188 colored_pc_ = ipa_SensorFusion::CreateColoredPointCloud();
00189 #endif
00190
00191 if (people_detector_ != 0)
00192 delete people_detector_;
00193 people_detector_ = new ipa_PeopleDetector::PeopleDetector();
00194
00195 std::cout << " PeopleDetector created." << std::endl;
00196
00197 filename_ = 0;
00198
00199
00200 loadRecognizerData();
00201 std::cout << " recognizer data loaded." << std::endl;
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 std::string iniFileNameAndPath = directory_ + "peopleDetectorIni.xml";
00213
00214
00215
00216
00217
00218
00219
00220
00221 if (people_detector_->Init(directory_) & ipa_Utils::RET_FAILED)
00222 {
00223 std::cerr << "ERROR - PeopleDetector::Init:" << std::endl;
00224 std::cerr << "\t ... Could not initialize people detector library.\n";
00225 return ipa_Utils::RET_FAILED;
00226 }
00227 std::cout << " PeopleDetector initilized." << std::endl;
00228
00229 if (loadParameters(iniFileNameAndPath.c_str()) & ipa_Utils::RET_FAILED)
00230 {
00231 std::cerr << "ERROR - PeopleDetector::Init:" << std::endl;
00232 std::cerr << "\t ... Error while loading configuration file '" << std::endl;
00233 std::cerr << "\t ... " << iniFileNameAndPath << "'.\n";
00234 return ipa_Utils::RET_FAILED;
00235 }
00236 std::cout << " ini-file loaded." << std::endl;
00237
00238 run_pca_ = false;
00239
00240 return ipa_Utils::RET_OK;
00241 }
00242
00243 bool CobFaceDetectionNodelet::recognizeServiceServerCallback(cob_people_detection::Recognition::Request &req, cob_people_detection::Recognition::Response &res)
00244 {
00245
00246 boost::timed_mutex::scoped_timed_lock lock(action_mutex_, boost::posix_time::milliseconds(2000));
00247
00248 if (lock.owns_lock() == false || (occupied_by_action_ == true && recognize_server_running_ == false))
00249 {
00250
00251 std::cerr << "ERROR - PeopleDetector::recognizeServerCallback:" << std::endl;
00252 std::cerr << "\t ... Another action is running at the moment. The other action has to finish or to be stopped before this action can run.\n";
00253 res.success = ipa_Utils::RET_FAILED;
00254 return false;
00255 }
00256
00257
00258
00259 if (req.running == true)
00260 {
00261
00262 occupied_by_action_ = true;
00263 recognize_server_running_ = true;
00264 do_recognition_ = req.doRecognition;
00265 display_ = req.display;
00266
00267
00268
00269
00270 }
00271 else
00272 {
00273
00274 occupied_by_action_ = false;
00275 recognize_server_running_ = false;
00276 }
00277
00278 res.success = ipa_Utils::RET_OK;
00279 return true;
00280 }
00281
00282 void CobFaceDetectionNodelet::recognizeServerCallback(const cob_people_detection::RecognizeGoalConstPtr& goal)
00283 {
00284
00285 boost::timed_mutex::scoped_timed_lock lock(action_mutex_, boost::posix_time::milliseconds(2000));
00286
00287 cob_people_detection::RecognizeResult result;
00288 if (lock.owns_lock() == false || (occupied_by_action_ == true && recognize_server_running_ == false))
00289 {
00290
00291 std::cerr << "ERROR - PeopleDetector::recognizeServerCallback:" << std::endl;
00292 std::cerr << "\t ... Another action is running at the moment. The other action has to finish or to be stopped before this action can run.\n";
00293 result.success = ipa_Utils::RET_FAILED;
00294 recognize_server_->setSucceeded(result, "Some other action is handled at the moment.");
00295 return;
00296 }
00297
00298
00299
00300 if (goal->running == true)
00301 {
00302
00303 occupied_by_action_ = true;
00304 recognize_server_running_ = true;
00305 do_recognition_ = goal->doRecognition;
00306 display_ = goal->display;
00307
00308
00309
00310
00311 }
00312 else
00313 {
00314
00315 occupied_by_action_ = false;
00316 recognize_server_running_ = false;
00317 }
00318
00319 result.success = ipa_Utils::RET_OK;
00320 recognize_server_->setSucceeded(result);
00321 }
00322
00323 void CobFaceDetectionNodelet::trainContinuousServerCallback(const cob_people_detection::TrainContinuousGoalConstPtr& goal)
00324 {
00325
00326 boost::timed_mutex::scoped_timed_lock lock(action_mutex_, boost::posix_time::milliseconds(2000));
00327
00328 cob_people_detection::TrainContinuousResult result;
00329 if (lock.owns_lock() == false || (occupied_by_action_ == true && train_continuous_server_running_ == false))
00330 {
00331
00332 std::cerr << "ERROR - PeopleDetector::trainContinuousServerCallback:" << std::endl;
00333 std::cerr << "\t ... Another action is running at the moment. The other action has to finish or to be stopped before this action can run.\n";
00334 result.success = ipa_Utils::RET_FAILED;
00335 train_continuous_server_->setSucceeded(result, "Some other action is handled at the moment.");
00336 return;
00337 }
00338
00339
00340
00341 if (goal->running == true)
00342 {
00343
00344 capture_training_face_ = false;
00345 current_training_id_ = goal->trainingID;
00346
00347 if (goal->appendData == true)
00348 loadTrainingData(false);
00349 else
00350 {
00351 filename_ = 0;
00352 std::string path = directory_ + "TrainingData/";
00353 try
00354 {
00355 boost::filesystem::remove_all(path.c_str());
00356 boost::filesystem::create_directory(path.c_str());
00357 } catch (const std::exception &ex)
00358 {
00359 std::cerr << "ERROR - PeopleDetector::trainContinuousServerCallback():" << std::endl;
00360 std::cerr << "\t ... Exception catch of '" << ex.what() << "'" << std::endl;
00361 }
00362 }
00363 occupied_by_action_ = true;
00364 train_continuous_server_running_ = true;
00365
00366
00367
00368
00369 std::cout << "train run...\n";
00370
00371
00372 if (goal->numberOfImagesToCapture > 0)
00373 {
00374 lock.unlock();
00375 number_training_images_captured_ = 0;
00376 bool capture = true;
00377 while (capture)
00378 {
00379 boost::timed_mutex::scoped_timed_lock lock(action_mutex_, boost::posix_time::milliseconds(10));
00380 if (lock.owns_lock() && capture_training_face_ == false)
00381 capture_training_face_ = true;
00382 capture = (number_training_images_captured_ < goal->numberOfImagesToCapture);
00383 }
00384
00385
00386 std::cout << "continuous train off...\n";
00387
00388
00389 occupied_by_action_ = false;
00390 train_continuous_server_running_ = false;
00391
00392
00393 saveTrainingData();
00394
00395
00396 if (goal->doPCA)
00397 {
00398 PCA();
00399 saveRecognizerData();
00400 }
00401 }
00402 }
00403 else
00404 {
00405 std::cout << "train off...\n";
00406
00407
00408 occupied_by_action_ = false;
00409 train_continuous_server_running_ = false;
00410
00411
00412
00413
00414 saveTrainingData();
00415
00416
00417 if (goal->doPCA)
00418 {
00419 PCA();
00420 saveRecognizerData();
00421 }
00422 }
00423
00424 result.success = ipa_Utils::RET_OK;
00425 train_continuous_server_->setSucceeded(result);
00426 }
00427
00428 void CobFaceDetectionNodelet::trainCaptureSampleServerCallback(const cob_people_detection::TrainCaptureSampleGoalConstPtr& goal)
00429 {
00430
00431 boost::timed_mutex::scoped_timed_lock lock(action_mutex_, boost::posix_time::milliseconds(10));
00432
00433 cob_people_detection::TrainCaptureSampleResult result;
00434 if (lock.owns_lock() == false || (occupied_by_action_ == true && train_continuous_server_running_ == false) || occupied_by_action_ == false)
00435 {
00436
00437 std::cerr << "ERROR - PeopleDetector::trainCaptureSampleServerCallback:" << std::endl;
00438 std::cerr
00439 << "\t ... Either the training mode is not started or another action is running at the moment. The other action has to finish or to be stopped before this action can run.\n";
00440 result.success = ipa_Utils::RET_FAILED;
00441 train_capture_sample_server_->setSucceeded(result, "Some other action is handled at the moment or training mode not started.");
00442 return;
00443 }
00444
00445 capture_training_face_ = true;
00446 result.success = ipa_Utils::RET_OK;
00447 train_capture_sample_server_->setSucceeded(result);
00448 }
00449
00450 void CobFaceDetectionNodelet::loadServerCallback(const cob_people_detection::LoadGoalConstPtr& goal)
00451 {
00452
00453 boost::timed_mutex::scoped_timed_lock lock(action_mutex_, boost::posix_time::milliseconds(2000));
00454
00455 cob_people_detection::LoadResult result;
00456 if (lock.owns_lock() == false || occupied_by_action_ == true)
00457 {
00458
00459 std::cerr << "ERROR - PeopleDetector::loadServerCallback:" << std::endl;
00460 std::cerr << "\t ... Another action is running at the moment. The other action has to finish or to be stopped before this action can run.\n";
00461 result.success = ipa_Utils::RET_FAILED;
00462 load_server_->setSucceeded(result, "Some other action is handled at the moment or training mode not started.");
00463 return;
00464 }
00465
00466
00467 result.success = ipa_Utils::RET_OK;
00468 if (goal->loadMode == 0)
00469 result.success = loadAllData();
00470 else if (goal->loadMode == 1)
00471 result.success = loadTrainingData(goal->doPCA);
00472 else if (goal->loadMode == 2)
00473 result.success = loadRecognizerData();
00474
00475 load_server_->setSucceeded(result);
00476 }
00477
00478 void CobFaceDetectionNodelet::saveServerCallback(const cob_people_detection::SaveGoalConstPtr& goal)
00479 {
00480
00481 boost::timed_mutex::scoped_timed_lock lock(action_mutex_, boost::posix_time::milliseconds(2000));
00482
00483 cob_people_detection::SaveResult result;
00484 if (lock.owns_lock() == false || occupied_by_action_ == true)
00485 {
00486
00487 std::cerr << "ERROR - PeopleDetector::saveServerCallback:" << std::endl;
00488 std::cerr << "\t ... Another action is running at the moment. The other action has to finish or to be stopped before this action can run.\n";
00489 result.success = ipa_Utils::RET_FAILED;
00490 save_server_->setSucceeded(result, "Some other action is handled at the moment or training mode not started.");
00491 return;
00492 }
00493
00494
00495 result.success = ipa_Utils::RET_OK;
00496 if (goal->saveMode == 0)
00497 result.success = saveAllData();
00498 else if (goal->saveMode == 1)
00499 result.success = saveTrainingData();
00500 else if (goal->saveMode == 2)
00501 result.success = saveRecognizerData();
00502
00503 save_server_->setSucceeded(result);
00504 }
00505
00506 void CobFaceDetectionNodelet::showServerCallback(const cob_people_detection::ShowGoalConstPtr& goal)
00507 {
00508
00509 boost::timed_mutex::scoped_timed_lock lock(action_mutex_, boost::posix_time::milliseconds(2000));
00510
00511 cob_people_detection::ShowResult result;
00512 if (lock.owns_lock() == false || occupied_by_action_ == true)
00513 {
00514
00515 std::cerr << "ERROR - PeopleDetector::showServerCallback:" << std::endl;
00516 std::cerr << "\t ... Another action is running at the moment. The other action has to finish or to be stopped before this action can run.\n";
00517 result.success = ipa_Utils::RET_FAILED;
00518 show_server_->setSucceeded(result, "Some other action is handled at the moment or training mode not started.");
00519 return;
00520 }
00521
00522
00523 loadTrainingData(false);
00524 if (goal->mode == 0)
00525 {
00526
00527 cv::Mat avgImage(100, 100, CV_8UC1);
00528 PCA();
00529 showAVGImage(avgImage);
00530
00531 cv::namedWindow("AVGImage");
00532 cv::imshow("AVGImage", avgImage);
00533 cv::waitKey(3000);
00534
00535 cv::destroyWindow("AVGImage");
00536 }
00537 else if (goal->mode == 1)
00538 {
00539
00540 cv::Mat eigenface;
00541 cv::namedWindow("Eigenfaces");
00542 PCA();
00543 for (int i = 0; i < (int)20; i++)
00544 {
00545 getEigenface(eigenface, i);
00546 cv::imshow("Eigenfaces", eigenface);
00547 cv::waitKey();
00548 }
00549 cv::destroyWindow("Eigenfaces");
00550 }
00551
00552 result.success = ipa_Utils::RET_OK;
00553 show_server_->setSucceeded(result);
00554 }
00555
00556 unsigned long CobFaceDetectionNodelet::detectFaces(cv::Mat& xyz_image, cv::Mat& color_image)
00557 {
00558 cv::Mat xyz_image_8U3;
00559 ipa_Utils::ConvertToShowImage(xyz_image, xyz_image_8U3, 3);
00560 if (people_detector_->DetectFaces(color_image, xyz_image_8U3, color_faces_, range_faces_, range_face_indices_with_color_face_detection_, fill_unassigned_depth_values_)
00561 & ipa_Utils::RET_FAILED)
00562 {
00563 std::cerr << "ERROR - PeopleDetection::detectFaces" << std::endl;
00564 std::cerr << "\t ... Could not detect faces.\n";
00565 return ipa_Utils::RET_FAILED;
00566 }
00567
00568
00569 std::vector < cv::Rect > tempFaces = color_faces_;
00570 color_faces_.clear();
00571
00572 for (uint iface = 0; iface < tempFaces.size(); iface++)
00573 {
00574 cv::Rect& face = tempFaces[iface];
00575
00576
00577
00578
00579
00580 int uStart = floor(0.25 * face.width);
00581 int uEnd = floor(0.75 * face.width) + 1;
00582 int vStart = floor(0.25 * face.height);
00583 int vEnd = floor(0.75 * face.height) + 1;
00584 int du = abs(uEnd - uStart);
00585
00586 cv::Mat faceRegion = xyz_image(face);
00587 cv::Mat tmat(1, du * abs(vEnd - vStart), CV_32FC1);
00588 float* tmatPtr = (float*)tmat.data;
00589 for (int v = vStart; v < vEnd; v++)
00590 {
00591 float* zPtr = (float*)faceRegion.row(v).data;
00592 zPtr += 2 + 3 * uStart;
00593 for (int u = uStart; u < uEnd; u++)
00594 {
00595 float depthval = *zPtr;
00596 if (!isnan(depthval))
00597 *tmatPtr = depthval;
00598 else
00599 *tmatPtr = 1e20;
00600 tmatPtr++;
00601 zPtr += 3;
00602 }
00603 }
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 cv::Mat tmat_sorted;
00616 cv::sort(tmat, tmat_sorted, CV_SORT_EVERY_COLUMN + CV_SORT_DESCENDING);
00617 double avg_depth = tmat_sorted.at<float>(floor(cv::countNonZero(tmat_sorted >= 0.0) * 0.5));
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628 if (avg_depth > 0)
00629 {
00630 double radiusX, radiusY, radius3d = 1e20;
00631 cv::Vec3f a, b;
00632
00633
00634 a = xyz_image.at<cv::Vec3f>((int)(face.y + face.height * 0.25), (int)(face.x + 0.5 * face.width));
00635 b = xyz_image.at<cv::Vec3f>((int)(face.y + face.height * 0.75), (int)(face.x + 0.5 * face.width));
00636 if (display_)
00637 std::cout << "a: " << a.val[0] << " " << a.val[1] << " " << a.val[2] << " b: " << " " << b.val[0] << " " << b.val[1] << " " << b.val[2] << "\n";
00638 if (isnan(a.val[0]) || isnan(b.val[0]))
00639 radiusY = 0.0;
00640 else
00641 radiusY = cv::norm(b - a);
00642 radius3d = radiusY;
00643
00644
00645 a = xyz_image.at<cv::Vec3f>((int)(face.y + face.height * 0.5), (int)(face.x + face.width * 0.25));
00646 b = xyz_image.at<cv::Vec3f>((int)(face.y + face.height * 0.5), (int)(face.x + face.width * 0.75));
00647 if (display_)
00648 std::cout << "a: " << a.val[0] << " " << a.val[1] << " " << a.val[2] << " b: " << " " << b.val[0] << " " << b.val[1] << " " << b.val[2] << "\n";
00649 if (isnan(a.val[0]) || isnan(b.val[0]))
00650 radiusX = 0.0;
00651 else
00652 {
00653 radiusX = cv::norm(b - a);
00654 if (radiusY != 0.0)
00655 radius3d = (radiusX + radiusY) * 0.5;
00656 else
00657 radius3d = radiusX;
00658 }
00659
00660
00661
00662
00663
00664
00665
00666
00667 if (display_)
00668 {
00669 std::cout << "radiusX: " << radiusX << " radiusY: " << radiusY << "\n";
00670 std::cout << "avg_depth: " << avg_depth << " > max_face_z_m_: " << max_face_z_m_ << " ? 2*radius3d: " << 2.0 * radius3d << " < face_size_min_m_: "
00671 << face_size_min_m_ << " ? 2radius3d: " << 2.0 * radius3d << " > face_size_max_m_:" << face_size_max_m_ << "?\n";
00672 }
00673 if (reason_about_3dface_size_ == true && radius3d > 0.0 && (avg_depth > max_face_z_m_ || 2.0 * radius3d < face_size_min_m_ || 2.0 * radius3d > face_size_max_m_))
00674 continue;
00675 }
00676 color_faces_.push_back(face);
00677 }
00678
00679
00680
00681 return ipa_Utils::RET_OK;
00682 }
00683
00684 unsigned long CobFaceDetectionNodelet::recognizeFace(cv::Mat& color_image, std::vector<int>& index)
00685 {
00686 if (people_detector_->RecognizeFace(color_image, color_faces_, &n_eigens_, eigen_vectors_, avg_image_, face_class_avg_projections_, index, &threshold_, &threshold_fs_,
00687 eigen_val_mat_, 0) & ipa_Utils::RET_FAILED)
00688 {
00689 std::cerr << "ERROR - PeopleDetector::recognizeFace:" << std::endl;
00690 std::cerr << "\t ... Error while recognizing faces.\n";
00691 return ipa_Utils::RET_FAILED;
00692 }
00693
00694 return ipa_Utils::RET_OK;
00695 }
00696
00697 unsigned long CobFaceDetectionNodelet::addFace(cv::Mat& image, std::string id)
00698 {
00699
00700 if (people_detector_->AddFace(image, color_faces_[0], id, face_images_, id_) & ipa_Utils::RET_FAILED)
00701 {
00702 std::cerr << "ERROR - PeopleDetectorControlFlow::AddFace:" << std::endl;
00703 std::cerr << "\t ... Could not save face.\n";
00704 return ipa_Utils::RET_FAILED;
00705 }
00706 run_pca_ = true;
00707
00708 return ipa_Utils::RET_OK;
00709 }
00710
00711 unsigned long CobFaceDetectionNodelet::PCA()
00712 {
00713
00714 if (!run_pca_)
00715 {
00716
00717
00718 return ipa_Utils::RET_OK;
00719 }
00720
00721 if (face_images_.size() < 2)
00722 {
00723 std::cout << "WARNING - PeopleDetector::ConsoleGUI:" << std::endl;
00724 std::cout << "\t ... Less than two images are trained.\n";
00725 return ipa_Utils::RET_OK;
00726 }
00727
00728
00729 eigen_vectors_.clear();
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 if (people_detector_->PCA(&n_eigens_, eigen_vectors_, eigen_val_mat_, avg_image_, face_images_, projected_train_face_mat_) & ipa_Utils::RET_FAILED)
00747 {
00748 std::cerr << "ERROR - PeopleDetectorControlFlow::PCA:" << std::endl;
00749 std::cerr << "\t ... Error while PCA.\n";
00750 return ipa_Utils::RET_FAILED;
00751 }
00752
00753
00754 std::cout << "Debug: n_eigens: " << n_eigens_ << " id: " << id_.size() << "\n";
00755 if (people_detector_->CalculateFaceClasses(projected_train_face_mat_, id_, &n_eigens_, face_class_avg_projections_, id_unique_, 0)
00756 & ipa_Utils::RET_FAILED)
00757 {
00758 std::cerr << "ERROR - PeopleDetectorControlFlow::PCA:" << std::endl;
00759 std::cerr << "\t ... Error while calculating FaceClasses.\n";
00760 return ipa_Utils::RET_FAILED;
00761 }
00762
00763 run_pca_ = false;
00764
00765 return ipa_Utils::RET_OK;
00766 }
00767
00768 unsigned long CobFaceDetectionNodelet::saveAllData()
00769 {
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781 if (saveTrainingData() != ipa_Utils::RET_OK)
00782 return ipa_Utils::RET_FAILED;
00783 if (saveRecognizerData() != ipa_Utils::RET_OK)
00784 return ipa_Utils::RET_FAILED;
00785
00786 return ipa_Utils::RET_OK;
00787 }
00788
00789 unsigned long CobFaceDetectionNodelet::saveTrainingData()
00790 {
00791 std::string path = directory_ + "TrainingData/";
00792 std::string filename = "tdata.xml";
00793 std::string img_ext = ".bmp";
00794
00795 std::ostringstream complete;
00796 complete << path << filename;
00797
00798 cv::FileStorage fileStorage(complete.str().c_str(), cv::FileStorage::WRITE);
00799 if (!fileStorage.isOpened())
00800 {
00801 std::cout << "WARNING - PeopleDetector::SaveTrainingData:" << std::endl;
00802 std::cout << "\t ... Can't save training data.\n";
00803 return ipa_Utils::RET_OK;
00804 }
00805
00806
00807 fileStorage << "id_num" << (int)id_.size();
00808 for (int i = 0; i < (int)id_.size(); i++)
00809 {
00810 std::ostringstream tag;
00811 tag << "id_" << i;
00812 fileStorage << tag.str().c_str() << id_[i].c_str();
00813 }
00814
00815
00816 fileStorage << "faces_num" << (int)face_images_.size();
00817 for (int i = 0; i < (int)face_images_.size(); i++)
00818 {
00819 std::ostringstream img, shortname;
00820 img << path << i << img_ext;
00821 shortname << "TrainingData/" << i << img_ext;
00822 std::ostringstream tag;
00823 tag << "img_" << i;
00824 fileStorage << tag.str().c_str() << shortname.str().c_str();
00825 cv::imwrite(img.str().c_str(), face_images_[i]);
00826 }
00827
00828 fileStorage.release();
00829
00830 std::cout << "INFO - PeopleDetector::SaveTrainingData:" << std::endl;
00831 std::cout << "\t ... " << face_images_.size() << " images saved.\n";
00832 return ipa_Utils::RET_OK;
00833 }
00834
00835 unsigned long CobFaceDetectionNodelet::saveRecognizerData()
00836 {
00837 std::string path = directory_ + "TrainingData/";
00838 std::string filename = "rdata.xml";
00839
00840 std::ostringstream complete;
00841 complete << path << filename;
00842
00843 cv::FileStorage fileStorage(complete.str().c_str(), cv::FileStorage::WRITE);
00844 if (!fileStorage.isOpened())
00845 {
00846 std::cout << "WARNING - PeopleDetector::saveRecognizerData:" << std::endl;
00847 std::cout << "\t ... Can't save training data.\n";
00848 return ipa_Utils::RET_OK;
00849 }
00850
00851
00852 fileStorage << "eigens_num" << n_eigens_;
00853
00854
00855 for (int i = 0; i < n_eigens_; i++)
00856 {
00857 std::ostringstream tag;
00858 tag << "ev_" << i;
00859 fileStorage << tag.str().c_str() << eigen_vectors_[i];
00860 }
00861
00862
00863 fileStorage << "eigen_val_mat" << eigen_val_mat_;
00864
00865
00866 fileStorage << "avg_image" << avg_image_;
00867
00868
00869 fileStorage << "projected_train_face_mat" << projected_train_face_mat_;
00870
00871
00872 fileStorage << "id_unique_num" << (int)id_unique_.size();
00873 for (int i = 0; i < (int)id_unique_.size(); i++)
00874 {
00875 std::ostringstream tag;
00876 tag << "id_unique_" << i;
00877 fileStorage << tag.str().c_str() << id_unique_[i].c_str();
00878 }
00879
00880
00881 fileStorage << "face_class_avg_projections" << face_class_avg_projections_;
00882
00883 fileStorage.release();
00884
00885
00886 std::string classifierFile = path + "svm.dat";
00887
00888
00889 std::cout << "INFO - PeopleDetector::saveRecognizerData:" << std::endl;
00890 std::cout << "\t ... recognizer data saved.\n";
00891 return ipa_Utils::RET_OK;
00892 }
00893
00894 unsigned long CobFaceDetectionNodelet::loadAllData()
00895 {
00896 if (loadTrainingData(true) != ipa_Utils::RET_OK)
00897 return ipa_Utils::RET_FAILED;
00898 if (loadRecognizerData() != ipa_Utils::RET_OK)
00899 return ipa_Utils::RET_FAILED;
00900
00901 return ipa_Utils::RET_OK;
00902 }
00903
00904 unsigned long CobFaceDetectionNodelet::loadTrainingData(bool runPCA)
00905 {
00906 std::string path = directory_ + "TrainingData/";
00907 std::string filename = "tdata.xml";
00908
00909 std::ostringstream complete;
00910 complete << path << filename;
00911
00912 if (fs::is_directory(path.c_str()))
00913 {
00914 cv::FileStorage fileStorage(complete.str().c_str(), cv::FileStorage::READ);
00915 if (!fileStorage.isOpened())
00916 {
00917 std::cout << "WARNING - PeopleDetector::loadTrainingData:" << std::endl;
00918 std::cout << "\t ... Cant open " << complete.str() << ".\n";
00919 return ipa_Utils::RET_OK;
00920 }
00921
00922
00923 id_.clear();
00924 int id_num = (int)fileStorage["id_num"];
00925 for (int i = 0; i < id_num; i++)
00926 {
00927 std::ostringstream tag;
00928 tag << "id_" << i;
00929 id_.push_back((std::string)fileStorage[tag.str().c_str()]);
00930 }
00931
00932
00933 face_images_.clear();
00934 int faces_num = (int)fileStorage["faces_num"];
00935 for (int i = 0; i < faces_num; i++)
00936 {
00937 std::ostringstream tag;
00938 tag << "img_" << i;
00939 std::string path = directory_ + (std::string)fileStorage[tag.str().c_str()];
00940 cv::Mat temp = cv::imread(path.c_str(), 0);
00941 face_images_.push_back(temp);
00942 }
00943
00944
00945 filename_ = faces_num;
00946
00947 fileStorage.release();
00948
00949
00950 run_pca_ = true;
00951 if (runPCA)
00952 PCA();
00953
00954 std::cout << "INFO - PeopleDetector::loadTrainingData:" << std::endl;
00955 std::cout << "\t ... " << faces_num << " images loaded.\n";
00956 }
00957 else
00958 {
00959 std::cerr << "ERROR - PeopleDetector::loadTrainingData:" << std::endl;
00960 std::cerr << "\t .... Path '" << path << "' is not a directory." << std::endl;
00961 return ipa_Utils::RET_FAILED;
00962 }
00963
00964 return ipa_Utils::RET_OK;
00965 }
00966
00967 unsigned long CobFaceDetectionNodelet::loadRecognizerData()
00968 {
00969 std::string path = directory_ + "TrainingData/";
00970 std::string filename = "rdata.xml";
00971
00972 std::ostringstream complete;
00973 complete << path << filename;
00974
00975 if (fs::is_directory(path.c_str()))
00976 {
00977 cv::FileStorage fileStorage(complete.str().c_str(), cv::FileStorage::READ);
00978 if (!fileStorage.isOpened())
00979 {
00980 std::cout << "WARNING - PeopleDetector::loadRecognizerData:" << std::endl;
00981 std::cout << "\t ... Cant open " << complete.str() << ".\n";
00982 return ipa_Utils::RET_OK;
00983 }
00984 std::cout << " loading recognizer data..." << std::endl;
00985
00986
00987 n_eigens_ = (int)fileStorage["eigens_num"];
00988
00989
00990 eigen_vectors_.clear();
00991 eigen_vectors_.resize(n_eigens_, cv::Mat());
00992 for (int i = 0; i < n_eigens_; i++)
00993 {
00994 std::ostringstream tag;
00995 tag << "ev_" << i;
00996 fileStorage[tag.str().c_str()] >> eigen_vectors_[i];
00997 }
00998
00999
01000 eigen_val_mat_ = cv::Mat();
01001 fileStorage["eigen_val_mat"] >> eigen_val_mat_;
01002
01003
01004 avg_image_ = cv::Mat();
01005 fileStorage["avg_image"] >> avg_image_;
01006
01007
01008 projected_train_face_mat_ = cv::Mat();
01009 fileStorage["projected_train_face_mat"] >> projected_train_face_mat_;
01010
01011
01012 id_unique_.clear();
01013 int idUniqueNum = (int)fileStorage["id_unique_num"];
01014 for (int i = 0; i < idUniqueNum; i++)
01015 {
01016 std::ostringstream tag;
01017 tag << "id_unique_" << i;
01018 id_unique_.push_back((std::string)fileStorage[tag.str().c_str()]);
01019 }
01020
01021
01022 face_class_avg_projections_ = cv::Mat();
01023 fileStorage["face_class_avg_projections"] >> face_class_avg_projections_;
01024
01025 fileStorage.release();
01026
01027
01028 std::string classifierFile = path + "svm.dat";
01029
01030
01031
01032 run_pca_ = false;
01033
01034 std::cout << "INFO - PeopleDetector::loadRecognizerData:" << std::endl;
01035 std::cout << "\t ... recognizer data loaded.\n";
01036 }
01037 else
01038 {
01039 std::cerr << "ERROR - PeopleDetector::loadRecognizerData():" << std::endl;
01040 std::cerr << "\t .... Path '" << path << "' is not a directory." << std::endl;
01041 return ipa_Utils::RET_FAILED;
01042 }
01043
01044 return ipa_Utils::RET_OK;
01045 }
01046
01047 unsigned long CobFaceDetectionNodelet::getEigenface(cv::Mat& eigenface, int index)
01048 {
01049 cv::normalize(eigen_vectors_[index], eigenface, 0, 255, cv::NORM_MINMAX, CV_8UC1);
01050
01051 return ipa_Utils::RET_OK;
01052 }
01053
01054 unsigned long CobFaceDetectionNodelet::showAVGImage(cv::Mat& avgImage)
01055 {
01056 if (!run_pca_ && face_images_.size() < 2)
01057 {
01058 std::cerr << "PeopleDetector::showAvgImage()" << std::endl;
01059 std::cerr << "No AVG image calculated" << std::endl;
01060 return 0;
01061 }
01062
01063 cv::normalize(avg_image_, avgImage, 0, 255, cv::NORM_MINMAX, CV_8UC1);
01064
01065 return ipa_Utils::RET_OK;
01066 }
01067
01068 unsigned long CobFaceDetectionNodelet::saveRangeTrainImages(cv::Mat& xyz_image)
01069 {
01070 std::string path = directory_ + "haarcascades/";
01071 std::string img_ext = ".jpg";
01072 cv::Mat xyzImage_8U3(xyz_image.size(), CV_8UC3);
01073 ipa_Utils::ConvertToShowImage(xyz_image, xyzImage_8U3, 3);
01074
01075 for (int i = 0; i < (int)color_faces_.size(); i++)
01076 {
01077 cv::Mat xyzImage_8U3_resized(100, 100, CV_8UC3);
01078
01079 double scale = 1.6;
01080 cv::Rect rangeFace;
01081 rangeFace.height = (int)(color_faces_[i].height * scale);
01082 rangeFace.width = (int)(color_faces_[i].width * scale);
01083 rangeFace.x = color_faces_[i].x - ((rangeFace.width - color_faces_[i].width) / 2);
01084 rangeFace.y = color_faces_[i].y - ((rangeFace.height - color_faces_[i].height) / 2) - 10;
01085
01086 cv::Mat xyzImage_8U3_roi = xyzImage_8U3(rangeFace);
01087
01088 cv::resize(xyzImage_8U3_roi, xyzImage_8U3_resized, xyzImage_8U3_resized.size());
01089
01090 std::ostringstream file;
01091 file << path << filename_ << img_ext;
01092
01093 cv::imwrite(file.str().c_str(), xyzImage_8U3_resized);
01094 filename_++;
01095 }
01096
01097 return ipa_Utils::RET_OK;
01098 }
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01146
01147
01148
01149
01150
01151 unsigned long CobFaceDetectionNodelet::convertColorImageMessageToMat(const sensor_msgs::Image::ConstPtr& color_image_msg, cv_bridge::CvImageConstPtr& color_image_ptr,
01152 cv::Mat& color_image)
01153 {
01154 try
01155 {
01156 color_image_ptr = cv_bridge::toCvShare(color_image_msg, sensor_msgs::image_encodings::BGR8);
01157 } catch (cv_bridge::Exception& e)
01158 {
01159 ROS_ERROR("PeopleDetection: cv_bridge exception: %s", e.what());
01160 return ipa_Utils::RET_FAILED;
01161 }
01162 color_image = color_image_ptr->image;
01163
01164 return ipa_Utils::RET_OK;
01165 }
01166
01167 unsigned long CobFaceDetectionNodelet::convertPclMessageToMat(const sensor_msgs::PointCloud2::ConstPtr& shared_image_msg, cv::Mat& depth_image)
01168 {
01169 pcl::PointCloud < pcl::PointXYZ > depth_cloud;
01170 pcl::fromROSMsg(*shared_image_msg, depth_cloud);
01171 depth_image.create(depth_cloud.height, depth_cloud.width, CV_32FC3);
01172 uchar* depth_image_ptr = (uchar*)depth_image.data;
01173 for (int v = 0; v < (int)depth_cloud.height; v++)
01174 {
01175 int baseIndex = depth_image.step * v;
01176 for (int u = 0; u < (int)depth_cloud.width; u++)
01177 {
01178 int index = baseIndex + 3 * u * sizeof(float);
01179 float* data_ptr = (float*)(depth_image_ptr + index);
01180 pcl::PointXYZ point_xyz = depth_cloud(u, v);
01181 data_ptr[0] = point_xyz.x;
01182 data_ptr[1] = point_xyz.y;
01183 data_ptr[2] = (isnan(point_xyz.z)) ? 0.f : point_xyz.z;
01184
01185 }
01186 }
01187 return ipa_Utils::RET_OK;
01188 }
01189
01190 inline std::string CobFaceDetectionNodelet::getLabel(int index)
01191 {
01192 switch (index)
01193 {
01194 case -1:
01195
01196 return "Unknown";
01197 break;
01198 case -2:
01199
01200 return "No face";
01201 break;
01202 default:
01203
01204 return id_unique_[index];
01205 }
01206 }
01207
01208 inline int abs(int x)
01209 {
01210 return ((x < 0) ? -x : x);
01211 }
01212
01213 void CobFaceDetectionNodelet::recognizeCallback(const sensor_msgs::PointCloud2::ConstPtr& shared_image_msg, const sensor_msgs::Image::ConstPtr& color_image_msg)
01214 {
01215
01216 if (train_continuous_server_running_ == true)
01217 {
01218 trainContinuousCallback(shared_image_msg, color_image_msg);
01219 return;
01220 }
01221
01222
01223 if (recognize_server_running_ == false)
01224 return;
01225
01226
01227
01228 cv_bridge::CvImageConstPtr color_image_ptr;
01229 cv::Mat color_image;
01230 convertColorImageMessageToMat(color_image_msg, color_image_ptr, color_image);
01231
01232
01233 cv::Mat depth_image;
01234 convertPclMessageToMat(shared_image_msg, depth_image);
01235
01236 #ifdef __LINUX__
01237 color_image_ = color_image;
01238 range_image_ = depth_image;
01239 #else
01240
01241 colored_pc_->SetColorImage(color_image);
01242 colored_pc_->SetXYZImage(depth_image);
01243 #endif
01244
01245
01246
01247 PCA();
01248
01249 if (eigen_vectors_.size() < 1)
01250 {
01251 std::cout << "WARNING - PeopleDetector::ConsoleGUI:" << std::endl;
01252 std::cout << "\t ... Less than two images are trained.\n";
01253 return;
01254 }
01255
01256
01257 cv::Mat colorImage_8U3;
01258 #ifdef __LINUX__
01259 detectFaces(range_image_, color_image_);
01260 colorImage_8U3 = color_image_.clone();
01261 #else
01262 detectFaces(colored_pc_->GetXYZImage(), colored_pc_->GetColorImage());
01263 colored_pc_->GetColorImage().copyTo(colorImage_8U3);
01264 #endif
01265
01266 std::vector<int> index;
01267 if (do_recognition_ == true)
01268 {
01269 recognizeFace(color_image, index);
01270
01271 }
01272 else
01273 for (int i = 0; i < (int)color_faces_.size(); i++)
01274 index.push_back(-1);
01275
01276
01277
01278 cob_perception_msgs::DetectionArray facePositionMsg;
01279
01280
01281 facePositionMsg.header.stamp = shared_image_msg->header.stamp;
01282
01283
01284 for (int i = 0; i < (int)range_faces_.size(); i++)
01285 {
01286
01287 if (range_face_indices_with_color_face_detection_.find(i) == range_face_indices_with_color_face_detection_.end())
01288 {
01289 cv::Rect face = range_faces_[i];
01290
01291
01292 cob_perception_msgs::Detection det;
01293 det.header = shared_image_msg->header;
01294 det.mask.roi.x = face.x;
01295 det.mask.roi.y = face.y;
01296 det.mask.roi.width = face.width;
01297 det.mask.roi.height = face.height;
01298 float center2Dx = face.x + face.width * 0.5f;
01299 float center2Dy = face.y + face.height * 0.5f;
01300
01301
01302 geometry_msgs::Point* point = &(det.pose.pose.position);
01303 cv::Point3f p;
01304 bool validCoordinates = false;
01305 for (int d = 0; (d < 6 && !validCoordinates); d++)
01306 {
01307 for (int v = -d; (v <= d && !validCoordinates); v++)
01308 {
01309 for (int u = -d; (u <= d && !validCoordinates); u++)
01310 {
01311 if (abs(v) != d && abs(u) != d)
01312 continue;
01313
01314 p = depth_image.at<cv::Point3f>(center2Dy + v, center2Dx + u);
01315 point->x = p.x;
01316 point->y = p.y;
01317 point->z = p.z;
01318
01319 if (!isnan(point->x) && !isnan(point->y) && point->z != 0.f)
01320 validCoordinates = true;
01321 }
01322 }
01323 }
01324 if (validCoordinates == false)
01325 continue;
01326
01327
01328 det.label = "UnknownRange";
01329
01330
01331 det.detector = "range";
01332
01333 facePositionMsg.detections.push_back(det);
01334 }
01335 }
01336
01337
01338 for (int i = 0; i < (int)color_faces_.size(); i++)
01339 {
01340 cv::Rect face = color_faces_[i];
01341
01342
01343 cob_perception_msgs::Detection det;
01344 det.mask.roi.x = face.x;
01345 det.mask.roi.y = face.y;
01346 det.mask.roi.width = face.width;
01347 det.mask.roi.height = face.height;
01348 float center2Dx = face.x + face.width * 0.5f;
01349 float center2Dy = face.y + face.height * 0.5f;
01350
01351
01352
01353
01354
01355
01356
01357 geometry_msgs::Point* point = &(det.pose.pose.position);
01358 cv::Point3f p;
01359 bool validCoordinates = false;
01360 for (int d = 0; (d < 6 && !validCoordinates); d++)
01361 {
01362 for (int v = -d; (v <= d && !validCoordinates); v++)
01363 {
01364 for (int u = -d; (u <= d && !validCoordinates); u++)
01365 {
01366 if (abs(v) != d && abs(u) != d)
01367 continue;
01368
01369 p = depth_image.at<cv::Point3f>(center2Dy + v, center2Dx + u);
01370 point->x = p.x;
01371 point->y = p.y;
01372 point->z = p.z;
01373
01374 if (!isnan(point->x) && !isnan(point->y) && point->z != 0.f)
01375 validCoordinates = true;
01376 }
01377 }
01378 }
01379 if (validCoordinates == false)
01380 continue;
01381
01382
01383 det.label = getLabel(index[i]);
01384
01385
01386 det.detector = "color";
01387
01388 facePositionMsg.detections.push_back(det);
01389 }
01390 face_position_publisher_.publish(facePositionMsg);
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423 if (display_ == true)
01424 {
01425 for (int i = 0; i < (int)range_faces_.size(); i++)
01426 {
01427 cv::Rect face = range_faces_[i];
01428 cv::rectangle(colorImage_8U3, cv::Point(face.x, face.y), cv::Point(face.x + face.width, face.y + face.height), CV_RGB(0, 0, 255), 2, 8, 0);
01429 }
01430
01431 for (int i = 0; i < (int)color_faces_.size(); i++)
01432 {
01433 cv::Rect face = color_faces_[i];
01434
01435 cv::rectangle(colorImage_8U3, cv::Point(face.x, face.y), cv::Point(face.x + face.width, face.y + face.height), CV_RGB(0, 255, 0), 2, 8, 0);
01436
01437 std::stringstream tmp;
01438 switch (index[i])
01439 {
01440 case -1:
01441
01442 tmp << "Unknown";
01443 cv::putText(colorImage_8U3, tmp.str().c_str(), cv::Point(face.x, face.y + face.height + 25), cv::FONT_HERSHEY_PLAIN, 2, CV_RGB( 255, 0, 0 ), 2);
01444 break;
01445 case -2:
01446
01447 tmp << "No face";
01448 cv::putText(colorImage_8U3, tmp.str().c_str(), cv::Point(face.x, face.y + face.height + 25), cv::FONT_HERSHEY_PLAIN, 2, CV_RGB( 255, 0, 0 ), 2);
01449 break;
01450 default:
01451
01452 tmp << id_unique_[index[i]].c_str();
01453 cv::putText(colorImage_8U3, tmp.str().c_str(), cv::Point(face.x, face.y + face.height + 25), cv::FONT_HERSHEY_PLAIN, 2, CV_RGB( 0, 255, 0 ), 2);
01454 }
01455 }
01456
01457
01458
01459 cv_bridge::CvImage cv_ptr;
01460 cv_ptr.image = colorImage_8U3;
01461 cv_ptr.encoding = "bgr8";
01462 face_detection_image_pub_.publish(cv_ptr.toImageMsg());
01463 }
01464 }
01465
01466 void CobFaceDetectionNodelet::trainContinuousCallback(const sensor_msgs::PointCloud2::ConstPtr& shared_image_msg, const sensor_msgs::Image::ConstPtr& color_image_msg)
01467 {
01468 if (train_continuous_server_running_ == false)
01469 return;
01470
01471
01472
01473 cv_bridge::CvImageConstPtr color_image_ptr;
01474 cv::Mat color_image;
01475 convertColorImageMessageToMat(color_image_msg, color_image_ptr, color_image);
01476
01477
01478 cv::Mat depth_image;
01479 convertPclMessageToMat(shared_image_msg, depth_image);
01480
01481 #ifdef __LINUX__
01482 color_image_ = color_image;
01483 range_image_ = depth_image;
01484 #else
01485
01486 colored_pc_->SetColorImage(color_image);
01487 colored_pc_->SetXYZImage(depth_image);
01488 #endif
01489
01490
01491 cv::Mat colorImage_8U3;
01492 #ifdef __LINUX__
01493 detectFaces(range_image_, color_image_);
01494 colorImage_8U3 = color_image_.clone();
01495 #else
01496 detectFaces(colored_pc_->GetXYZImage(), colored_pc_->GetColorImage());
01497 colored_pc_->GetColorImage().copyTo(colorImage_8U3);
01498 #endif
01499
01500 for (int i = 0; i < (int)color_faces_.size(); i++)
01501 {
01502 cv::Rect face = color_faces_[i];
01503 cv::rectangle(colorImage_8U3, cv::Point(face.x, face.y), cv::Point(face.x + face.width, face.y + face.height), CV_RGB( 0, 255, 0 ), 2, 8, 0);
01504 }
01505
01506
01507
01508
01509 cv_bridge::CvImage cv_ptr;
01510 cv_ptr.image = colorImage_8U3;
01511 cv_ptr.encoding = "bgr8";
01512 face_detection_image_pub_.publish(cv_ptr.toImageMsg());
01513
01514
01515
01516 boost::timed_mutex::scoped_timed_lock lock(action_mutex_, boost::posix_time::milliseconds(10));
01517 if (lock.owns_lock() && capture_training_face_ == true)
01518 {
01519 capture_training_face_ = false;
01520
01521
01522 if (color_faces_.size() > 1)
01523 {
01524 std::cout << "WARNING - CobFaceDetectionNodelet::trainContinuousCallback:" << std::endl;
01525 std::cout << "\t ... More than one faces are detected in image. Please try again." << std::endl;
01526 return;
01527 }
01528
01529
01530 if (color_faces_.size() < 1)
01531 {
01532 std::cout << "WARNING - CobFaceDetectionNodelet::trainContinuousCallback:" << std::endl;
01533 std::cout << "\t ... Less than one faces are detected in image. Please try again." << std::endl;
01534 return;
01535 }
01536
01537 #ifdef __LINUX__
01538 addFace(color_image_, current_training_id_);
01539 #else
01540 addFace(colored_pc_->GetColorImage(), current_training_id_);
01541 #endif
01542 number_training_images_captured_++;
01543 std::cout << "INFO - CuiPeopleDetector::ConsoleGUI:" << std::endl;
01544 std::cout << "\t ... Face captured (" << face_images_.size() << ")." << std::endl;
01545 }
01546 }
01547
01548 unsigned long CobFaceDetectionNodelet::loadParameters(const char* iniFileName)
01549 {
01551 TiXmlDocument* p_configXmlDocument = new TiXmlDocument(iniFileName);
01552 if (!p_configXmlDocument->LoadFile())
01553 {
01554 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01555 std::cerr << "\t ... Error while loading xml configuration file" << std::endl;
01556 std::cerr << "\t ... (Check filename and syntax of the file):" << std::endl;
01557 std::cerr << "\t ... '" << iniFileName << "'" << std::endl;
01558 return ipa_Utils::RET_FAILED;
01559 }
01560 std::cout << "INFO - PeopleDetector::LoadParameters:" << std::endl;
01561 std::cout << "\t ... Parsing xml configuration file:" << std::endl;
01562 std::cout << "\t ... '" << iniFileName << "'" << std::endl;
01563
01564 if (p_configXmlDocument)
01565 {
01566
01567
01568
01569
01570
01571 TiXmlElement *p_xmlElement_Root = NULL;
01572 p_xmlElement_Root = p_configXmlDocument->FirstChildElement("PeopleDetector");
01573
01574 if (p_xmlElement_Root)
01575 {
01576
01577
01578
01579
01580
01581 TiXmlElement *p_xmlElement_Root_OD = NULL;
01582 p_xmlElement_Root_OD = p_xmlElement_Root->FirstChildElement("adaBoost");
01583
01584 if (p_xmlElement_Root_OD)
01585 {
01586
01587
01588
01589
01590
01591 TiXmlElement *p_xmlElement_Child = NULL;
01592 p_xmlElement_Child = p_xmlElement_Root_OD->FirstChildElement("Faces_increase_search_scale");
01593
01594 if (p_xmlElement_Child)
01595 {
01596
01597 if (p_xmlElement_Child->QueryValueAttribute("value", &people_detector_->m_faces_increase_search_scale) != TIXML_SUCCESS)
01598 {
01599 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01600 std::cerr << "\t ... Can't find attribute 'value' of tag 'Faces_increase_search_scale'" << std::endl;
01601 return ipa_Utils::RET_FAILED;
01602 }
01603 }
01604 else
01605 {
01606 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01607 std::cerr << "\t ... Can't find tag 'Faces_increase_search_scale'" << std::endl;
01608 return ipa_Utils::RET_FAILED;
01609 }
01610
01611
01612
01613
01614
01615 p_xmlElement_Child = NULL;
01616 p_xmlElement_Child = p_xmlElement_Root_OD->FirstChildElement("Faces_drop_groups");
01617
01618 if (p_xmlElement_Child)
01619 {
01620
01621 if (p_xmlElement_Child->QueryValueAttribute("value", &people_detector_->m_faces_drop_groups) != TIXML_SUCCESS)
01622 {
01623 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01624 std::cerr << "\t ... Can't find attribute 'value' of tag 'Faces_drop_groups'" << std::endl;
01625 return ipa_Utils::RET_FAILED;
01626 }
01627 }
01628 else
01629 {
01630 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01631 std::cerr << "\t ... Can't find tag 'Faces_drop_groups'" << std::endl;
01632 return ipa_Utils::RET_FAILED;
01633 }
01634
01635
01636
01637
01638
01639 p_xmlElement_Child = NULL;
01640 p_xmlElement_Child = p_xmlElement_Root_OD->FirstChildElement("Faces_min_search_scale_x");
01641
01642 if (p_xmlElement_Child)
01643 {
01644
01645 if (p_xmlElement_Child->QueryValueAttribute("value", &people_detector_->m_faces_min_search_scale_x) != TIXML_SUCCESS)
01646 {
01647 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01648 std::cerr << "\t ... Can't find attribute 'value' of tag 'Faces_min_search_scale_x'" << std::endl;
01649 return ipa_Utils::RET_FAILED;
01650 }
01651 }
01652 else
01653 {
01654 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01655 std::cerr << "\t ... Can't find tag 'Faces_min_search_scale_x'" << std::endl;
01656 return ipa_Utils::RET_FAILED;
01657 }
01658
01659
01660
01661
01662
01663 p_xmlElement_Child = NULL;
01664 p_xmlElement_Child = p_xmlElement_Root_OD->FirstChildElement("Faces_min_search_scale_y");
01665
01666 if (p_xmlElement_Child)
01667 {
01668
01669 if (p_xmlElement_Child->QueryValueAttribute("value", &people_detector_->m_faces_min_search_scale_y) != TIXML_SUCCESS)
01670 {
01671 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01672 std::cerr << "\t ... Can't find attribute 'value' of tag 'Faces_min_search_scale_y'" << std::endl;
01673 return ipa_Utils::RET_FAILED;
01674 }
01675 }
01676 else
01677 {
01678 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01679 std::cerr << "\t ... Can't find tag 'Faces_min_search_scale_y'" << std::endl;
01680 return ipa_Utils::RET_FAILED;
01681 }
01682
01683
01684
01685
01686
01687 p_xmlElement_Child = NULL;
01688 p_xmlElement_Child = p_xmlElement_Root_OD->FirstChildElement("Range_increase_search_scale");
01689
01690 if (p_xmlElement_Child)
01691 {
01692
01693 if (p_xmlElement_Child->QueryValueAttribute("value", &people_detector_->m_range_increase_search_scale) != TIXML_SUCCESS)
01694 {
01695 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01696 std::cerr << "\t ... Can't find attribute 'value' of tag 'Range_increase_search_scale'" << std::endl;
01697 return ipa_Utils::RET_FAILED;
01698 }
01699 }
01700 else
01701 {
01702 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01703 std::cerr << "\t ... Can't find tag 'Range_increase_search_scale'" << std::endl;
01704 return ipa_Utils::RET_FAILED;
01705 }
01706
01707
01708
01709
01710
01711 p_xmlElement_Child = NULL;
01712 p_xmlElement_Child = p_xmlElement_Root_OD->FirstChildElement("Range_drop_groups");
01713
01714 if (p_xmlElement_Child)
01715 {
01716
01717 if (p_xmlElement_Child->QueryValueAttribute("value", &people_detector_->m_range_drop_groups) != TIXML_SUCCESS)
01718 {
01719 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01720 std::cerr << "\t ... Can't find attribute 'value' of tag 'Range_drop_groups'" << std::endl;
01721 return ipa_Utils::RET_FAILED;
01722 }
01723 }
01724 else
01725 {
01726 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01727 std::cerr << "\t ... Can't find tag 'Range_drop_groups'" << std::endl;
01728 return ipa_Utils::RET_FAILED;
01729 }
01730
01731
01732
01733
01734
01735 p_xmlElement_Child = NULL;
01736 p_xmlElement_Child = p_xmlElement_Root_OD->FirstChildElement("Range_min_search_scale_x");
01737
01738 if (p_xmlElement_Child)
01739 {
01740
01741 if (p_xmlElement_Child->QueryValueAttribute("value", &people_detector_->m_range_min_search_scale_x) != TIXML_SUCCESS)
01742 {
01743 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01744 std::cerr << "\t ... Can't find attribute 'value' of tag 'Range_min_search_scale_x'" << std::endl;
01745 return ipa_Utils::RET_FAILED;
01746 }
01747 }
01748 else
01749 {
01750 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01751 std::cerr << "\t ... Can't find tag 'Range_min_search_scale_x'" << std::endl;
01752 return ipa_Utils::RET_FAILED;
01753 }
01754
01755
01756
01757
01758
01759 p_xmlElement_Child = NULL;
01760 p_xmlElement_Child = p_xmlElement_Root_OD->FirstChildElement("Range_min_search_scale_y");
01761
01762 if (p_xmlElement_Child)
01763 {
01764
01765 if (p_xmlElement_Child->QueryValueAttribute("value", &people_detector_->m_range_min_search_scale_y) != TIXML_SUCCESS)
01766 {
01767 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01768 std::cerr << "\t ... Can't find attribute 'value' of tag 'Range_min_search_scale_y'" << std::endl;
01769 return ipa_Utils::RET_FAILED;
01770 }
01771 }
01772 else
01773 {
01774 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01775 std::cerr << "\t ... Can't find tag 'Range_min_search_scale_y'" << std::endl;
01776 return ipa_Utils::RET_FAILED;
01777 }
01778 }
01779
01780
01781
01782
01783
01784
01785
01786
01787 p_xmlElement_Root_OD = NULL;
01788 p_xmlElement_Root_OD = p_xmlElement_Root->FirstChildElement("eigenfaces");
01789
01790 if (p_xmlElement_Root_OD)
01791 {
01792
01793
01794
01795
01796
01797 TiXmlElement *p_xmlElement_Child = NULL;
01798 p_xmlElement_Child = p_xmlElement_Root_OD->FirstChildElement("Threshold_Face_Class");
01799
01800 if (p_xmlElement_Child)
01801 {
01802
01803 if (p_xmlElement_Child->QueryValueAttribute("value", &threshold_) != TIXML_SUCCESS)
01804 {
01805 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01806 std::cerr << "\t ... Can't find attribute 'value' of tag 'Threshold_Face_Class'" << std::endl;
01807 return ipa_Utils::RET_FAILED;
01808 }
01809 }
01810 else
01811 {
01812 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01813 std::cerr << "\t ... Can't find tag 'Threshold_Face_Class'" << std::endl;
01814 return ipa_Utils::RET_FAILED;
01815 }
01816
01817
01818
01819
01820 p_xmlElement_Child = NULL;
01821 p_xmlElement_Child = p_xmlElement_Root_OD->FirstChildElement("Threshold_Facespace");
01822
01823 if (p_xmlElement_Child)
01824 {
01825
01826 if (p_xmlElement_Child->QueryValueAttribute("value", &threshold_fs_) != TIXML_SUCCESS)
01827 {
01828 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01829 std::cerr << "\t ... Can't find attribute 'value' of tag 'Threshold_Facespace'" << std::endl;
01830 return ipa_Utils::RET_FAILED;
01831 }
01832 }
01833 else
01834 {
01835 std::cerr << "ERROR - PeopleDetector::LoadParameters:" << std::endl;
01836 std::cerr << "\t ... Can't find tag 'Threshold_Facespace'" << std::endl;
01837 return ipa_Utils::RET_FAILED;
01838 }
01839
01840
01841
01842
01843 }
01844 else
01845 {
01846 std::cerr << "ERROR - CameraDataViewerControlFlow::LoadParameters:" << std::endl;
01847 std::cerr << "\t ... Can't find tag 'ObjectDetectorParameters'" << std::endl;
01848 return ipa_Utils::RET_FAILED;
01849 }
01850
01851 }
01852
01853
01854
01855
01856 else
01857 {
01858 std::cerr << "ERROR - CameraDataViewerControlFlow::LoadParameters:" << std::endl;
01859 std::cerr << "\t ... Can't find tag 'ObjectDetector'" << std::endl;
01860 return ipa_Utils::RET_FAILED;
01861 }
01862 }
01863 return ipa_Utils::RET_OK;
01864 }
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892