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
00056
00057 #ifndef _PEOPLE_DETECTION_
00058 #define _PEOPLE_DETECTION_
00059
00060
00061
00062
00063
00064
00065
00066
00067 #include <ros/ros.h>
00068 #include <nodelet/nodelet.h>
00069 #include <ros/package.h>
00070
00071
00072 #include <sensor_msgs/Image.h>
00073 #include <sensor_msgs/PointCloud2.h>
00074 #include <cob_perception_msgs/DetectionArray.h>
00075
00076
00077 #include <cob_people_detection/DetectPeople.h>
00078
00079
00080 #include <message_filters/subscriber.h>
00081 #include <message_filters/synchronizer.h>
00082 #include <message_filters/sync_policies/approximate_time.h>
00083 #include <image_transport/image_transport.h>
00084 #include <image_transport/subscriber_filter.h>
00085
00086
00087 #include <opencv2/opencv.hpp>
00088 #include <cv_bridge/cv_bridge.h>
00089 #include <sensor_msgs/image_encodings.h>
00090
00091
00092 #include <pcl/point_types.h>
00093 #include <pcl_ros/point_cloud.h>
00094
00095
00096 #include <boost/bind.hpp>
00097 #include <boost/thread/mutex.hpp>
00098
00099
00100 #include "cob_vision_utils/GlobalDefines.h"
00101
00102 #include <sstream>
00103 #include <string>
00104 #include <vector>
00105
00106 #include <pluginlib/class_list_macros.h>
00107
00108 namespace ipa_PeopleDetector
00109 {
00110
00111
00112
00113 class CobPeopleDetectionNodelet: public nodelet::Nodelet
00114 {
00115 protected:
00116
00117 image_transport::ImageTransport* it_;
00118 image_transport::SubscriberFilter people_segmentation_image_sub_;
00119 image_transport::SubscriberFilter color_image_sub_;
00120 message_filters::Synchronizer<message_filters::sync_policies::ApproximateTime<cob_perception_msgs::DetectionArray, sensor_msgs::Image> >* sync_input_2_;
00121 message_filters::Synchronizer<message_filters::sync_policies::ApproximateTime<cob_perception_msgs::DetectionArray, sensor_msgs::Image, sensor_msgs::Image> >
00122 * sync_input_3_;
00123 message_filters::Subscriber<cob_perception_msgs::DetectionArray> face_position_subscriber_;
00124 ros::Publisher face_position_publisher_;
00125 image_transport::Publisher people_detection_image_pub_;
00126 ros::ServiceServer service_server_detect_people_;
00127
00128
00129 ros::NodeHandle node_handle_;
00130
00131 std::vector<cob_perception_msgs::Detection> face_position_accumulator_;
00132 boost::timed_mutex face_position_accumulator_mutex_;
00133 std::vector<std::map<std::string, double> > face_identification_votes_;
00134
00135
00136 bool display_;
00137 bool use_people_segmentation_;
00138 double face_redetection_time_;
00139 double min_segmented_people_ratio_color_;
00140 double min_segmented_people_ratio_range_;
00141 double tracking_range_m_;
00142 double face_identification_score_decay_rate_;
00143 double min_face_identification_score_to_publish_;
00144 bool fall_back_to_unknown_identification_;
00145
00146 public:
00147
00148 CobPeopleDetectionNodelet()
00149 {
00150 it_ = 0;
00151 sync_input_2_ = 0;
00152 sync_input_3_ = 0;
00153 }
00154
00155 ~CobPeopleDetectionNodelet()
00156 {
00157 if (it_ != 0)
00158 delete it_;
00159 if (sync_input_2_ != 0)
00160 delete sync_input_2_;
00161 if (sync_input_3_ != 0)
00162 delete sync_input_3_;
00163 }
00164
00166 void onInit()
00167 {
00168 node_handle_ = getNodeHandle();
00169
00170
00171 std::cout << "\n---------------------------\nPeople Detection Parameters:\n---------------------------\n";
00172 node_handle_.param("display", display_, true);
00173 std::cout << "display = " << display_ << "\n";
00174 node_handle_.param("face_redetection_time", face_redetection_time_, 2.0);
00175 std::cout << "face_redetection_time = " << face_redetection_time_ << "\n";
00176 node_handle_.param("min_segmented_people_ratio_color", min_segmented_people_ratio_color_, 0.7);
00177 std::cout << "min_segmented_people_ratio_color = " << min_segmented_people_ratio_color_ << "\n";
00178 node_handle_.param("min_segmented_people_ratio_range", min_segmented_people_ratio_range_, 0.2);
00179 std::cout << "min_segmented_people_ratio_range = " << min_segmented_people_ratio_range_ << "\n";
00180 node_handle_.param("use_people_segmentation", use_people_segmentation_, true);
00181 std::cout << "use_people_segmentation = " << use_people_segmentation_ << "\n";
00182 node_handle_.param("tracking_range_m", tracking_range_m_, 0.3);
00183 std::cout << "tracking_range_m = " << tracking_range_m_ << "\n";
00184 node_handle_.param("face_identification_score_decay_rate", face_identification_score_decay_rate_, 0.9);
00185 std::cout << "face_identification_score_decay_rate = " << face_identification_score_decay_rate_ << "\n";
00186 node_handle_.param("min_face_identification_score_to_publish", min_face_identification_score_to_publish_, 0.9);
00187 std::cout << "min_face_identification_score_to_publish = " << min_face_identification_score_to_publish_ << "\n";
00188 node_handle_.param("fall_back_to_unknown_identification", fall_back_to_unknown_identification_, true);
00189 std::cout << "fall_back_to_unknown_identification = " << fall_back_to_unknown_identification_ << "\n";
00190
00191
00192 it_ = new image_transport::ImageTransport(node_handle_);
00193 people_segmentation_image_sub_.subscribe(*it_, "people_segmentation_image", 1);
00194 if (display_ == true)
00195 color_image_sub_.subscribe(*it_, "colorimage", 1);
00196 face_position_subscriber_.subscribe(node_handle_, "face_position_array_in", 1);
00197
00198
00199 sensor_msgs::Image::ConstPtr nullPtr;
00200 if (use_people_segmentation_ == true)
00201 {
00202 if (display_ == false)
00203 {
00204 sync_input_2_
00205 = new message_filters::Synchronizer<message_filters::sync_policies::ApproximateTime<cob_perception_msgs::DetectionArray, sensor_msgs::Image> >(2);
00206 sync_input_2_->connectInput(face_position_subscriber_, people_segmentation_image_sub_);
00207 sync_input_2_->registerCallback(boost::bind(&CobPeopleDetectionNodelet::inputCallback, this, _1, _2, nullPtr));
00208 }
00209 else
00210 {
00211 sync_input_3_ = new message_filters::Synchronizer<message_filters::sync_policies::ApproximateTime<cob_perception_msgs::DetectionArray, sensor_msgs::Image,
00212 sensor_msgs::Image> >(3);
00213 sync_input_3_->connectInput(face_position_subscriber_, people_segmentation_image_sub_, color_image_sub_);
00214 sync_input_3_->registerCallback(boost::bind(&CobPeopleDetectionNodelet::inputCallback, this, _1, _2, _3));
00215 }
00216 }
00217 else
00218 {
00219 if (display_ == true)
00220 {
00221 sync_input_2_
00222 = new message_filters::Synchronizer<message_filters::sync_policies::ApproximateTime<cob_perception_msgs::DetectionArray, sensor_msgs::Image> >(2);
00223 sync_input_2_->connectInput(face_position_subscriber_, color_image_sub_);
00224 sync_input_2_->registerCallback(boost::bind(&CobPeopleDetectionNodelet::inputCallback, this, _1, nullPtr, _2));
00225 }
00226 else
00227 {
00228 face_position_subscriber_.registerCallback(boost::bind(&CobPeopleDetectionNodelet::inputCallback, this, _1, nullPtr, nullPtr));
00229 }
00230 }
00231
00232
00233 service_server_detect_people_ = node_handle_.advertiseService("detect_people", &CobPeopleDetectionNodelet::detectPeopleCallback, this);
00234
00235
00236 face_position_publisher_ = node_handle_.advertise<cob_perception_msgs::DetectionArray>("face_position_array", 1);
00237 people_detection_image_pub_ = it_->advertise("people_detection_image", 1);
00238
00239 std::cout << "CobPeopleDetectionNodelet initialized.\n";
00240
00241
00242 }
00243
00245 unsigned long convertColorImageMessageToMat(const sensor_msgs::Image::ConstPtr& image_msg, cv_bridge::CvImageConstPtr& image_ptr, cv::Mat& image)
00246 {
00247 try
00248 {
00249 image_ptr = cv_bridge::toCvShare(image_msg, sensor_msgs::image_encodings::BGR8);
00250 } catch (cv_bridge::Exception& e)
00251 {
00252 ROS_ERROR("PeopleDetection: cv_bridge exception: %s", e.what());
00253 return ipa_Utils::RET_FAILED;
00254 }
00255 image = image_ptr->image;
00256
00257 return ipa_Utils::RET_OK;
00258 }
00259
00266 unsigned long copyDetection(const cob_perception_msgs::Detection& src, cob_perception_msgs::Detection& dest, bool update = false,
00267 unsigned int updateIndex = UINT_MAX)
00268 {
00269
00270 dest.mask.roi.x = src.mask.roi.x;
00271 dest.mask.roi.y = src.mask.roi.y;
00272 dest.mask.roi.width = src.mask.roi.width;
00273 dest.mask.roi.height = src.mask.roi.height;
00274
00275
00276 const geometry_msgs::Point* pointIn = &(src.pose.pose.position);
00277 geometry_msgs::Point* pointOut = &(dest.pose.pose.position);
00278 pointOut->x = pointIn->x;
00279 pointOut->y = pointIn->y;
00280 pointOut->z = pointIn->z;
00281
00282
00283 if (update == true)
00284 {
00285
00286
00287
00288 if (face_identification_votes_[updateIndex].find(src.label) == face_identification_votes_[updateIndex].end())
00289 face_identification_votes_[updateIndex][src.label] = 1.0;
00290 else
00291 face_identification_votes_[updateIndex][src.label] += 1.0;
00292
00293
00294
00295 double max_score = 0;
00296 dest.label = src.label;
00297 for (std::map<std::string, double>::iterator face_identification_votes_it = face_identification_votes_[updateIndex].begin(); face_identification_votes_it
00298 != face_identification_votes_[updateIndex].end(); face_identification_votes_it++)
00299 {
00300 face_identification_votes_it->second *= face_identification_score_decay_rate_;
00301 std::string label = face_identification_votes_it->first;
00302 if (((label != "Unknown" && fall_back_to_unknown_identification_ == false) || fall_back_to_unknown_identification_ == true) && label != "UnknownRange"
00303 && face_identification_votes_it->second > max_score)
00304 {
00305 max_score = face_identification_votes_it->second;
00306 dest.label = label;
00307 }
00308 }
00309
00310
00311 if (face_identification_votes_[updateIndex][dest.label] > face_identification_votes_[updateIndex]["UnknownRange"])
00312 face_identification_votes_[updateIndex]["UnknownRange"] = face_identification_votes_[updateIndex][dest.label];
00313 if (fall_back_to_unknown_identification_ == false)
00314 {
00315 if (face_identification_votes_[updateIndex]["Unknown"] > face_identification_votes_[updateIndex]["UnknownRange"])
00316 face_identification_votes_[updateIndex]["UnknownRange"] = face_identification_votes_[updateIndex]["Unknown"];
00317 }
00318 }
00319 else
00320 dest.label = src.label;
00321
00322 if (dest.label == "UnknownRange")
00323 dest.label = "Unknown";
00324
00325
00326
00327
00328
00329
00330
00331 dest.detector = src.detector;
00332
00333 dest.header.stamp = ros::Time::now();
00334
00335 return ipa_Utils::RET_OK;
00336 }
00337
00338 inline double abs(double x)
00339 {
00340 return ((x < 0) ? -x : x);
00341 }
00342
00346 double computeFacePositionDistance(const cob_perception_msgs::Detection& previous_detection, const cob_perception_msgs::Detection& current_detection)
00347 {
00348 const geometry_msgs::Point* point_1 = &(previous_detection.pose.pose.position);
00349 const geometry_msgs::Point* point_2 = &(current_detection.pose.pose.position);
00350
00351 double dx = abs(point_1->x - point_2->x);
00352 double dy = abs(point_1->y - point_2->y);
00353 double dz = abs(point_1->z - point_2->z);
00354
00355
00356 if (dx > tracking_range_m_ || dy > tracking_range_m_ || dz > tracking_range_m_)
00357 {
00358
00359 return DBL_MAX;
00360 }
00361
00362
00363 double dist = dx * dx + dy * dy + dz * dz;
00364 return dist;
00365 }
00366
00369 unsigned long removeMultipleInstancesOfLabel()
00370 {
00371
00372 for (int i = 0; i < (int)face_position_accumulator_.size(); i++)
00373 {
00374
00375 std::string label = face_position_accumulator_[i].label;
00376
00377
00378 if (label != "Unknown" && label != "No face")
00379 {
00380 for (int j = 0; j < (int)face_position_accumulator_.size(); j++)
00381 {
00382 if (j == i)
00383 continue;
00384
00385 if (face_position_accumulator_[j].label == label)
00386 {
00387 if (display_)
00388 std::cout << "face_identification_votes_[i][" << label << "] = " << face_identification_votes_[i][label] << " face_identification_votes_[j][" << label
00389 << "] = " << face_identification_votes_[j][label] << "\n";
00390
00391
00392 if (face_identification_votes_[i][label] < face_identification_votes_[j][label])
00393 {
00394 face_position_accumulator_[i].label = "Unknown";
00395
00396 if (face_identification_votes_[i][label] > face_identification_votes_[i]["Unknown"])
00397 face_identification_votes_[i]["Unknown"] = face_identification_votes_[i][label];
00398 }
00399 }
00400 }
00401 }
00402 }
00403
00404 return ipa_Utils::RET_OK;
00405 }
00406
00407 unsigned long prepareFacePositionMessage(cob_perception_msgs::DetectionArray& face_position_msg_out)
00408 {
00409
00410 std::vector<cob_perception_msgs::Detection> faces_to_publish;
00411 for (int i = 0; i < (int)face_position_accumulator_.size(); i++)
00412 {
00413 if (display_)
00414 std::cout << "'UnknownRange' score: " << face_identification_votes_[i]["UnknownRange"] << " label '" << face_position_accumulator_[i].label << "' score: "
00415 << face_identification_votes_[i][face_position_accumulator_[i].label] << " - ";
00416 if (face_identification_votes_[i][face_position_accumulator_[i].label] > min_face_identification_score_to_publish_ || face_identification_votes_[i]["UnknownRange"]
00417 > min_face_identification_score_to_publish_)
00418 {
00419 faces_to_publish.push_back(face_position_accumulator_[i]);
00420 if (display_)
00421 std::cout << "published\n";
00422 }
00423 else if (display_)
00424 std::cout << "not published\n";
00425 }
00426 face_position_msg_out.detections = faces_to_publish;
00427
00428
00429
00430
00431
00432
00433 face_position_msg_out.header.stamp = ros::Time::now();
00434
00435 return ipa_Utils::RET_OK;
00436 }
00437
00439 void inputCallback(const cob_perception_msgs::DetectionArray::ConstPtr& face_position_msg_in, const sensor_msgs::Image::ConstPtr& people_segmentation_image_msg,
00440 const sensor_msgs::Image::ConstPtr& color_image_msg)
00441 {
00442
00443 cv_bridge::CvImageConstPtr people_segmentation_image_ptr;
00444 cv::Mat people_segmentation_image;
00445 if (use_people_segmentation_ == true)
00446 convertColorImageMessageToMat(people_segmentation_image_msg, people_segmentation_image_ptr, people_segmentation_image);
00447
00448 if (display_)
00449 std::cout << "detections: " << face_position_msg_in->detections.size() << "\n";
00450
00451
00452 std::stringstream ss;
00453 ss << face_position_msg_in->header.frame_id;
00454 int width, height;
00455 ss >> width;
00456 ss >> height;
00457
00458
00459 ros::Duration timeSpan(face_redetection_time_);
00460 for (int i = 0; i < (int)face_position_accumulator_.size(); i++)
00461 {
00462 if ((ros::Time::now() - face_position_accumulator_[i].header.stamp) > timeSpan)
00463 {
00464 face_position_accumulator_.erase(face_position_accumulator_.begin() + i);
00465 face_identification_votes_.erase(face_identification_votes_.begin() + i);
00466 }
00467 }
00468 if (display_)
00469 std::cout << "Old face positions deleted.\n";
00470
00471
00472 boost::timed_mutex::scoped_timed_lock lock(face_position_accumulator_mutex_, boost::posix_time::milliseconds(2000));
00473 if (lock.owns_lock() == false)
00474 {
00475 ROS_ERROR("cob_people_detection::CobPeopleDetectionNodelet: Mutex was not freed during response time.");
00476 return;
00477 }
00478 if (display_)
00479 std::cout << "Got mutex.\n";
00480
00481
00482 std::vector<int> face_detection_indices;
00483 if (use_people_segmentation_ == true)
00484 {
00485 for (int i = 0; i < (int)face_position_msg_in->detections.size(); i++)
00486 {
00487 const cob_perception_msgs::Detection* const det_in = &(face_position_msg_in->detections[i]);
00488 cv::Rect face;
00489 face.x = det_in->mask.roi.x;
00490 face.y = det_in->mask.roi.y;
00491 face.width = det_in->mask.roi.width;
00492 face.height = det_in->mask.roi.height;
00493
00494 int numberBlackPixels = 0;
00495
00496 for (int v = face.y; v < face.y + face.height; v++)
00497 {
00498 uchar* data = people_segmentation_image.ptr(v);
00499 for (int u = face.x; u < face.x + face.width; u++)
00500 {
00501 int index = 3 * u;
00502 if (data[index] == 0 && data[index + 1] == 0 && data[index + 2] == 0)
00503 numberBlackPixels++;
00504 }
00505 }
00506 int faceArea = face.height * face.width;
00507 double segmentedPeopleRatio = (double)(faceArea - numberBlackPixels) / (double)faceArea;
00508
00509
00510 if ((det_in->detector == "color" && segmentedPeopleRatio < min_segmented_people_ratio_color_) || (det_in->detector == "range" && segmentedPeopleRatio
00511 < min_segmented_people_ratio_range_))
00512 {
00513
00514 if (display_)
00515 std::cout << "False detection\n";
00516 }
00517 else
00518 {
00519
00520 face_detection_indices.push_back(i);
00521 }
00522 }
00523 if (display_)
00524 std::cout << "Verification with people segmentation done.\n";
00525 }
00526 else
00527 {
00528 for (unsigned int i = 0; i < face_position_msg_in->detections.size(); i++)
00529 face_detection_indices.push_back(i);
00530 }
00531
00532
00533 std::map<int, std::map<int, double> > distance_matrix;
00534 std::map<int, std::map<int, double> >::iterator distance_matrix_it;
00535 for (unsigned int previous_det = 0; previous_det < face_position_accumulator_.size(); previous_det++)
00536 {
00537 std::map<int, double> distance_row;
00538 for (unsigned int i = 0; i < face_detection_indices.size(); i++)
00539 distance_row[face_detection_indices[i]] = computeFacePositionDistance(face_position_accumulator_[previous_det],
00540 face_position_msg_in->detections[face_detection_indices[i]]);
00541 distance_matrix[previous_det] = distance_row;
00542 }
00543 if (display_)
00544 std::cout << "Distance matrix.\n";
00545
00546
00547 unsigned int number_matchings = (face_position_accumulator_.size() < face_detection_indices.size()) ? face_position_accumulator_.size() : face_detection_indices.size();
00548 std::vector<bool> current_detection_has_matching(face_detection_indices.size(), false);
00549 for (unsigned int m = 0; m < number_matchings; m++)
00550 {
00551
00552 double min_dist = DBL_MAX;
00553 int previous_min_index, current_min_index;
00554 for (distance_matrix_it = distance_matrix.begin(); distance_matrix_it != distance_matrix.end(); distance_matrix_it++)
00555 {
00556 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++)
00557 {
00558 if (distance_row_it->second < min_dist)
00559 {
00560 min_dist = distance_row_it->second;
00561 previous_min_index = distance_matrix_it->first;
00562 current_min_index = distance_row_it->first;
00563 }
00564 }
00565 }
00566
00567
00568
00569
00570 if (min_dist == DBL_MAX)
00571 break;
00572
00573
00574 copyDetection(face_position_msg_in->detections[current_min_index], face_position_accumulator_[previous_min_index], true, previous_min_index);
00575
00576 for (unsigned int i = 0; i < face_detection_indices.size(); i++)
00577 if (face_detection_indices[i] == current_min_index)
00578 current_detection_has_matching[i] = true;
00579
00580
00581 distance_matrix.erase(previous_min_index);
00582 for (distance_matrix_it = distance_matrix.begin(); distance_matrix_it != distance_matrix.end(); distance_matrix_it++)
00583 distance_matrix_it->second.erase(current_min_index);
00584 }
00585 if (display_)
00586 std::cout << "Matches found.\n";
00587
00588
00589 for (unsigned int i = 0; i < face_detection_indices.size(); i++)
00590 {
00591 if (current_detection_has_matching[i] == false)
00592 {
00593 const cob_perception_msgs::Detection* const det_in = &(face_position_msg_in->detections[face_detection_indices[i]]);
00594 if (det_in->detector == "color")
00595 {
00596
00597 if (display_)
00598 std::cout << "\n***** New detection *****\n\n";
00599 cob_perception_msgs::Detection det_out;
00600 copyDetection(*det_in, det_out, false);
00601 det_out.pose.header.frame_id = face_position_msg_in->header.frame_id;
00602 face_position_accumulator_.push_back(det_out);
00603
00604 std::map<std::string, double> new_identification_data;
00605
00606 new_identification_data["UnknownRange"] = 0.0;
00607 new_identification_data[det_in->label] = 1.0;
00608 face_identification_votes_.push_back(new_identification_data);
00609 }
00610 }
00611 }
00612 if (display_)
00613 std::cout << "New detections.\n";
00614
00615
00616 removeMultipleInstancesOfLabel();
00617
00618
00619 cob_perception_msgs::DetectionArray face_position_msg_out;
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640 prepareFacePositionMessage(face_position_msg_out);
00641 face_position_publisher_.publish(face_position_msg_out);
00642
00643
00644 if (display_ == true)
00645 {
00646
00647 cv_bridge::CvImageConstPtr colorImagePtr;
00648 cv::Mat colorImage;
00649 convertColorImageMessageToMat(color_image_msg, colorImagePtr, colorImage);
00650
00651
00652 for (int i = 0; i < (int)face_position_msg_out.detections.size(); i++)
00653 {
00654 cv::Rect face;
00655 cob_perception_msgs::Rect& faceRect = face_position_msg_out.detections[i].mask.roi;
00656 face.x = faceRect.x;
00657 face.width = faceRect.width;
00658 face.y = faceRect.y;
00659 face.height = faceRect.height;
00660
00661 if (face_position_msg_out.detections[i].detector == "range")
00662 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);
00663 else
00664 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);
00665
00666 if (face_position_msg_out.detections[i].label == "Unknown")
00667
00668 cv::putText(colorImage, "Unknown", cv::Point(face.x, face.y + face.height + 25), cv::FONT_HERSHEY_PLAIN, 2, CV_RGB( 255, 0, 0 ), 2);
00669 else if (face_position_msg_out.detections[i].label == "No face")
00670
00671 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);
00672 else
00673
00674 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,
00675 CV_RGB( 0, 255, 0 ), 2);
00676 }
00677
00678 cv_bridge::CvImage cv_ptr;
00679 cv_ptr.image = colorImage;
00680 cv_ptr.encoding = "bgr8";
00681 people_detection_image_pub_.publish(cv_ptr.toImageMsg());
00682 }
00683 }
00684
00685 bool detectPeopleCallback(cob_people_detection::DetectPeople::Request &req, cob_people_detection::DetectPeople::Response &res)
00686 {
00687
00688 boost::timed_mutex::scoped_timed_lock lock(face_position_accumulator_mutex_, boost::posix_time::milliseconds(2000));
00689 if (lock.owns_lock() == false)
00690 {
00691 ROS_ERROR("cob_people_detection::CobPeopleDetectionNodelet: Mutex was not freed during response time.");
00692 return false;
00693 }
00694
00695 prepareFacePositionMessage(res.people_list);
00696
00697
00698 return true;
00699 }
00700 };
00701
00702 }
00703 ;
00704
00705 PLUGINLIB_EXPORT_CLASS(ipa_PeopleDetector::CobPeopleDetectionNodelet, nodelet::Nodelet);
00706
00707 #endif // _PEOPLE_DETECTION_