detection_tracker_node.cpp
Go to the documentation of this file.
00001 
00060 //##################
00061 //#### includes ####
00062 
00063 #include <cob_people_detection/detection_tracker_node.h>
00064 #include <munkres/munkres.h>
00065 
00066 // standard includes
00067 //--
00068 
00069 // ROS includes
00070 #include <ros/ros.h>
00071 #include <ros/package.h>
00072 
00073 // ROS message includes
00074 #include <sensor_msgs/Image.h>
00075 #include <cob_perception_msgs/DetectionArray.h>
00076 
00077 // services
00078 //#include <cob_people_detection/DetectPeople.h>
00079 
00080 // topics
00081 #include <message_filters/subscriber.h>
00082 #include <message_filters/synchronizer.h>
00083 #include <message_filters/sync_policies/approximate_time.h>
00084 #include <image_transport/image_transport.h>
00085 #include <image_transport/subscriber_filter.h>
00086 
00087 // opencv
00088 #include <opencv/cv.h>
00089 #include <opencv/highgui.h>
00090 #include <cv_bridge/cv_bridge.h>
00091 #include <sensor_msgs/image_encodings.h>
00092 
00093 // boost
00094 #include <boost/bind.hpp>
00095 #include <boost/thread/mutex.hpp>
00096 
00097 // external includes
00098 #include "cob_vision_utils/GlobalDefines.h"
00099 
00100 // Timer
00101 #include "cob_people_detection/timer.h"
00102 
00103 #include <sstream>
00104 #include <string>
00105 #include <vector>
00106 
00107 using namespace ipa_PeopleDetector;
00108 
00109 DetectionTrackerNode::DetectionTrackerNode(ros::NodeHandle nh) :
00110         node_handle_(nh)
00111 {
00112         it_ = 0;
00113         sync_input_2_ = 0;
00114 
00115         // parameters
00116         std::cout << "\n---------------------------\nPeople Detection Parameters:\n---------------------------\n";
00117         node_handle_.param("debug", debug_, false);
00118         std::cout << "debug = " << debug_ << "\n";
00119         node_handle_.param("rosbag_mode", rosbag_mode_, false);
00120         std::cout << "use rosbag mode:  " << rosbag_mode_ << "\n";
00121         node_handle_.param("use_people_segmentation", use_people_segmentation_, true);
00122         std::cout << "use_people_segmentation = " << use_people_segmentation_ << "\n";
00123         node_handle_.param("face_redetection_time", face_redetection_time_, 2.0);
00124         std::cout << "face_redetection_time = " << face_redetection_time_ << "\n";
00125         double publish_currently_not_visible_detections_timespan = face_redetection_time_;
00126         node_handle_.param("publish_currently_not_visible_detections_timespan", publish_currently_not_visible_detections_timespan, face_redetection_time_);
00127         std::cout << "publish_currently_not_visible_detections_timespan = " << publish_currently_not_visible_detections_timespan << "\n";
00128         publish_currently_not_visible_detections_timespan_ = ros::Duration(publish_currently_not_visible_detections_timespan);
00129         node_handle_.param("min_segmented_people_ratio_face", min_segmented_people_ratio_face_, 0.7);
00130         std::cout << "min_segmented_people_ratio_face = " << min_segmented_people_ratio_face_ << "\n";
00131         node_handle_.param("min_segmented_people_ratio_head", min_segmented_people_ratio_head_, 0.2);
00132         std::cout << "min_segmented_people_ratio_head = " << min_segmented_people_ratio_head_ << "\n";
00133         node_handle_.param("tracking_range_m", tracking_range_m_, 0.3);
00134         std::cout << "tracking_range_m = " << tracking_range_m_ << "\n";
00135         node_handle_.param("face_identification_score_decay_rate", face_identification_score_decay_rate_, 0.9);
00136         std::cout << "face_identification_score_decay_rate = " << face_identification_score_decay_rate_ << "\n";
00137         node_handle_.param("min_face_identification_score_to_publish", min_face_identification_score_to_publish_, 0.9);
00138         std::cout << "min_face_identification_score_to_publish = " << min_face_identification_score_to_publish_ << "\n";
00139         node_handle_.param("fall_back_to_unknown_identification", fall_back_to_unknown_identification_, true);
00140         std::cout << "fall_back_to_unknown_identification = " << fall_back_to_unknown_identification_ << "\n";
00141         node_handle_.param("display_timing", display_timing_, false);
00142         std::cout << "display_timing = " << display_timing_ << "\n";
00143 
00144         // subscribers
00145         it_ = new image_transport::ImageTransport(node_handle_);
00146         people_segmentation_image_sub_.subscribe(*it_, "people_segmentation_image", 1);
00147         face_position_subscriber_.subscribe(node_handle_, "face_position_array_in", 1);
00148 
00149         // input synchronization
00150         sensor_msgs::Image::ConstPtr nullPtr;
00151         if (use_people_segmentation_ == true)
00152         {
00153                 sync_input_2_ = new message_filters::Synchronizer<message_filters::sync_policies::ApproximateTime<cob_perception_msgs::DetectionArray, sensor_msgs::Image> >(2);
00154                 sync_input_2_->connectInput(face_position_subscriber_, people_segmentation_image_sub_);
00155                 sync_input_2_->registerCallback(boost::bind(&DetectionTrackerNode::inputCallback, this, _1, _2));
00156         }
00157         else
00158         {
00159                 face_position_subscriber_.registerCallback(boost::bind(&DetectionTrackerNode::inputCallback, this, _1, nullPtr));
00160         }
00161 
00162         // publishers
00163         face_position_publisher_ = node_handle_.advertise<cob_perception_msgs::DetectionArray>("face_position_array", 1);
00164 
00165         std::cout << "DetectionTrackerNode initialized." << std::endl;
00166 }
00167 
00168 DetectionTrackerNode::~DetectionTrackerNode()
00169 {
00170         if (it_ != 0)
00171                 delete it_;
00172         if (sync_input_2_ != 0)
00173                 delete sync_input_2_;
00174 }
00175 
00177 unsigned long DetectionTrackerNode::convertColorImageMessageToMat(const sensor_msgs::Image::ConstPtr& image_msg, cv_bridge::CvImageConstPtr& image_ptr, cv::Mat& image)
00178 {
00179         try
00180         {
00181                 image_ptr = cv_bridge::toCvShare(image_msg, sensor_msgs::image_encodings::BGR8);
00182         } catch (cv_bridge::Exception& e)
00183         {
00184                 ROS_ERROR("PeopleDetection: cv_bridge exception: %s", e.what());
00185                 return ipa_Utils::RET_FAILED;
00186         }
00187         image = image_ptr->image;
00188 
00189         return ipa_Utils::RET_OK;
00190 }
00191 
00198 unsigned long DetectionTrackerNode::copyDetection(const cob_perception_msgs::Detection& src, cob_perception_msgs::Detection& dest, bool update,
00199                 unsigned int updateIndex)
00200 {
00201         // 2D image coordinates
00202         dest.mask.roi.x = src.mask.roi.x;
00203         dest.mask.roi.y = src.mask.roi.y;
00204         dest.mask.roi.width = src.mask.roi.width;
00205         dest.mask.roi.height = src.mask.roi.height;
00206 
00207         // 3D world coordinates
00208         //      const geometry_msgs::Point* pointIn = &(src.pose.pose.position);
00209         //      geometry_msgs::Point* pointOut = &(dest.pose.pose.position);
00210         //      pointOut->x = pointIn->x; pointOut->y = pointIn->y; pointOut->z = pointIn->z;
00211         dest.pose.pose = src.pose.pose;
00212 
00213         // person ID
00214         if (update == true)
00215         {
00216                 // update label history
00217                 // if (src.label!="No face")
00218                 // {
00219                 if (face_identification_votes_[updateIndex].find(src.label) == face_identification_votes_[updateIndex].end())
00220                         face_identification_votes_[updateIndex][src.label] = 1.0;
00221                 else
00222                         face_identification_votes_[updateIndex][src.label] += 1.0;
00223                 // }
00224 
00225                 // apply voting decay with time and find most voted label
00226                 double max_score = 0;
00227                 dest.label = src.label;
00228                 for (std::map<std::string, double>::iterator face_identification_votes_it = face_identification_votes_[updateIndex].begin(); face_identification_votes_it
00229                                 != face_identification_votes_[updateIndex].end(); face_identification_votes_it++)
00230                 {
00231                         // todo: make the decay time-dependend - otherwise faster computing = faster decay. THIS IS ACTUALLY WRONG as true detections occur with same rate as decay -> so computing power only affects response time to a changed situation
00232                         face_identification_votes_it->second *= face_identification_score_decay_rate_;
00233                         std::string label = face_identification_votes_it->first;
00234                         if (face_identification_votes_it->second > max_score && (fall_back_to_unknown_identification_ == true || (label != "Unknown" && fall_back_to_unknown_identification_
00235                                         == false)) && label != "UnknownHead" /*&& label!="No face"*/)
00236                         {
00237                                 max_score = face_identification_votes_it->second;
00238                                 dest.label = label;
00239                         }
00240                 }
00241 
00242                 // if the score for the assigned label is higher than the score for UnknownHead increase the score for UnknownHead to the label's score (allows smooth transition if only the head detection is available after recognition)
00243                 if (face_identification_votes_[updateIndex][dest.label] > face_identification_votes_[updateIndex]["UnknownHead"])
00244                         face_identification_votes_[updateIndex]["UnknownHead"] = face_identification_votes_[updateIndex][dest.label];
00245                 if (fall_back_to_unknown_identification_ == false)
00246                 {
00247                         if (face_identification_votes_[updateIndex]["Unknown"] > face_identification_votes_[updateIndex]["UnknownHead"])
00248                                 face_identification_votes_[updateIndex]["UnknownHead"] = face_identification_votes_[updateIndex]["Unknown"];
00249                 }
00250         }
00251         else
00252                 dest.label = src.label;
00253 
00254         if (dest.label == "UnknownHead")
00255                 dest.label = "Unknown";
00256 
00257         // time stamp, detector (color or range)
00258         // if (update==true)
00259         // {
00260         // if (src.detector=="color") dest.detector = "color";
00261         // }
00262         // else dest.detector = src.detector;
00263         dest.detector = src.detector;
00264 
00265         dest.header.stamp = src.header.stamp; //ros::Time::now();
00266 
00267         return ipa_Utils::RET_OK;
00268 }
00269 
00270 inline double abs(double x)
00271 {
00272         return ((x < 0) ? -x : x);
00273 }
00274 
00278 double DetectionTrackerNode::computeFacePositionDistanceTrackingRange(const cob_perception_msgs::Detection& previous_detection,
00279                 const cob_perception_msgs::Detection& current_detection)
00280 {
00281         const geometry_msgs::Point* point_1 = &(previous_detection.pose.pose.position);
00282         const geometry_msgs::Point* point_2 = &(current_detection.pose.pose.position);
00283 
00284         double dx = abs(point_1->x - point_2->x);
00285         double dy = abs(point_1->y - point_2->y);
00286         double dz = abs(point_1->z - point_2->z);
00287 
00288         // return a huge distance if the current face position is too far away from the recent
00289         if (dx > tracking_range_m_ || dy > tracking_range_m_ || dz > tracking_range_m_)
00290         {
00291                 // new face position is too distant to recent position
00292                 return DBL_MAX;
00293         }
00294 
00295         // return Euclidian distance if both faces are sufficiently close
00296         double dist = dx * dx + dy * dy + dz * dz;
00297         return dist;
00298 }
00299 
00300 double DetectionTrackerNode::computeFacePositionDistance(const cob_perception_msgs::Detection& previous_detection,
00301                 const cob_perception_msgs::Detection& current_detection)
00302 {
00303         const geometry_msgs::Point* point_1 = &(previous_detection.pose.pose.position);
00304         const geometry_msgs::Point* point_2 = &(current_detection.pose.pose.position);
00305 
00306         double dx = point_1->x - point_2->x;
00307         double dy = point_1->y - point_2->y;
00308         double dz = point_1->z - point_2->z;
00309 
00310         return sqrt(dx * dx + dy * dy + dz * dz);
00311 }
00312 
00315 unsigned long DetectionTrackerNode::removeMultipleInstancesOfLabel()
00316 {
00317         // check this for each recognized face
00318         for (int i = 0; i < (int)face_position_accumulator_.size(); i++)
00319         {
00320                 // label of this detection
00321                 std::string label = face_position_accumulator_[i].label;
00322 
00323                 // check whether this label has multiple occurrences if it is a real name
00324                 if (label != "Unknown" && label != "No face")
00325                 {
00326                         for (int j = 0; j < (int)face_position_accumulator_.size(); j++)
00327                         {
00328                                 if (j == i)
00329                                         continue; // do not check yourself
00330 
00331                                 if (face_position_accumulator_[j].label == label)
00332                                 {
00333                                         if (debug_)
00334                                                 std::cout << "face_identification_votes_[i][" << label << "] = " << face_identification_votes_[i][label] << " face_identification_votes_[j][" << label
00335                                                                 << "] = " << face_identification_votes_[j][label] << "\n";
00336 
00337                                         // correct this label to Unknown when some other instance has a higher score on this label
00338                                         if (face_identification_votes_[i][label] < face_identification_votes_[j][label])
00339                                         {
00340                                                 face_position_accumulator_[i].label = "Unknown";
00341                                                 // copy score to unknown if it is higher (this enables the display if either the unknown score or label's recognition score were high enough)
00342                                                 if (face_identification_votes_[i][label] > face_identification_votes_[i]["Unknown"])
00343                                                         face_identification_votes_[i]["Unknown"] = face_identification_votes_[i][label];
00344                                         }
00345                                 }
00346                         }
00347                 }
00348         }
00349 
00350         return ipa_Utils::RET_OK;
00351 }
00352 
00353 unsigned long DetectionTrackerNode::prepareFacePositionMessage(cob_perception_msgs::DetectionArray& face_position_msg_out, ros::Time image_recording_time)
00354 {
00355         // publish face positions
00356         std::vector < cob_perception_msgs::Detection > faces_to_publish;
00357         for (int i = 0; i < (int)face_position_accumulator_.size(); i++)
00358         {
00359                 if (debug_)
00360                         std::cout << "'UnknownHead' score: " << face_identification_votes_[i]["UnknownHead"] << " label '" << face_position_accumulator_[i].label << "' score: "
00361                                         << face_identification_votes_[i][face_position_accumulator_[i].label] << " - ";
00362                 if ((face_identification_votes_[i][face_position_accumulator_[i].label] > min_face_identification_score_to_publish_ || face_identification_votes_[i]["UnknownHead"]
00363                                 > min_face_identification_score_to_publish_) && ((image_recording_time - face_position_accumulator_[i].header.stamp)
00364                                 < publish_currently_not_visible_detections_timespan_))
00365                 {
00366                         faces_to_publish.push_back(face_position_accumulator_[i]);
00367                         if (debug_)
00368                                 std::cout << "published\n";
00369                 }
00370                 else if (debug_)
00371                         std::cout << "not published\n";
00372         }
00373         face_position_msg_out.detections = faces_to_publish;
00374         // hack: for WimiCare replace 'Unknown' by '0000'
00375         //        for (int i=0; i<(int)face_position_msg_out.detections.size(); i++)
00376         //        {
00377         //                if (face_position_msg_out.detections[i].label=="Unknown")
00378         //                        face_position_msg_out.detections[i].label = "0000";
00379         //        }
00380         face_position_msg_out.header.stamp = ros::Time::now();
00381 
00382         return ipa_Utils::RET_OK;
00383 }
00384 
00386 void DetectionTrackerNode::inputCallback(const cob_perception_msgs::DetectionArray::ConstPtr& face_position_msg_in,
00387                 const sensor_msgs::Image::ConstPtr& people_segmentation_image_msg)
00388 {
00389         // todo? make update rates time dependent!
00390         // NOT USEFUL, as true detections occur with same rate as decay -> so computing power only affects response time to a changed situation
00391 
00392         //      Timer tim;
00393         //      tim.start();
00394 
00395         // convert segmentation image to cv::Mat
00396         cv_bridge::CvImageConstPtr people_segmentation_image_ptr;
00397         cv::Mat people_segmentation_image;
00398         if (use_people_segmentation_ == true)
00399                 convertColorImageMessageToMat(people_segmentation_image_msg, people_segmentation_image_ptr, people_segmentation_image);
00400 
00401         if (debug_)
00402                 std::cout << "incoming detections: " << face_position_msg_in->detections.size() << "\n";
00403 
00404         // delete old face positions in list, i.e. those that were not updated for a long time
00405         ros::Duration timeSpan(face_redetection_time_);
00406         // do not delete  when bag file is played back
00407         if (!rosbag_mode_)
00408         {
00409                 for (int i = (int)face_position_accumulator_.size() - 1; i >= 0; i--)
00410                 {
00411                         if ((ros::Time::now() - face_position_accumulator_[i].header.stamp) > timeSpan)
00412                         {
00413                                 face_position_accumulator_.erase(face_position_accumulator_.begin() + i);
00414                                 face_identification_votes_.erase(face_identification_votes_.begin() + i);
00415                         }
00416                 }
00417                 if (debug_)
00418                         std::cout << "Old face positions deleted.\n";
00419         }
00420 
00421         // verify face detections with people segmentation if enabled -> only accept detected faces if a person is segmented at that position
00422         std::vector<int> face_detection_indices; // index set for face_position_msg_in: contains those indices of detected faces which are supported by a person segmentation at the same location
00423         if (use_people_segmentation_ == true)
00424         {
00425                 for (int i = 0; i < (int)face_position_msg_in->detections.size(); i++)
00426                 {
00427                         const cob_perception_msgs::Detection& det_in = face_position_msg_in->detections[i];
00428                         cv::Rect face;
00429                         face.x = det_in.mask.roi.x;
00430                         face.y = det_in.mask.roi.y;
00431                         face.width = det_in.mask.roi.width;
00432                         face.height = det_in.mask.roi.height;
00433                         //std::cout << "face: " << face.x << " " << face.y << " " << face.width << " " << face.height << "\n";
00434 
00435                         int numberBlackPixels = 0;
00436                         for (int v = face.y; v < face.y + face.height; v++)
00437                         {
00438                                 uchar* data = people_segmentation_image.ptr(v);
00439                                 for (int u = face.x; u < face.x + face.width; u++)
00440                                 {
00441                                         int index = 3 * u;
00442                                         if (data[index] == 0 && data[index + 1] == 0 && data[index + 2] == 0)
00443                                                 numberBlackPixels++;
00444                                 }
00445                         }
00446                         int faceArea = face.height * face.width;
00447                         double segmentedPeopleRatio = (double)(faceArea - numberBlackPixels) / (double)faceArea;
00448 
00449                         // if (debug_) std::cout << "ratio: " << segmentedPeopleRatio << "\n";
00450                         if ((det_in.detector == "face" && segmentedPeopleRatio < min_segmented_people_ratio_face_) || (det_in.detector == "head" && segmentedPeopleRatio
00451                                         < min_segmented_people_ratio_head_))
00452                         {
00453                                 // False detection
00454                                 if (debug_)
00455                                         std::cout << "False detection\n";
00456                         }
00457                         else
00458                         {
00459                                 // Push index of this detection into the list
00460                                 face_detection_indices.push_back(i);
00461                         }
00462                 }
00463                 if (debug_)
00464                         std::cout << "Verification with people segmentation done.\n";
00465         }
00466         else
00467         {
00468                 for (unsigned int i = 0; i < face_position_msg_in->detections.size(); i++)
00469                         face_detection_indices.push_back(i);
00470         }
00471 
00472         // match current detections with previous detections
00473         std::vector<bool> current_detection_has_matching(face_detection_indices.size(), false); // index set for face_detection_indices: contains the indices of face_detection_indices and whether these faces could be matched to previously found faces
00474         // Option 1: greedy procedure
00475         if (false)
00476         {
00477                 // build distance matrix
00478                 std::map<int, std::map<int, double> > distance_matrix; // 1. index = face_position_accumulator_ index of previous detections, 2. index = index of current detections, content = spatial distance between the indexed faces
00479                 std::map<int, std::map<int, double> >::iterator distance_matrix_it;
00480                 for (unsigned int previous_det = 0; previous_det < face_position_accumulator_.size(); previous_det++)
00481                 {
00482                         std::map<int, double> distance_row;
00483                         for (unsigned int i = 0; i < face_detection_indices.size(); i++)
00484                                 distance_row[face_detection_indices[i]] = computeFacePositionDistanceTrackingRange(face_position_accumulator_[previous_det],
00485                                                 face_position_msg_in->detections[face_detection_indices[i]]);
00486                         distance_matrix[previous_det] = distance_row;
00487                 }
00488                 if (debug_)
00489                         std::cout << "Distance matrix.\n";
00490 
00491                 // find matching faces between previous and current detections
00492                 unsigned int number_matchings = (face_position_accumulator_.size() < face_detection_indices.size()) ? face_position_accumulator_.size() : face_detection_indices.size();
00493                 for (unsigned int m = 0; m < number_matchings; m++)
00494                 {
00495                         // find minimum matching distance between any two elements of the distance_matrix
00496                         double min_dist = DBL_MAX;
00497                         int previous_min_index, current_min_index;
00498                         for (distance_matrix_it = distance_matrix.begin(); distance_matrix_it != distance_matrix.end(); distance_matrix_it++)
00499                         {
00500                                 for (std::map<int, double>::iterator distance_row_it = distance_matrix_it->second.begin(); distance_row_it != distance_matrix_it->second.end(); distance_row_it++)
00501                                 {
00502                                         if (distance_row_it->second < min_dist)
00503                                         {
00504                                                 min_dist = distance_row_it->second;
00505                                                 previous_min_index = distance_matrix_it->first;
00506                                                 current_min_index = distance_row_it->first;
00507                                         }
00508                                 }
00509                         }
00510 
00511                         // todo: this is a greedy strategy that is likely to fail -> replace by global matching
00512                         // todo: consider size relation between color and depth image face frames!
00513 
00514                         // if there is no matching pair of detections interrupt the search for matchings at this point
00515                         if (min_dist == DBL_MAX)
00516                                 break;
00517 
00518                         // instantiate the matching
00519                         copyDetection(face_position_msg_in->detections[current_min_index], face_position_accumulator_[previous_min_index], true, previous_min_index);
00520                         // mark the respective entry in face_detection_indices as labeled
00521                         for (unsigned int i = 0; i < face_detection_indices.size(); i++)
00522                                 if (face_detection_indices[i] == current_min_index)
00523                                         current_detection_has_matching[i] = true;
00524 
00525                         // delete the row and column of the found matching so that both detections cannot be involved in any further matching again
00526                         distance_matrix.erase(previous_min_index);
00527                         for (distance_matrix_it = distance_matrix.begin(); distance_matrix_it != distance_matrix.end(); distance_matrix_it++)
00528                                 distance_matrix_it->second.erase(current_min_index);
00529                 }
00530         }
00531         // Option 2: global optimum with Hungarian method
00532         else
00533         {
00534                 // create the costs matrix (which consist of Eulidean distance in cm and a punishment for dissimilar labels)
00535                 std::vector < std::vector<int> > costs_matrix(face_position_accumulator_.size(), std::vector<int>(face_detection_indices.size(), 0));
00536                 if (debug_)
00537                         std::cout << "Costs matrix.\n";
00538                 for (unsigned int previous_det = 0; previous_det < face_position_accumulator_.size(); previous_det++)
00539                 {
00540                         for (unsigned int i = 0; i < face_detection_indices.size(); i++)
00541                         {
00542                                 costs_matrix[previous_det][i] = 100 * computeFacePositionDistance(face_position_accumulator_[previous_det],
00543                                                 face_position_msg_in->detections[face_detection_indices[i]]) + 100 * tracking_range_m_
00544                                                 * (face_position_msg_in->detections[face_detection_indices[i]].label.compare(face_position_accumulator_[previous_det].label) == 0 ? 0 : 1);
00545                                 if (debug_)
00546                                         std::cout << costs_matrix[previous_det][i] << "\t";
00547                         }
00548                         if (debug_)
00549                                 std::cout << std::endl;
00550                 }
00551 
00552                 if (face_position_accumulator_.size() != 0 && face_detection_indices.size() != 0)
00553                 {
00554                         // solve assignment problem
00555                         munkres assignmentProblem;
00556                         assignmentProblem.set_diag(false);
00557                         assignmentProblem.load_weights(costs_matrix);
00558                         int num_rows = std::min(costs_matrix.size(), costs_matrix[0].size());
00559                         //int num_columns = std::max(costs_matrix.size(), costs_matrix[0].size());
00560                         ordered_pair *optimalAssignment = new ordered_pair[num_rows];
00561                         assignmentProblem.assign(optimalAssignment);
00562                         if (debug_)
00563                                 std::cout << "Assignment problem solved.\n";
00564 
00565                         // read out solutions, update face_position_accumulator
00566                         for (int i = 0; i < num_rows; i++)
00567                         {
00568                                 int current_match_index = 0, previous_match_index = 0;
00569                                 if (face_position_accumulator_.size() < face_detection_indices.size())
00570                                 {
00571                                         // results are reported with original row and column
00572                                         previous_match_index = optimalAssignment[i].row;
00573                                         current_match_index = optimalAssignment[i].col;
00574                                 }
00575                                 else
00576                                 {
00577                                         // rows and columns are switched in results
00578                                         previous_match_index = optimalAssignment[i].col;
00579                                         current_match_index = optimalAssignment[i].row;
00580                                 }
00581 
00582                                 // instantiate the matching
00583                                 copyDetection(face_position_msg_in->detections[current_match_index], face_position_accumulator_[previous_match_index], true, previous_match_index);
00584                                 // mark the respective entry in face_detection_indices as labeled
00585                                 for (unsigned int i = 0; i < face_detection_indices.size(); i++)
00586                                         if (face_detection_indices[i] == current_match_index)
00587                                                 current_detection_has_matching[i] = true;
00588                         }
00589 
00590                         delete optimalAssignment;
00591                 }
00592         }
00593         if (debug_)
00594                 std::cout << "Matches found.\n";
00595 
00596         // create new detections for the unmatched of the current detections if they originate from the color image
00597         for (unsigned int i = 0; i < face_detection_indices.size(); i++)
00598         {
00599                 if (current_detection_has_matching[i] == false)
00600                 {
00601                         const cob_perception_msgs::Detection& det_in = face_position_msg_in->detections[face_detection_indices[i]];
00602                         if (det_in.detector == "face")
00603                         {
00604                                 // save in accumulator
00605                                 if (debug_)
00606                                         std::cout << "\n***** New detection *****\n\n";
00607                                 cob_perception_msgs::Detection det_out;
00608                                 copyDetection(det_in, det_out, false);
00609                                 det_out.pose.header.frame_id = "head_cam3d_link";
00610                                 face_position_accumulator_.push_back(det_out);
00611                                 // remember label history
00612                                 std::map<std::string, double> new_identification_data;
00613                                 //new_identification_data["Unknown"] = 0.0;
00614                                 new_identification_data["UnknownHead"] = 0.0;
00615                                 new_identification_data[det_in.label] = 1.0;
00616                                 face_identification_votes_.push_back(new_identification_data);
00617                         }
00618                 }
00619         }
00620         if (debug_)
00621                 std::cout << "New detections.\n";
00622 
00623         // eliminate multiple instances of a label
00624         removeMultipleInstancesOfLabel();
00625 
00626         // publish face positions
00627         ros::Time image_recording_time = (face_position_msg_in->detections.size() > 0 ? face_position_msg_in->detections[0].header.stamp : ros::Time::now());
00628         cob_perception_msgs::DetectionArray face_position_msg_out;
00629         prepareFacePositionMessage(face_position_msg_out, image_recording_time);
00630         face_position_msg_out.header.stamp = face_position_msg_in->header.stamp;
00631         face_position_publisher_.publish(face_position_msg_out);
00632 
00633         //  // display
00634         //  if (debug_ == true)
00635         //  {
00636         //      // convert image message to cv::Mat
00637         //      cv_bridge::CvImageConstPtr colorImagePtr;
00638         //      cv::Mat colorImage;
00639         //      convertColorImageMessageToMat(color_image_msg, colorImagePtr, colorImage);
00640         //
00641         //      // display color image
00642         //      for(int i=0; i<(int)face_position_msg_out.detections.size(); i++)
00643         //      {
00644         //        cv::Rect face;
00645         //        cob_perception_msgs::Rect& faceRect = face_position_msg_out.detections[i].mask.roi;
00646         //        face.x = faceRect.x; face.width = faceRect.width;
00647         //        face.y = faceRect.y; face.height = faceRect.height;
00648         //
00649         //        if (face_position_msg_out.detections[i].detector == "range")
00650         //              cv::rectangle(colorImage, cv::Point(face.x, face.y), cv::Point(face.x + face.width, face.y + face.height), CV_RGB(0, 0, 255), 2, 8, 0);
00651         //        else
00652         //              cv::rectangle(colorImage, cv::Point(face.x, face.y), cv::Point(face.x + face.width, face.y + face.height), CV_RGB(0, 255, 0), 2, 8, 0);
00653         //
00654         //        if (face_position_msg_out.detections[i].label == "Unknown")
00655         //              // Distance to face class is too high
00656         //              cv::putText(colorImage, "Unknown", cv::Point(face.x,face.y+face.height+25), cv::FONT_HERSHEY_PLAIN, 2, CV_RGB( 255, 0, 0 ), 2);
00657         //        else if (face_position_msg_out.detections[i].label == "No face")
00658         //              // Distance to face space is too high
00659         //              cv::putText(colorImage, "No face", cv::Point(face.x,face.y+face.height+25), cv::FONT_HERSHEY_PLAIN, 2, CV_RGB( 255, 0, 0 ), 2);
00660         //        else
00661         //              // Face classified
00662         //              cv::putText(colorImage, face_position_msg_out.detections[i].label.c_str(), cv::Point(face.x,face.y+face.height+25), cv::FONT_HERSHEY_PLAIN, 2, CV_RGB( 0, 255, 0 ), 2);
00663         //      }
00664         //      // publish image
00665         //      cv_bridge::CvImage cv_ptr;
00666         //      cv_ptr.image = colorImage;
00667         //      cv_ptr.encoding = "bgr8";
00668         //      people_detection_image_pub_.publish(cv_ptr.toImageMsg());
00669         //  }
00670 
00671         if (display_timing_ == true)
00672                 ROS_INFO("%d DetectionTracker: Time stamp of pointcloud message: %f. Delay: %f.", face_position_msg_in->header.seq, face_position_msg_in->header.stamp.toSec(), ros::Time::now().toSec()-face_position_msg_in->header.stamp.toSec());
00673         //      ROS_INFO("Detection Tracker took %f ms.", tim.getElapsedTimeInMilliSec());
00674 }
00675 
00676 //#######################
00677 //#### main programm ####
00678 int main(int argc, char** argv)
00679 {
00680         // Initialize ROS, specify name of node
00681         ros::init(argc, argv, "detection_tracker");
00682 
00683         // Create a handle for this node, initialize node
00684         ros::NodeHandle nh;
00685 
00686         // Create FaceRecognizerNode class instance
00687         DetectionTrackerNode detection_tracker_node(nh);
00688 
00689         // Create action nodes
00690         //DetectObjectsAction detect_action_node(object_detection_node, nh);
00691         //AcquireObjectImageAction acquire_image_node(object_detection_node, nh);
00692         //TrainObjectAction train_object_node(object_detection_node, nh);
00693 
00694         ros::spin();
00695 
00696         return 0;
00697 }


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