face_capture_node.cpp
Go to the documentation of this file.
00001 
00060 #include <cob_people_detection/face_capture_node.h>
00061 
00062 using namespace ipa_PeopleDetector;
00063 
00064 // Prevent deleting memory twice, when using smart pointer
00065 void voidDeleter(const sensor_msgs::Image* const) {}
00066 
00067 FaceCaptureNode::FaceCaptureNode(ros::NodeHandle nh)
00068 : node_handle_(nh)
00069 {
00070         it_ = 0;
00071         sync_input_2_ = 0;
00072         capture_image_ = false;
00073         finish_image_capture_ = false;
00074         face_images_.clear();
00075         face_depthmaps_.clear();
00076 
00077         // parameters
00078         //data_directory_ = ros::package::getPath("cob_people_detection") + "/common/files/";
00079         bool debug;                                                             // enables some debug outputs
00080         bool use_depth;
00081 
00082         bool norm_illumination;
00083         bool norm_align;
00084         bool norm_extreme_illumination;
00085         int  norm_size;                                         // Desired width and height of the Eigenfaces (=eigenvectors).
00086 
00087         std::cout << "\n---------------------------\nFace Capture Node Parameters:\n---------------------------\n";
00088         if(!node_handle_.getParam("/cob_people_detection/data_storage_directory", data_directory_)) std::cout<<"PARAM NOT AVAILABLE"<<std::endl;
00089         std::cout << "data_directory = " << data_directory_ << "\n";
00090         node_handle_.param("norm_size", norm_size, 100);
00091         std::cout << "norm_size = " << norm_size << "\n";
00092         node_handle_.param("norm_illumination", norm_illumination, true);
00093         std::cout << "norm_illumination = " << norm_illumination << "\n";
00094         node_handle_.param("norm_align", norm_align, false);
00095         std::cout << "norm_align = " << norm_align << "\n";
00096         node_handle_.param("norm_extreme_illumination", norm_extreme_illumination, false);
00097         std::cout << "norm_extreme_illumination = " << norm_extreme_illumination << "\n";
00098         node_handle_.param("debug", debug, false);
00099         std::cout << "debug = " << debug << "\n";
00100         node_handle_.param("use_depth",use_depth,false);
00101         std::cout<< "use depth: "<<use_depth<<"\n";
00102 
00103   
00104         // face recognizer trainer
00105         face_recognizer_trainer_.initTraining(data_directory_, norm_size,norm_illumination,norm_align,norm_extreme_illumination, debug, face_images_, face_depthmaps_, use_depth);
00106 
00107         // subscribers
00108         it_ = new image_transport::ImageTransport(node_handle_);
00109 //      people_segmentation_image_sub_.subscribe(*it_, "people_segmentation_image", 1);
00110 //      face_recognition_subscriber_.subscribe(node_handle_, "face_position_array", 1);
00111 
00112 //      face_detection_subscriber_.subscribe(node_handle_, "face_detections", 1);
00113 //      color_image_sub_.subscribe(*it_, "color_image", 1);
00114 
00115         // actions
00116         add_data_server_ = new AddDataServer(node_handle_, "add_data_server", boost::bind(&FaceCaptureNode::addDataServerCallback, this, _1), false);
00117         add_data_server_->start();
00118         update_data_server_ = new UpdateDataServer(node_handle_, "update_data_server", boost::bind(&FaceCaptureNode::updateDataServerCallback, this, _1), false);
00119         update_data_server_->start();
00120         delete_data_server_ = new DeleteDataServer(node_handle_, "delete_data_server", boost::bind(&FaceCaptureNode::deleteDataServerCallback, this, _1), false);
00121         delete_data_server_->start();
00122 
00123         // input synchronization
00124 //      sync_input_2_ = new message_filters::Synchronizer<message_filters::sync_policies::ApproximateTime<cob_perception_msgs::ColorDepthImageArray, sensor_msgs::Image> >(30);
00125 //      sync_input_2_->connectInput(face_detection_subscriber_, color_image_sub_);
00126 
00127         std::cout << "FaceCaptureNode initialized. " << face_images_.size() << " color images and " << face_depthmaps_.size() << " depth images for training loaded.\n" << std::endl;
00128 }
00129 
00130 FaceCaptureNode::~FaceCaptureNode()
00131 {
00132         if (it_ != 0) delete it_;
00133         if (sync_input_2_ != 0) delete sync_input_2_;
00134         if (add_data_server_ != 0) delete add_data_server_;
00135         if (update_data_server_ != 0) delete update_data_server_;
00136         if (delete_data_server_ != 0) delete delete_data_server_;
00137 }
00138 
00139 void FaceCaptureNode::addDataServerCallback(const cob_people_detection::addDataGoalConstPtr& goal)
00140 {
00141         // secure this function with a mutex
00142         boost::lock_guard<boost::mutex> lock(active_action_mutex_);
00143 
00144         // open the gateway for sensor messages
00145         // rosrun dynamic_reconfigure dynparam set /cob_people_detection/sensor_message_gateway/sensor_message_gateway target_publishing_rate 2.0
00146 
00147         // set the label for the images than will be captured
00148         current_label_ = goal->label;
00149 
00150         // subscribe to face image topics
00151         //message_filters::Connection input_callback_connection = sync_input_2_->registerCallback(boost::bind(&FaceCaptureNode::inputCallback, this, _1, _2));
00152         face_detection_subscriber_.subscribe(node_handle_, "face_detections", 1);
00153         face_detection_subscriber_.registerCallback(boost::bind(&FaceCaptureNode::inputCallback, this, _1));
00154 
00155 
00156         if (goal->capture_mode == MANUAL)
00157         {
00158                 // configure manual recording
00159                 number_captured_images_ = 0;
00160                 finish_image_capture_ = false;          // finishes the image recording
00161                 capture_image_ = false;                         // trigger for image capture -> set true by service message
00162 
00163                 // activate service server for image capture trigger messages and finish
00164                 service_server_capture_image_ = node_handle_.advertiseService("capture_image", &FaceCaptureNode::captureImageCallback, this);
00165                 service_server_finish_recording_ = node_handle_.advertiseService("finish_recording", &FaceCaptureNode::finishRecordingCallback, this);
00166 
00167                 // wait until finish manual capture service message arrives
00168                 while (finish_image_capture_ == false)
00169                         ros::spinOnce();
00170 
00171                 // unadvertise the manual image capture trigger service and finish recording service
00172                 service_server_capture_image_.shutdown();
00173                 service_server_finish_recording_.shutdown();
00174 
00175                 // save new database status
00176                 face_recognizer_trainer_.saveTrainingData(face_images_,face_depthmaps_);
00177 
00178                 // close action
00179                 cob_people_detection::addDataResult result;
00180                 add_data_server_->setSucceeded(result, "Manual capture finished successfully.");
00181         }
00182         else if (goal->capture_mode == CONTINUOUS)
00183         {
00184                 // configure continuous recording
00185                 number_captured_images_ = 0;
00186                 while (number_captured_images_ < goal->continuous_mode_images_to_capture)
00187                 {
00188                         capture_image_ = true;          // trigger for image recording
00189                         ros::Duration(goal->continuous_mode_delay).sleep();             // wait for a given time until next image can be captured
00190                 }
00191 
00192                 // save new database status
00193                 face_recognizer_trainer_.saveTrainingData(face_images_,face_depthmaps_);
00194 
00195                 // close action
00196                 cob_people_detection::addDataResult result;
00197                 std::stringstream ss;
00198                 ss << "Continuous capture of " << goal->continuous_mode_images_to_capture << " images finished successfully.";
00199                 add_data_server_->setSucceeded(result, ss.str());
00200         }
00201         else
00202         {
00203                 ROS_ERROR("FaceCaptureNode::addDataServerCallback: Unknown capture mode: %d.", goal->capture_mode);
00204                 cob_people_detection::addDataResult result;
00205                 std::stringstream ss;
00206                 ss << "Unknown capture mode: " << goal->capture_mode;
00207                 add_data_server_->setAborted(result, ss.str());
00208         }
00209 
00210         // unsubscribe face image topics
00211         //input_callback_connection.disconnect();
00212         face_detection_subscriber_.unsubscribe();
00213 }
00214 
00216 void FaceCaptureNode::inputCallback(const cob_perception_msgs::ColorDepthImageArray::ConstPtr& face_detection_msg)//, const sensor_msgs::Image::ConstPtr& color_image_msg)
00217 {
00218         //ROS_INFO("inputCallback");
00219 
00220         // only capture images if a recording is triggered
00221         if (capture_image_ == true)
00222         {
00223                 // check number of detected faces -> accept only exactly one
00224                 int numberFaces = 0;
00225                 int headIndex = 0;
00226                 for (unsigned int i=0; i<face_detection_msg->head_detections.size(); i++)
00227                 {
00228                         numberFaces += face_detection_msg->head_detections[i].face_detections.size();
00229                         if (face_detection_msg->head_detections[i].face_detections.size() == 1)
00230                                 headIndex = i;
00231                 }
00232                 if (numberFaces != 1)
00233                 {
00234                         ROS_WARN("Either no head or more than one head detected. Discarding image.");
00235                         return;
00236                 }
00237 
00238                 // convert color image to cv::Mat
00239                 cv_bridge::CvImageConstPtr color_image_ptr;
00240                 cv::Mat color_image,depth_image;
00241                 //convertColorImageMessageToMat(color_image_msg, color_image_ptr, color_image);
00242                 sensor_msgs::ImageConstPtr msgPtr = boost::shared_ptr<sensor_msgs::Image const>(&(face_detection_msg->head_detections[headIndex].color_image), voidDeleter);
00243                 convertColorImageMessageToMat(msgPtr, color_image_ptr, color_image);
00244 
00245                 msgPtr = boost::shared_ptr<sensor_msgs::Image const>(&(face_detection_msg->head_detections[headIndex].depth_image), voidDeleter);
00246                 convertDepthImageMessageToMat(msgPtr, color_image_ptr, depth_image);
00247 
00248                 // store image and label
00249 // merge todo: check whether new coordinate convention (face_bounding box uses coordinates of head and face) hold in this code as well
00250 //              const cob_perception_msgs::Rect& face_rect = face_detection_msg->head_detections[0].face_detections[0];
00251 //              const cob_perception_msgs::Rect& head_rect = face_detection_msg->head_detections[0].head_detection;
00252 //              cv::Rect face_bounding_box(face_rect.x, face_rect.y, face_rect.width, face_rect.height);
00253                 const cob_perception_msgs::Rect& face_rect = face_detection_msg->head_detections[headIndex].face_detections[0];
00254                 const cob_perception_msgs::Rect& head_rect = face_detection_msg->head_detections[headIndex].head_detection;
00255                 cv::Rect face_bounding_box(face_rect.x, face_rect.y, face_rect.width, face_rect.height);
00256                 cv::Rect head_bounding_box(head_rect.x, head_rect.y, head_rect.width, head_rect.height);
00257                 cv::Mat img_color = color_image;
00258                 cv::Mat img_depth = depth_image;
00259 
00260                 // normalize face
00261                 if (face_recognizer_trainer_.addFace(img_color, img_depth, face_bounding_box, head_bounding_box, current_label_, face_images_, face_depthmaps_)==ipa_Utils::RET_FAILED)
00262                 {
00263                         ROS_WARN("face_capture: Adding face failed.");
00264                         capture_image_ = false;                 // reset trigger for recording
00265                         return;
00266                 }
00267 
00268                 // only after successful recording
00269                 number_captured_images_++;              // increase number of captured images
00270                 capture_image_ = false;                 // reset trigger for recording
00271 
00272                 ROS_INFO("Face number %d captured.", number_captured_images_);
00273         }
00274 }
00275 
00277 unsigned long FaceCaptureNode::convertColorImageMessageToMat(const sensor_msgs::Image::ConstPtr& image_msg, cv_bridge::CvImageConstPtr& image_ptr, cv::Mat& image)
00278 {
00279         try
00280         {
00281                 image_ptr = cv_bridge::toCvShare(image_msg, sensor_msgs::image_encodings::BGR8);
00282         }
00283         catch (cv_bridge::Exception& e)
00284         {
00285                 ROS_ERROR("PeopleDetection: cv_bridge exception: %s", e.what());
00286                 return ipa_Utils::RET_FAILED;
00287         }
00288         image = image_ptr->image;
00289 
00290         return ipa_Utils::RET_OK;
00291 }
00292 
00294 unsigned long FaceCaptureNode::convertDepthImageMessageToMat(const sensor_msgs::Image::ConstPtr& image_msg, cv_bridge::CvImageConstPtr& image_ptr, cv::Mat& image)
00295 {
00296         try
00297         {
00298                 image_ptr = cv_bridge::toCvShare(image_msg, sensor_msgs::image_encodings::TYPE_32FC3);
00299         }
00300         catch (cv_bridge::Exception& e)
00301         {
00302                 ROS_ERROR("PeopleDetection: cv_bridge exception: %s", e.what());
00303                 return ipa_Utils::RET_FAILED;
00304         }
00305         image = image_ptr->image;
00306 
00307         return ipa_Utils::RET_OK;
00308 }
00309 
00310 bool FaceCaptureNode::captureImageCallback(cob_people_detection::captureImage::Request &req, cob_people_detection::captureImage::Response &res)
00311 {
00312         capture_image_ = true;
00313         // block until captured
00314         while (capture_image_ == true)
00315                 ros::spinOnce();
00316         res.number_captured_images = number_captured_images_;
00317         return true;
00318 }
00319 
00320 bool FaceCaptureNode::finishRecordingCallback(cob_people_detection::finishRecording::Request &req, cob_people_detection::finishRecording::Response &res)
00321 {
00322         finish_image_capture_ = true;
00323         return true;
00324 }
00325 
00326 void FaceCaptureNode::updateDataServerCallback(const cob_people_detection::updateDataGoalConstPtr& goal)
00327 {
00328         // secure this function with a mutex
00329         boost::lock_guard<boost::mutex> lock(active_action_mutex_);
00330 
00331         cob_people_detection::updateDataResult result;
00332 
00333         // determine the update mode
00334         if (goal->update_mode == BY_INDEX)
00335         {
00336                 // update only one entry identified by its index
00337                 face_recognizer_trainer_.updateFaceLabel(goal->update_index, goal->new_label);
00338         }
00339         else if (goal->update_mode == BY_LABEL)
00340         {
00341                 // update all entries identified by their old label
00342                 face_recognizer_trainer_.updateFaceLabels(goal->old_label, goal->new_label);
00343         }
00344         else
00345         {
00346                 ROS_ERROR("FaceCaptureNode::updateDataServerCallback: Unknown update_mode.");
00347                 update_data_server_->setAborted(result, "Unknown update_mode. No entries have been updated.");
00348                 return;
00349         }
00350 
00351         // save new database status
00352         face_recognizer_trainer_.saveTrainingData(face_images_,face_depthmaps_);
00353 
00354         // close action
00355         update_data_server_->setSucceeded(result, "Database update finished successfully.");
00356 }
00357 
00358 void FaceCaptureNode::deleteDataServerCallback(const cob_people_detection::deleteDataGoalConstPtr& goal)
00359 {
00360         // secure this function with a mutex
00361         boost::lock_guard<boost::mutex> lock(active_action_mutex_);
00362 
00363         cob_people_detection::deleteDataResult result;
00364 
00365         // determine the delete mode
00366         if (goal->delete_mode == BY_INDEX)
00367         {
00368                 // delete only one entry identified by its index
00369                 face_recognizer_trainer_.deleteFace(goal->delete_index, face_images_,face_depthmaps_);
00370         }
00371         else if (goal->delete_mode == BY_LABEL)
00372         {
00373                 // delete all entries identified by their label
00374                 face_recognizer_trainer_.deleteFaces(goal->label, face_images_,face_depthmaps_);
00375         }
00376         else
00377         {
00378                 ROS_ERROR("FaceCaptureNode::deleteDataServerCallback: Unknown delete_mode.");
00379                 delete_data_server_->setAborted(result, "Unknown delete_mode. No entries have been deleted from the database.");
00380                 return;
00381         }
00382 
00383         // save new database status
00384         face_recognizer_trainer_.saveTrainingData(face_images_,face_depthmaps_);
00385 
00386         // close action
00387         delete_data_server_->setSucceeded(result, "Deleting entries from the database finished successfully.");
00388 }
00389 
00390 
00391 //#######################
00392 //#### main programm ####
00393 int main(int argc, char** argv)
00394 {
00395         // Initialize ROS, specify name of node
00396         ros::init(argc, argv, "face_capture");
00397 
00398         // Create a handle for this node, initialize node
00399         ros::NodeHandle nh;
00400 
00401         // Create FaceRecognizerNode class instance
00402         FaceCaptureNode face_capture_node(nh);
00403 
00404         // Create action nodes
00405         //DetectObjectsAction detect_action_node(object_detection_node, nh);
00406         //AcquireObjectImageAction acquire_image_node(object_detection_node, nh);
00407         //TrainObjectAction train_object_node(object_detection_node, nh);
00408 
00409         ros::spin();
00410 
00411         return 0;
00412 }
00413 


cob_people_detection
Author(s): Richard Bormann , Thomas Zwölfer
autogenerated on Fri Aug 28 2015 10:24:12