Go to the documentation of this file.00001
00060
00061
00062
00063 #include <munkres/munkres.h>
00064
00065
00066
00067
00068
00069 #include <ros/ros.h>
00070 #include <ros/package.h>
00071
00072
00073 #include <sensor_msgs/Image.h>
00074
00075 #include <cob_perception_msgs/DetectionArray.h>
00076
00077
00078
00079
00080
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
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
00094 #include <boost/bind.hpp>
00095 #include <boost/thread/mutex.hpp>
00096 #include <boost/lexical_cast.hpp>
00097
00098
00099 #include "cob_vision_utils/GlobalDefines.h"
00100
00101 #include <sstream>
00102 #include <string>
00103 #include <vector>
00104
00105 class EvalObj
00106 {
00107 public:
00108 ros::Time timestamp;
00109 std::vector<geometry_msgs::Point> positions;
00110 std::vector<std::string> labels;
00111 EvalObj()
00112 {
00113 }
00114 void print()
00115 {
00116 std::cout << "-----------------------------" << std::endl;
00117 std::cout << "Timestamp:\n" << timestamp << std::endl;
00118 std::cout << "Positions:" << std::endl;
00119 for (int i = 0; i < positions.size(); i++)
00120 {
00121 std::cout << positions[i].x << " " << positions[i].y << std::endl;
00122 ;
00123 }
00124 std::cout << "Labels:" << std::endl;
00125 for (int i = 0; i < labels.size(); i++)
00126 {
00127 std::cout << labels[i] << std::endl;
00128 ;
00129 }
00130 std::cout << "-----------------------------" << std::endl;
00131 }
00132
00133 bool compare(EvalObj& cmp, std::string& gt, bool& this_corr, bool& cmp_corr)
00134 {
00135 if (cmp.timestamp != this->timestamp)
00136 {
00137 std::cout << "time discrepancy - skipping comparison" << std::endl;
00138 return false;
00139 }
00140 else
00141 {
00142
00143 float dist = 100000;
00144 std::vector<int> index_arr;
00145 index_arr.resize(this->labels.size());
00146 if (this->labels.size() == 0)
00147 {
00148 std::cout << "empty label array...." << std::endl;
00149 return false;
00150 }
00151 if (cmp.labels.size() == 0)
00152 {
00153 std::cout << "empty label array...." << std::endl;
00154 return false;
00155 }
00156 for (int i = 0; i < this->labels.size(); i++)
00157 {
00158 for (int j = 0; j < cmp.labels.size(); j++)
00159 {
00160
00161 float tmp_dist = (cmp.positions[i].x - this->positions[j].x) * (cmp.positions[i].x - this->positions[j].y) + (cmp.positions[i].y - this->positions[j].y)
00162 * (cmp.positions[i].y - this->positions[j].y);
00163 if (tmp_dist < dist)
00164 {
00165 dist = tmp_dist;
00166 index_arr[i] = j;
00167 }
00168 }
00169 }
00170
00171
00172
00173
00174
00175
00176 this_corr = true;
00177 cmp_corr = true;
00178 for (int i; i < index_arr.size(); i++)
00179 {
00180 std::string a = boost::lexical_cast<std::string>(this->labels[i]);
00181 std::string b = boost::lexical_cast<std::string>(cmp.labels[index_arr[i]]);
00182 std::cout << a << ": " << gt.compare(a) << " - " << b << ": " << gt.compare(b) << std::endl;
00183 if (a.compare("UnknownHead") == 0 || b.compare("UnknownHead") == 0)
00184 {
00185 std::cout << "discarding" << std::endl;
00186 return false;
00187 }
00188
00189 if (a.compare(gt) != 0)
00190 this_corr = false;
00191 if (b.compare(gt) != 0)
00192 cmp_corr = false;
00193
00194 }
00195
00196 }
00197 return true;
00198 }
00199 };
00200
00201 class TrackingEvalNode
00202 {
00203 public:
00204
00205 EvalObj eval_rec_;
00206 EvalObj eval_track_;
00207 bool rec_track;
00208 bool rec_rec;
00209 std::string gt_name_;
00210
00211 int correct_trackings_;
00212 int correct_recognitions_;
00213 int total_comparisons_;
00214 int tracking_improvement_;
00215 int tracking_decline_;
00216 int error_out_;
00217
00218 ros::Subscriber recognition_subscriber_;
00219 ros::Subscriber tracking_subscriber_;
00220 ros::NodeHandle node_handle_;
00221
00222 TrackingEvalNode(ros::NodeHandle nh) :
00223 node_handle_(nh), correct_trackings_(0), correct_recognitions_(0), total_comparisons_(0), error_out_(0), tracking_improvement_(0), tracking_decline_(0), rec_track(false),
00224 rec_rec(false)
00225 {
00226
00227
00228 recognition_subscriber_ = node_handle_.subscribe("/cob_people_detection/face_recognizer/face_recognitions", 1, &TrackingEvalNode::recognitionCallback, this);
00229 tracking_subscriber_ = node_handle_.subscribe("/cob_people_detection/detection_tracker/face_position_array", 1, &TrackingEvalNode::trackingCallback, this);
00230
00231
00232 if (!node_handle_.getParam("/cob_people_detection/tracking_evaluator/person", gt_name_))
00233 std::cout << "PARAM NOT AVAILABLE" << std::endl;
00234 std::cout << "Groundtruth name: " << gt_name_ << "\n";
00235
00236 }
00237
00238 ~TrackingEvalNode()
00239 {
00240 }
00241
00242 double computeFacePositionDistance(const cob_perception_msgs::Detection& previous_detection, const cob_perception_msgs::Detection& current_detection)
00243 {
00244 const geometry_msgs::Point* point_1 = &(previous_detection.pose.pose.position);
00245 const geometry_msgs::Point* point_2 = &(current_detection.pose.pose.position);
00246
00247 double dx = point_1->x - point_2->x;
00248 double dy = point_1->y - point_2->y;
00249 double dz = point_1->z - point_2->z;
00250
00251 return sqrt(dx * dx + dy * dy + dz * dz);
00252 }
00253
00255 void trackingCallback(const cob_perception_msgs::DetectionArray::ConstPtr& face_position_msg_in)
00256 {
00257
00258
00259 EvalObj eval_obj;
00260 eval_obj.timestamp = face_position_msg_in->header.stamp;
00261
00262
00263 for (unsigned int i = 0; i < face_position_msg_in->detections.size(); i++)
00264 {
00265 if (face_position_msg_in->detections[i].label.compare("") != 0)
00266 {
00267
00268 eval_obj.positions.push_back(face_position_msg_in->detections[i].pose.pose.position);
00269 eval_obj.labels.push_back(face_position_msg_in->detections[i].label);
00270 }
00271 }
00272 eval_track_ = eval_obj;
00273 rec_track = true;
00274 this->eval();
00275 }
00277 void recognitionCallback(const cob_perception_msgs::DetectionArray::ConstPtr& face_position_msg_in)
00278 {
00279
00280
00281 EvalObj eval_obj;
00282 eval_obj.timestamp = face_position_msg_in->header.stamp;
00283
00284
00285 for (unsigned int i = 0; i < face_position_msg_in->detections.size(); i++)
00286 {
00287 if (face_position_msg_in->detections[i].label.compare("") != 0)
00288 {
00289
00290 eval_obj.positions.push_back(face_position_msg_in->detections[i].pose.pose.position);
00291 eval_obj.labels.push_back(face_position_msg_in->detections[i].label);
00292 }
00293 }
00294 eval_rec_ = eval_obj;
00295 rec_rec = true;
00296 this->eval();
00297 }
00298
00299 void eval()
00300 {
00301 if (rec_track == true && rec_rec == true)
00302 {
00303
00304
00305 if (eval_track_.timestamp == eval_rec_.timestamp)
00306 {
00307
00308 bool rec_res, track_res;
00309 bool cmp_successful = eval_rec_.compare(eval_track_, gt_name_, rec_res, track_res);
00310 if (cmp_successful)
00311 {
00312 if (rec_res)
00313 correct_recognitions_++;
00314 if (track_res)
00315 correct_trackings_++;
00316 if (track_res && !rec_res)
00317 tracking_improvement_++;
00318 if (!track_res && rec_res)
00319 tracking_decline_++;
00320 if (!track_res && !rec_res)
00321 error_out_++;
00322 total_comparisons_++;
00323 this->print_result();
00324 }
00325 rec_rec = false;
00326 rec_rec = false;
00327 }
00328 }
00329 }
00330 void print_result()
00331 {
00332 std::cout << "-----------------------------------" << std::endl;
00333 std::cout << "total comparisons : " << total_comparisons_ << std::endl;
00334 std::cout << "correctly recognized : " << ((float)correct_recognitions_ / (float)total_comparisons_) * 100 << " \%" << std::endl;
00335 std::cout << "correctly tracked : " << ((float)correct_trackings_ / (float)total_comparisons_) * 100 << " \%" << std::endl;
00336 std::cout << "tracking improvement : " << ((float)tracking_improvement_ / (float)total_comparisons_) * 100 << " \%" << std::endl;
00337 std::cout << "tracking worsening : " << ((float)tracking_decline_ / (float)total_comparisons_) * 100 << " \%" << std::endl;
00338 std::cout << "errors after tracking: " << (error_out_ / total_comparisons_) * 100 << " \%" << std::endl;
00339 std::cout << "-----------------------------------" << std::endl;
00340
00341
00342
00343
00344
00345
00346
00347
00348 }
00349 };
00350
00351
00352
00353 int main(int argc, char** argv)
00354 {
00355
00356 ros::init(argc, argv, "tracking_evaluator");
00357
00358
00359 ros::NodeHandle nh;
00360
00361
00362 TrackingEvalNode tracking_eval_node(nh);
00363
00364
00365
00366
00367
00368
00369 ros::spin();
00370
00371 return 0;
00372 }