1 // Copyright (C) 2014 Davis E. King (davis@dlib.net) 2 // License: Boost Software License See LICENSE.txt for the full license. 3 4 5 #include <sstream> 6 #include "tester.h" 7 #include <dlib/svm_threaded.h> 8 #include <dlib/rand.h> 9 10 11 12 namespace 13 { 14 using namespace test; 15 using namespace dlib; 16 using namespace std; 17 18 logger dlog("test.learning_to_track"); 19 20 // ---------------------------------------------------------------------------------------- 21 22 struct detection_dense 23 { 24 typedef struct track_dense track_type; 25 matrix<double,0,1> measurements; 26 }; 27 28 29 struct track_dense 30 { 31 typedef matrix<double,0,1> feature_vector_type; 32 track_dense__anon8852b6760111::track_dense33 track_dense() 34 { 35 time_since_last_association = 0; 36 } 37 get_similarity_features__anon8852b6760111::track_dense38 void get_similarity_features(const detection_dense det, feature_vector_type& feats) const 39 { 40 feats = abs(last_measurements - det.measurements); 41 } 42 update_track__anon8852b6760111::track_dense43 void update_track(const detection_dense det) 44 { 45 last_measurements = det.measurements; 46 time_since_last_association = 0; 47 } 48 propagate_track__anon8852b6760111::track_dense49 void propagate_track() 50 { 51 ++time_since_last_association; 52 } 53 54 matrix<double,0,1> last_measurements; 55 unsigned long time_since_last_association; 56 }; 57 58 // ---------------------------------------------------------------------------------------- 59 60 struct detection_sparse 61 { 62 typedef struct track_sparse track_type; 63 matrix<double,0,1> measurements; 64 }; 65 66 67 struct track_sparse 68 { 69 typedef std::vector<std::pair<unsigned long,double> > feature_vector_type; 70 track_sparse__anon8852b6760111::track_sparse71 track_sparse() 72 { 73 time_since_last_association = 0; 74 } 75 get_similarity_features__anon8852b6760111::track_sparse76 void get_similarity_features(const detection_sparse det, feature_vector_type& feats) const 77 { 78 matrix<double,0,1> temp = abs(last_measurements - det.measurements); 79 feats.clear(); 80 for (long i = 0; i < temp.size(); ++i) 81 feats.push_back(make_pair(i, temp(i))); 82 } 83 update_track__anon8852b6760111::track_sparse84 void update_track(const detection_sparse det) 85 { 86 last_measurements = det.measurements; 87 time_since_last_association = 0; 88 } 89 propagate_track__anon8852b6760111::track_sparse90 void propagate_track() 91 { 92 ++time_since_last_association; 93 } 94 95 matrix<double,0,1> last_measurements; 96 unsigned long time_since_last_association; 97 }; 98 99 // ---------------------------------------------------------------------------------------- 100 // ---------------------------------------------------------------------------------------- 101 // ---------------------------------------------------------------------------------------- 102 103 dlib::rand rnd; 104 const long num_objects = 4; 105 const long num_properties = 6; 106 std::vector<matrix<double,0,1> > object_properties(num_objects); 107 initialize_object_properties()108 void initialize_object_properties() 109 { 110 rnd.set_seed("23ja2oirfjaf"); 111 for (unsigned long i = 0; i < object_properties.size(); ++i) 112 object_properties[i] = randm(num_properties,1,rnd); 113 } 114 115 template <typename detection> sample_detection_from_sensor(long object_id)116 detection sample_detection_from_sensor(long object_id) 117 { 118 DLIB_CASSERT(object_id < num_objects, 119 "You can't ask to sample a detection from an object that doesn't exist."); 120 detection temp; 121 // Set the measurements equal to the object's true property values plus a little bit of 122 // noise. 123 temp.measurements = object_properties[object_id] + randm(num_properties,1,rnd)*0.1; 124 return temp; 125 } 126 127 // ---------------------------------------------------------------------------------------- 128 129 130 template <typename detection> make_random_tracking_data_for_training()131 std::vector<std::vector<labeled_detection<detection> > > make_random_tracking_data_for_training() 132 { 133 typedef std::vector<labeled_detection<detection> > detections_at_single_time_step; 134 typedef std::vector<detections_at_single_time_step> track_history; 135 136 track_history data; 137 138 // At each time step we get a set of detections from the objects in the world. 139 // Simulate 100 time steps worth of data where there are 3 objects present. 140 const int num_time_steps = 100; 141 for (int i = 0; i < num_time_steps; ++i) 142 { 143 detections_at_single_time_step dets(3); 144 // sample a detection from object 0 145 dets[0].det = sample_detection_from_sensor<detection>(0); 146 dets[0].label = 0; 147 148 // sample a detection from object 1 149 dets[1].det = sample_detection_from_sensor<detection>(1); 150 dets[1].label = 1; 151 152 // sample a detection from object 2 153 dets[2].det = sample_detection_from_sensor<detection>(2); 154 dets[2].label = 2; 155 156 randomize_samples(dets, rnd); 157 data.push_back(dets); 158 } 159 160 // Now let's imagine object 1 and 2 are gone but a new object, object 3 has arrived. 161 for (int i = 0; i < num_time_steps; ++i) 162 { 163 detections_at_single_time_step dets(2); 164 // sample a detection from object 0 165 dets[0].det = sample_detection_from_sensor<detection>(0); 166 dets[0].label = 0; 167 168 // sample a detection from object 3 169 dets[1].det = sample_detection_from_sensor<detection>(3); 170 dets[1].label = 3; 171 172 randomize_samples(dets, rnd); 173 data.push_back(dets); 174 } 175 176 return data; 177 } 178 179 // ---------------------------------------------------------------------------------------- 180 181 template <typename detection> make_random_detections(long num_dets)182 std::vector<detection> make_random_detections(long num_dets) 183 { 184 DLIB_CASSERT(num_dets <= num_objects, 185 "You can't ask for more detections than there are objects in our little simulation."); 186 187 std::vector<detection> dets(num_dets); 188 for (unsigned long i = 0; i < dets.size(); ++i) 189 { 190 dets[i] = sample_detection_from_sensor<detection>(i); 191 } 192 randomize_samples(dets, rnd); 193 return dets; 194 } 195 196 // ---------------------------------------------------------------------------------------- 197 198 template <typename detection> test_tracking_stuff()199 void test_tracking_stuff() 200 { 201 print_spinner(); 202 203 204 typedef std::vector<labeled_detection<detection> > detections_at_single_time_step; 205 typedef std::vector<detections_at_single_time_step> track_history; 206 std::vector<track_history> data; 207 data.push_back(make_random_tracking_data_for_training<detection>()); 208 data.push_back(make_random_tracking_data_for_training<detection>()); 209 data.push_back(make_random_tracking_data_for_training<detection>()); 210 data.push_back(make_random_tracking_data_for_training<detection>()); 211 data.push_back(make_random_tracking_data_for_training<detection>()); 212 213 214 structural_track_association_trainer trainer; 215 trainer.set_c(1000); 216 track_association_function<detection> assoc = trainer.train(data); 217 218 double test_val = test_track_association_function(assoc, data); 219 DLIB_TEST_MSG( test_val == 1, test_val); 220 test_val = cross_validate_track_association_trainer(trainer, data, 5); 221 DLIB_TEST_MSG ( test_val == 1, test_val); 222 223 224 225 typedef typename detection::track_type track; 226 std::vector<track> tracks; 227 228 std::vector<detection> dets = make_random_detections<detection>(3); 229 assoc(tracks, dets); 230 DLIB_TEST(tracks.size() == 3); 231 232 dets = make_random_detections<detection>(3); 233 assoc(tracks, dets); 234 DLIB_TEST(tracks.size() == 3); 235 236 dets = make_random_detections<detection>(3); 237 assoc(tracks, dets); 238 DLIB_TEST(tracks.size() == 3); 239 240 dets = make_random_detections<detection>(4); 241 assoc(tracks, dets); 242 DLIB_TEST(tracks.size() == 4); 243 244 dets = make_random_detections<detection>(3); 245 assoc(tracks, dets); 246 DLIB_TEST(tracks.size() == 4); 247 unsigned long total_miss = 0; 248 for (unsigned long i = 0; i < tracks.size(); ++i) 249 total_miss += tracks[i].time_since_last_association; 250 DLIB_TEST(total_miss == 1); 251 252 dets = make_random_detections<detection>(3); 253 assoc(tracks, dets); 254 DLIB_TEST(tracks.size() == 4); 255 total_miss = 0; 256 unsigned long num_zero = 0; 257 for (unsigned long i = 0; i < tracks.size(); ++i) 258 { 259 total_miss += tracks[i].time_since_last_association; 260 if (tracks[i].time_since_last_association == 0) 261 ++num_zero; 262 } 263 DLIB_TEST(total_miss == 2); 264 DLIB_TEST(num_zero == 3); 265 266 267 268 ostringstream sout; 269 serialize(assoc, sout); 270 271 istringstream sin(sout.str()); 272 deserialize(assoc, sin); 273 DLIB_TEST( test_track_association_function(assoc, data) == 1); 274 } 275 276 277 // ---------------------------------------------------------------------------------------- 278 279 class test_learning_to_track : public tester 280 { 281 public: test_learning_to_track()282 test_learning_to_track ( 283 ) : 284 tester ("test_learning_to_track", 285 "Runs tests on the assignment learning code.") 286 {} 287 perform_test()288 void perform_test ( 289 ) 290 { 291 initialize_object_properties(); 292 for (int i = 0; i < 3; ++i) 293 { 294 dlog << LINFO << "run test_tracking_stuff<detection_dense>()"; 295 test_tracking_stuff<detection_dense>(); 296 dlog << LINFO << "run test_tracking_stuff<detection_sparse>()"; 297 test_tracking_stuff<detection_sparse>(); 298 } 299 } 300 } a; 301 302 // ---------------------------------------------------------------------------------------- 303 304 } 305 306 307