face_detector_node.cpp
Go to the documentation of this file.
00001 
00061 #ifdef __LINUX__
00062 #include "cob_people_detection/face_detector_node.h"
00063 #include "cob_vision_utils/GlobalDefines.h"
00064 #include "cob_people_detection/face_detection_message_helper.h"
00065 #else
00066 #endif
00067 
00068 // OpenCV
00069 #include <opencv2/opencv.hpp>
00070 #include <cv_bridge/cv_bridge.h>
00071 #include <sensor_msgs/image_encodings.h>
00072 
00073 // Boost
00074 #include <boost/shared_ptr.hpp>
00075 
00076 // timer
00077 #include <cob_people_detection/timer.h>
00078 
00079 using namespace ipa_PeopleDetector;
00080 
00081 FaceDetectorNode::FaceDetectorNode(ros::NodeHandle nh) :
00082         node_handle_(nh)
00083 {
00084         data_directory_ = ros::package::getPath("cob_people_detection") + "/common/files/";
00085 
00086         // Parameters
00087         double faces_increase_search_scale; // The factor by which the search window is scaled between the subsequent scans
00088         int faces_drop_groups; // Minimum number (minus 1) of neighbor rectangles that makes up an object.
00089         int faces_min_search_scale_x; // Minimum search scale x
00090         int faces_min_search_scale_y; // Minimum search scale y
00091         bool reason_about_3dface_size; // if true, the 3d face size is determined and only faces with reasonable size are accepted
00092         double face_size_max_m; // the maximum feasible face diameter [m] if reason_about_3dface_size is enabled
00093         double face_size_min_m; // the minimum feasible face diameter [m] if reason_about_3dface_size is enabled
00094         double max_face_z_m; // maximum distance [m] of detected faces to the sensor
00095         bool debug; // enables some debug outputs
00096         std::cout << "\n--------------------------\nFace Detector Parameters:\n--------------------------\n";
00097         node_handle_.param("data_directory", data_directory_, data_directory_);
00098         std::cout << "data_directory = " << data_directory_ << "\n";
00099         node_handle_.param("faces_increase_search_scale", faces_increase_search_scale, 1.1);
00100         std::cout << "faces_increase_search_scale = " << faces_increase_search_scale << "\n";
00101         node_handle_.param("faces_drop_groups", faces_drop_groups, 68);
00102         std::cout << "faces_drop_groups = " << faces_drop_groups << "\n";
00103         node_handle_.param("faces_min_search_scale_x", faces_min_search_scale_x, 20);
00104         std::cout << "faces_min_search_scale_x = " << faces_min_search_scale_x << "\n";
00105         node_handle_.param("faces_min_search_scale_y", faces_min_search_scale_y, 20);
00106         std::cout << "faces_min_search_scale_y = " << faces_min_search_scale_y << "\n";
00107         node_handle_.param("reason_about_3dface_size", reason_about_3dface_size, true);
00108         std::cout << "reason_about_3dface_size = " << reason_about_3dface_size << "\n";
00109         node_handle_.param("face_size_max_m", face_size_max_m, 0.35);
00110         std::cout << "face_size_max_m = " << face_size_max_m << "\n";
00111         node_handle_.param("face_size_min_m", face_size_min_m, 0.1);
00112         std::cout << "face_size_min_m = " << face_size_min_m << "\n";
00113         node_handle_.param("max_face_z_m", max_face_z_m, 8.0);
00114         std::cout << "max_face_z_m = " << max_face_z_m << "\n";
00115         node_handle_.param("debug", debug, false);
00116         std::cout << "debug = " << debug << "\n";
00117         node_handle_.param("display_timing", display_timing_, false);
00118         std::cout << "display_timing = " << display_timing_ << "\n";
00119 
00120         // initialize face detector
00121         face_detector_.init(data_directory_, faces_increase_search_scale, faces_drop_groups, faces_min_search_scale_x, faces_min_search_scale_y, reason_about_3dface_size,
00122                         face_size_max_m, face_size_min_m, max_face_z_m, debug);
00123 
00124         // advertise topics
00125         face_position_publisher_ = node_handle_.advertise<cob_perception_msgs::ColorDepthImageArray>("face_positions", 1);
00126         face_position_publisher_cartesian_ = node_handle_.advertise<cob_perception_msgs::DetectionArray>("face_detections_cartesian", 1);
00127 
00128         // subscribe to head detection topic
00129         head_position_subscriber_ = nh.subscribe("head_positions", 1, &FaceDetectorNode::head_positions_callback, this);
00130 
00131         std::cout << "FaceDetectorNode initialized." << std::endl;
00132 }
00133 
00134 FaceDetectorNode::~FaceDetectorNode(void)
00135 {
00136 }
00137 
00138 // Prevent deleting memory twice, when using smart pointer
00139 void voidDeleter(const sensor_msgs::Image* const )
00140 {
00141 }
00142 
00143 void FaceDetectorNode::head_positions_callback(const cob_perception_msgs::ColorDepthImageArray::ConstPtr& head_positions)
00144 {
00145         //      Timer tim;
00146         //      tim.start();
00147 
00148         // receive head positions and detect faces in the head region, finally publish detected faces
00149 
00150         // convert color and depth image patches of head regions
00151         std::vector<cv::Mat> heads_color_images(head_positions->head_detections.size());
00152         std::vector<cv::Mat> heads_depth_images(head_positions->head_detections.size());
00153         std::vector<cv::Rect> head_bounding_boxes(head_positions->head_detections.size());
00154         cv_bridge::CvImageConstPtr cv_cptr;
00155         cv_bridge::CvImagePtr cv_ptr(new cv_bridge::CvImage);
00156         for (unsigned int i = 0; i < head_positions->head_detections.size(); i++)
00157         {
00158                 // color image
00159                 sensor_msgs::ImageConstPtr msgPtr = boost::shared_ptr<sensor_msgs::Image const>(&(head_positions->head_detections[i].color_image), voidDeleter);
00160                 try
00161                 {
00162                         cv_cptr = cv_bridge::toCvShare(msgPtr, sensor_msgs::image_encodings::RGB8);
00163                 } catch (cv_bridge::Exception& e)
00164                 {
00165                         ROS_ERROR("cv_bridge exception: %s", e.what());
00166                         return;
00167                 }
00168                 heads_color_images[i] = cv_cptr->image.clone();
00169 
00170                 // depth image
00171                 msgPtr = boost::shared_ptr<const sensor_msgs::Image>(&(head_positions->head_detections[i].depth_image), voidDeleter);
00172                 try
00173                 {
00174                         cv_cptr = cv_bridge::toCvShare(msgPtr, sensor_msgs::image_encodings::TYPE_32FC3);
00175                 } catch (cv_bridge::Exception& e)
00176                 {
00177                         ROS_ERROR("cv_bridge exception: %s", e.what());
00178                         return;
00179                 }
00180                 heads_depth_images[i] = cv_cptr->image;
00181 
00182                 // head bounding box
00183                 const cob_perception_msgs::Rect& source_rect = head_positions->head_detections[i].head_detection;
00184                 cv::Rect rect(source_rect.x, source_rect.y, source_rect.width, source_rect.height);
00185                 head_bounding_boxes[i] = rect;
00186         }
00187         std::vector < std::vector<cv::Rect> > face_bounding_boxes;
00188         face_detector_.detectColorFaces(heads_color_images, heads_depth_images, face_bounding_boxes);
00189         // face_normalizer_.normalizeFaces(heads_color_images, heads_depth_images, face_coordinates);
00190 
00191         // prepare the face position message for publication
00192         if (face_position_publisher_.getNumSubscribers() > 0)
00193         {
00194                 cob_perception_msgs::ColorDepthImageArray image_array;
00195                 image_array = *head_positions;
00196                 for (unsigned int i = 0; i < face_bounding_boxes.size(); i++)
00197                 {
00198                         for (unsigned int j = 0; j < face_bounding_boxes[i].size(); j++)
00199                         {
00200                                 // face rectangle
00201                                 cob_perception_msgs::Rect rect;
00202                                 rect.x = face_bounding_boxes[i][j].x;
00203                                 rect.y = face_bounding_boxes[i][j].y;
00204                                 rect.width = face_bounding_boxes[i][j].width;
00205                                 rect.height = face_bounding_boxes[i][j].height;
00206                                 image_array.head_detections[i].face_detections.push_back(rect);
00207                         }
00208                         // processed color image
00209                         cv_ptr->encoding = sensor_msgs::image_encodings::RGB8;
00210                         cv_ptr->image = heads_color_images[i];
00211                         cv_ptr->toImageMsg(image_array.head_detections[i].color_image);
00212                         image_array.head_detections[i].color_image.header = head_positions->head_detections[i].color_image.header;
00213                 }
00214                 face_position_publisher_.publish(image_array);
00215         }
00216         
00217         // prepare the cartesian face detection message for publication
00218         if (face_position_publisher_cartesian_.getNumSubscribers() > 0)
00219         {
00220                 FaceDetectionMessageHelper face_detection_message_helper;
00221                 cob_perception_msgs::DetectionArray detection_msg;
00222                 face_detection_message_helper.prepareCartesionDetectionMessage(detection_msg, head_positions->header, heads_depth_images, head_bounding_boxes, face_bounding_boxes, 0);
00223                 face_position_publisher_cartesian_.publish(detection_msg);
00224         }
00225 
00226         if (display_timing_ == true)
00227                 ROS_INFO("%d FaceDetection: Time stamp of pointcloud message: %f. Delay: %f.", head_positions->header.seq, head_positions->header.stamp.toSec(),
00228                                 ros::Time::now().toSec() - head_positions->header.stamp.toSec());
00229         //      ROS_INFO("Face detection took %f ms.", tim.getElapsedTimeInMilliSec());
00230 }
00231 
00232 //#######################
00233 //#### main programm ####
00234 int main(int argc, char** argv)
00235 {
00236         // Initialize ROS, specify name of node
00237         ros::init(argc, argv, "face_detector");
00238 
00239         // Create a handle for this node, initialize node
00240         ros::NodeHandle nh("~");
00241 
00242         // Create FaceDetectorNode class instance
00243         FaceDetectorNode face_detector_node(nh);
00244 
00245         // Create action nodes
00246         //DetectObjectsAction detect_action_node(object_detection_node, nh);
00247         //AcquireObjectImageAction acquire_image_node(object_detection_node, nh);
00248         //TrainObjectAction train_object_node(object_detection_node, nh);
00249 
00250         ros::spin();
00251 
00252         return 0;
00253 }


cob_people_detection
Author(s): Richard Bormann , Thomas Zwölfer
autogenerated on Mon May 6 2019 02:32:06