main.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991
  1. //
  2. // Created by wrede on 19.04.16.
  3. //
  4. #include "../core/DetectionSequence.h"
  5. #include "../util/FileIO.h"
  6. #include "../util/Parser.h"
  7. #include "../algo/NStage.h"
  8. #include "../util/Visualizer.h"
  9. #include "../util/Logger.h"
  10. #include "../core/ObjectDataAngular.h"
  11. #include "../algo/Berclaz.h"
  12. #include "../algo/KShortestPaths.h"
  13. #include <boost/program_options.hpp>
  14. #include <boost/graph/named_function_params.hpp>
  15. #include <boost/graph/bellman_ford_shortest_paths.hpp>
  16. #include <iomanip>
  17. struct
  18. {
  19. std::string max_frame_skip;
  20. std::string max_tracklet_count;
  21. std::string penalty_value;
  22. double edge_weight_threshold;
  23. std::vector<std::unordered_map<std::string, double>> constraints;
  24. } n_stage_params;
  25. void RunNStage(core::DetectionSequence& sequence, std::vector<core::TrackletPtr>& tracks)
  26. {
  27. util::Logger::LogInfo("Running n-stage");
  28. std::vector<size_t> max_frame_skips;
  29. std::vector<double> penalty_values;
  30. std::vector<size_t> max_tracklet_counts;
  31. // Parse strings to vectors
  32. size_t d_index;
  33. std::string str, part;
  34. str = n_stage_params.max_frame_skip;
  35. do
  36. {
  37. d_index = str.find(",");
  38. part = str.substr(0, d_index);
  39. if (part.size() > 0)
  40. {
  41. max_frame_skips.push_back((unsigned long&&) atoi(part.c_str()));
  42. }
  43. str = str.substr(d_index + 1);
  44. }
  45. while (d_index != std::string::npos);
  46. str = n_stage_params.penalty_value;
  47. do
  48. {
  49. d_index = str.find(",");
  50. part = str.substr(0, d_index);
  51. if (part.size() > 0)
  52. {
  53. penalty_values.push_back(std::atof(part.c_str()));
  54. }
  55. str = str.substr(d_index + 1);
  56. }
  57. while (d_index != std::string::npos);
  58. str = n_stage_params.max_tracklet_count;
  59. do
  60. {
  61. d_index = str.find(",");
  62. part = str.substr(0, d_index);
  63. if (part.size() > 0)
  64. {
  65. max_tracklet_counts.push_back((unsigned long&&) atoi(part.c_str()));
  66. }
  67. str = str.substr(d_index + 1);
  68. }
  69. while (d_index != std::string::npos);
  70. // Init n-stage
  71. algo::NStage n_stage(max_frame_skips, penalty_values, max_tracklet_counts,
  72. n_stage_params.edge_weight_threshold, n_stage_params.constraints);
  73. n_stage.Run(sequence, tracks);
  74. // Interpolate tracks
  75. for (auto track : tracks)
  76. {
  77. track->InterpolateMissingFrames();
  78. }
  79. util::Logger::LogInfo("Finished");
  80. }
  81. struct
  82. {
  83. int h_res;
  84. int v_res;
  85. int vicinity_size;
  86. size_t batch_size;
  87. size_t max_track_count;
  88. util::Filter2D filter;
  89. } berclaz_params;
  90. void RunBerclaz(core::DetectionSequence & sequence, std::vector<core::TrackletPtr> & tracks)
  91. {
  92. util::Logger::LogInfo("Running berclaz");
  93. // Init berclaz
  94. algo::Berclaz berclaz(berclaz_params.h_res,
  95. berclaz_params.v_res,
  96. berclaz_params.vicinity_size);
  97. berclaz.Run(sequence,
  98. berclaz_params.batch_size,
  99. berclaz_params.max_track_count,
  100. tracks,
  101. berclaz_params.filter);
  102. util::Logger::LogInfo("Interpolate tracks");
  103. // Interpolate tracks
  104. for (auto track : tracks)
  105. {
  106. track->InterpolateMissingFrames();
  107. }
  108. util::Logger::LogInfo("Finished");
  109. }
  110. void Run(int argc, char const * const * argv)
  111. {
  112. //TODO output info for all possible constraints
  113. // Algorithm independent values
  114. std::string input_file, output_path, images_folder, algorithm, config_path, header;
  115. std::string input_format, berclaz_filter, n_stage_constraints;
  116. bool info, debug, display, output, output_images, show_grid;
  117. char input_delimiter, output_delimiter;
  118. double temporal_weight, spatial_weight, angular_weight, image_width, image_height;
  119. boost::program_options::options_description opts("Allowed options");
  120. opts.add_options()
  121. ("help",
  122. "produce help message")
  123. ("info",
  124. boost::program_options::value<bool>(&info)
  125. ->default_value(false),
  126. "if the program should show progress information")
  127. ("debug",
  128. boost::program_options::value<bool>(&debug)
  129. ->default_value(false),
  130. "if the program should show debug messages")
  131. ("display.enabled",
  132. boost::program_options::value<bool>(&display)
  133. ->default_value(false),
  134. "if a window with the images and the detected tracks should be opened")
  135. ("display.show-grid",
  136. boost::program_options::value<bool>(&show_grid)
  137. ->default_value(false),
  138. "if a grid should be shown in the visualized tracks (will only be shown if a resolution is given)")
  139. ("config",
  140. boost::program_options::value<std::string>(&config_path),
  141. "the path to the config file, if no path is given the command line arguments are read")
  142. ("input.file",
  143. boost::program_options::value<std::string>(&input_file),
  144. "set detections file path")
  145. ("output.enabled",
  146. boost::program_options::value<bool>(&output)
  147. ->default_value(false),
  148. "if the results should be written into the specified output folder")
  149. ("output.images",
  150. boost::program_options::value<bool>(&output_images)
  151. ->default_value(false),
  152. "if the images containing the visualized detections should be written to the output,"
  153. "a folder named 'images' in the output folder is required to store the images")
  154. ("output.path",
  155. boost::program_options::value<std::string>(&output_path),
  156. "set the output file path")
  157. ("output.delimiter",
  158. boost::program_options::value<char>(&output_delimiter)
  159. ->default_value(';'),
  160. "the delimiter used to separate values in the specified output file")
  161. ("input.images-folder",
  162. boost::program_options::value<std::string>(&images_folder),
  163. "set images folder path")
  164. ("input.header",
  165. boost::program_options::value<std::string>(&header),
  166. "sets the input header, this value is optional if the input file has a header labeling the values,"
  167. "the delimiter used for the header needs to be the same as for the rest of the file")
  168. ("input.format",
  169. boost::program_options::value<std::string>(&input_format)
  170. ->default_value("ObjectData"),
  171. "the format the input should be parsed into, valid formats are: "
  172. "2D, Box, Angular")
  173. ("input.delimiter",
  174. boost::program_options::value<char>(&input_delimiter)
  175. ->default_value(';'),
  176. "the delimiter used to separate values in the specified input file")
  177. ("input.image-width",
  178. boost::program_options::value<double>(&image_width)
  179. ->default_value(1.0),
  180. "the width of the image")
  181. ("input.image-height",
  182. boost::program_options::value<double>(&image_height)
  183. ->default_value(1.0),
  184. "the height of the image")
  185. ("algorithm",
  186. boost::program_options::value<std::string>(&algorithm),
  187. "set the algorithm to use, current viable options: n-stage berclaz")
  188. ("n-stage.max-frame-skip",
  189. boost::program_options::value<std::string>(&n_stage_params.max_frame_skip)
  190. ->default_value("1,1"),
  191. "(n-stage) set the maximum number of frames a track can skip between two detections,"
  192. " if set to less or equal than zero all frames are linked")
  193. ("n-stage.max-tracklet-count",
  194. boost::program_options::value<std::string>(&n_stage_params.max_tracklet_count)
  195. ->default_value("-1,1"),
  196. "(n-stage) set the maximum number of tracklets to be extracted")
  197. ("n-stage.penalty-value",
  198. boost::program_options::value<std::string>(&n_stage_params.penalty_value)
  199. ->default_value("0,0"),
  200. "(n-stage) set the penalty value for edges from and to source and sink")
  201. ("n-stage.temporal-weight",
  202. boost::program_options::value<double>(&temporal_weight)
  203. ->default_value(1.0),
  204. "(n-stage) temporal weight for difference calculations between two detections")
  205. ("n-stage.spatial-weight",
  206. boost::program_options::value<double>(&spatial_weight)
  207. ->default_value(1.0),
  208. "(n-stage) spatial weight for difference calculations between two detections")
  209. ("n-stage.angular-weight",
  210. boost::program_options::value<double>(&angular_weight)
  211. ->default_value(1.0),
  212. "(n-stage) angular weight for difference calculations between two detections")
  213. ("n-stage.edge-weight-threshold",
  214. boost::program_options::value<double>(&n_stage_params.edge_weight_threshold)
  215. ->default_value(1.0),
  216. "(n-stage) the maximum weight an edge can have in the initial graph, edges with"
  217. "higher edge weights are discarded")
  218. ("n-stage.constraints",
  219. boost::program_options::value<std::string>(&n_stage_constraints)
  220. ->default_value(""),
  221. "(n-stage) the constraints to ensure when creating the object graph,"
  222. " values and keys are separated by commas, stages are separated by semicolons,"
  223. " for example: key00,value00,key01,value01;key11,value11,key12,value21")
  224. ("berclaz.h-res",
  225. boost::program_options::value<int>(&berclaz_params.h_res)
  226. ->default_value(10),
  227. "(berclaz) the number of horizontal grid cells")
  228. ("berclaz.v-res",
  229. boost::program_options::value<int>(&berclaz_params.v_res)
  230. ->default_value(10),
  231. "(berclaz) the number of vertical grid cells")
  232. ("berclaz.vicinity-size",
  233. boost::program_options::value<int>(&berclaz_params.vicinity_size)
  234. ->default_value(1),
  235. "(berclaz) the vicinity size, the number of cells a detection can travel between two frames")
  236. ("berclaz.max-track-count",
  237. boost::program_options::value<size_t>(&berclaz_params.max_track_count)
  238. ->default_value(1),
  239. "(berclaz) the maximal number of tracks to extract")
  240. ("berclaz.batch-size",
  241. boost::program_options::value<size_t>(&berclaz_params.batch_size)
  242. ->default_value(100),
  243. "(berclaz) the size of one processing batch")
  244. ("berclaz.filter",
  245. boost::program_options::value<std::string>(&berclaz_filter)
  246. ->default_value(""),
  247. "(berclaz) the filter used in the berclaz grid (comma separated),"
  248. " e.g. multiplier, m01, m02,...,mnn");
  249. boost::program_options::variables_map opt_var_map;
  250. boost::program_options::store(
  251. boost::program_options::parse_command_line(argc, argv, opts),
  252. opt_var_map);
  253. boost::program_options::notify(opt_var_map);
  254. // Display help
  255. if (opt_var_map.count("help") != 0)
  256. {
  257. std::cout << opts << std::endl;
  258. exit(0);
  259. }
  260. // Read config
  261. if (opt_var_map.count("config") != 0)
  262. {
  263. std::ifstream config_file(config_path, std::ifstream::in);
  264. if (config_file.is_open())
  265. {
  266. boost::program_options::store(
  267. boost::program_options::parse_config_file(config_file,
  268. opts),
  269. opt_var_map);
  270. config_file.close();
  271. boost::program_options::notify(opt_var_map);
  272. }
  273. else
  274. {
  275. util::Logger::LogError("Unable to open config file!");
  276. exit(0);
  277. }
  278. }
  279. else if (opt_var_map.count("input-file") == 0 ||
  280. opt_var_map.count("input-format") == 0 ||
  281. (opt_var_map.count("output-path") == 0 && (output || output_images)))
  282. {
  283. std::cout << opts << std::endl;
  284. exit(0);
  285. }
  286. // Enable info logging
  287. if (info != 0)
  288. {
  289. util::Logger::SetInfo(true);
  290. util::Logger::LogInfo("Enabled");
  291. }
  292. // Enable debug logging
  293. if (debug != 0)
  294. {
  295. util::Logger::SetDebug(true);
  296. util::Logger::LogDebug("Enabled");
  297. }
  298. // Reading the input file
  299. util::Logger::LogInfo("Read input");
  300. util::ValueMapVector values;
  301. try
  302. {
  303. if (header.size() > 0)
  304. {
  305. util::Logger::LogDebug("header specified");
  306. util::FileIO::ReadCSV(values, header, input_file, input_delimiter);
  307. }
  308. else
  309. {
  310. util::Logger::LogDebug("read header from file");
  311. util::FileIO::ReadCSV(values, input_file, input_delimiter);
  312. }
  313. }
  314. catch (std::exception& e)
  315. {
  316. util::Logger::LogError("Failed to read input file!");
  317. util::Logger::LogError(e.what());
  318. exit(0);
  319. }
  320. // Parsing the read input
  321. core::DetectionSequence sequence;
  322. if (input_format == "2D")
  323. {
  324. util::Parser::ParseObjectData2D(values,
  325. sequence,
  326. image_width,
  327. image_height,
  328. temporal_weight,
  329. spatial_weight);
  330. }
  331. else if (input_format == "Box")
  332. {
  333. util::Parser::ParseObjectDataBox(values,
  334. sequence,
  335. image_width,
  336. image_height,
  337. temporal_weight,
  338. spatial_weight);
  339. }
  340. else if (input_format == "Angular")
  341. {
  342. util::Parser::ParseObjectDataAngular(values,
  343. sequence,
  344. image_width,
  345. image_height,
  346. temporal_weight,
  347. spatial_weight,
  348. angular_weight);
  349. }
  350. else
  351. {
  352. // No valid input-format specified
  353. std::cout << opts << std::endl;
  354. exit(0);
  355. }
  356. // Running the specified algorithm
  357. std::vector<core::TrackletPtr> tracks;
  358. time_t begin_time, end_time;
  359. std::string output_file_name = algorithm;
  360. util::Logger::LogInfo("Start time measurement");
  361. begin_time = time(0);
  362. if (algorithm == "n-stage")
  363. {
  364. // Parse the constraints
  365. std::vector<std::string> stages = util::FileIO::Split(n_stage_constraints, ';');
  366. for (size_t i = 0; i < stages.size(); ++i)
  367. {
  368. std::unordered_map<std::string, double> map;
  369. std::vector<std::string> pairs = util::FileIO::Split(stages[i], ',');
  370. for (size_t j = 1; j < pairs.size(); ++j)
  371. {
  372. map[pairs[j - 1]] = stod(pairs[j]);
  373. }
  374. n_stage_params.constraints.push_back(map);
  375. }
  376. //TODO set the output file name to better distinguish between different parameter values
  377. // std::vector<std::string> t_counts = util::FileIO::Split(n_stage_params.max_tracklet_count, ',');
  378. // for (auto str : t_counts)
  379. // {
  380. // output_file_name += "_" + str;
  381. // }
  382. RunNStage(sequence, tracks);
  383. }
  384. else if (algorithm == "berclaz")
  385. {
  386. output_file_name += "_" + std::to_string(berclaz_params.h_res) + "x"
  387. + std::to_string(berclaz_params.v_res) + "_"
  388. + std::to_string(berclaz_params.vicinity_size) + "_"
  389. + std::to_string(berclaz_params.max_track_count) + "_"
  390. + std::to_string(berclaz_params.batch_size);
  391. berclaz_params.filter = util::Filter2D(berclaz_filter, ',');
  392. RunBerclaz(sequence, tracks);
  393. }
  394. else
  395. {
  396. // No valid algorithm specified
  397. std::cout << opts << std::endl;
  398. exit(0);
  399. }
  400. output_file_name += ".csv";
  401. end_time = time(0);
  402. util::Logger::LogInfo("Time measurement stopped");
  403. util::Logger::LogInfo("Time passed: "
  404. + std::to_string(difftime(end_time, begin_time) / 60.0)
  405. + " minutes");
  406. // Write the output file
  407. if (output)
  408. {
  409. util::FileIO::WriteTracks(tracks, output_path + "/" + output_file_name, output_delimiter);
  410. }
  411. // Display the tracking data
  412. util::Visualizer vis;
  413. if (algorithm == "berclaz")
  414. vis.Display(tracks, sequence.GetFrameOffset(),
  415. images_folder, output_images, display, output_path, "Visualizer",
  416. 0, 24, show_grid, berclaz_params.h_res, berclaz_params.v_res);
  417. else
  418. vis.Display(tracks, sequence.GetFrameOffset(),
  419. images_folder, output_images, display, output_path);
  420. //TODO add CLEAR-MOT evaluation to pipeline
  421. }
  422. void CreateTestGraph(DirectedGraph& graph, Vertex& source, Vertex& sink)
  423. {
  424. // Create test graph (suurballe wikipedia example)
  425. // std::vector<Vertex> vertices;
  426. // for (size_t i = 0; i < 6; ++i)
  427. // {
  428. // vertices.push_back(
  429. // boost::add_vertex(
  430. // core::ObjectDataPtr(new core::ObjectData(i)),graph));
  431. // }
  432. //
  433. // // AB
  434. // boost::add_edge(vertices[0], vertices[1], 1.0, graph);
  435. // boost::add_edge(vertices[1], vertices[0], 1.0, graph);
  436. //
  437. // // AC
  438. // boost::add_edge(vertices[0], vertices[2], 2.0, graph);
  439. // boost::add_edge(vertices[2], vertices[0], 2.0, graph);
  440. //
  441. // // BD
  442. // boost::add_edge(vertices[1], vertices[3], 1.0, graph);
  443. // boost::add_edge(vertices[3], vertices[1], 1.0, graph);
  444. //
  445. // // BE
  446. // boost::add_edge(vertices[1], vertices[4], 2.0, graph);
  447. // boost::add_edge(vertices[4], vertices[1], 2.0, graph);
  448. //
  449. // // CD
  450. // boost::add_edge(vertices[2], vertices[3], 2.0, graph);
  451. // boost::add_edge(vertices[3], vertices[2], 2.0, graph);
  452. //
  453. // // DF
  454. // boost::add_edge(vertices[3], vertices[5], 1.0, graph);
  455. // boost::add_edge(vertices[5], vertices[3], 1.0, graph);
  456. //
  457. // // EF
  458. // boost::add_edge(vertices[4], vertices[5], 2.0, graph);
  459. // boost::add_edge(vertices[5], vertices[4], 2.0, graph);
  460. //
  461. // source = vertices[0];
  462. // sink = vertices[5];
  463. // Create test graph
  464. std::vector<Vertex> vertices;
  465. for (size_t i = 0; i < 11; ++i)
  466. {
  467. vertices.push_back(
  468. boost::add_vertex(
  469. core::ObjectDataPtr(new core::ObjectData(i)),graph));
  470. }
  471. // boost::add_edge(vertices[0], vertices[1], 0.0, graph);
  472. // boost::add_edge(vertices[0], vertices[8], 0.0, graph);
  473. // boost::add_edge(vertices[0], vertices[4], 0.0, graph);
  474. // boost::add_edge(vertices[1], vertices[2], -1.0, graph);
  475. // boost::add_edge(vertices[1], vertices[5], -1.0, graph);
  476. // boost::add_edge(vertices[2], vertices[3], -1.0, graph);
  477. // boost::add_edge(vertices[2], vertices[6], -1.0, graph);
  478. // boost::add_edge(vertices[2], vertices[10], -1.0, graph);
  479. // boost::add_edge(vertices[3], vertices[7], 4.0, graph);
  480. // boost::add_edge(vertices[4], vertices[2], 1.0, graph);
  481. // boost::add_edge(vertices[4], vertices[5], 1.0, graph);
  482. // boost::add_edge(vertices[4], vertices[9], 1.0, graph);
  483. // boost::add_edge(vertices[5], vertices[6], 2.0, graph);
  484. // boost::add_edge(vertices[5], vertices[3], 2.0, graph);
  485. // boost::add_edge(vertices[6], vertices[7], 4.0, graph);
  486. // boost::add_edge(vertices[8], vertices[2], -3.0, graph);
  487. // boost::add_edge(vertices[8], vertices[9], -3.0, graph);
  488. // boost::add_edge(vertices[9], vertices[3], 3.0, graph);
  489. // boost::add_edge(vertices[9], vertices[10], 3.0, graph);
  490. // boost::add_edge(vertices[10], vertices[7], 4.0, graph);
  491. source = vertices[0];
  492. sink = vertices[10];
  493. for (int i = 1; i < vertices.size() - 1; ++i)
  494. {
  495. boost::add_edge(source, vertices[i], 0.0, graph);
  496. }
  497. boost::add_edge(vertices[1], vertices[4], -1.0, graph);
  498. boost::add_edge(vertices[1], vertices[5], -1.0, graph);
  499. boost::add_edge(vertices[1], vertices[10], 0.0, graph);
  500. boost::add_edge(vertices[4], vertices[7], -1.0, graph);
  501. boost::add_edge(vertices[4], vertices[8], -1.0, graph);
  502. boost::add_edge(vertices[4], vertices[10], 0.0, graph);
  503. boost::add_edge(vertices[7], vertices[10], -1.0, graph);
  504. boost::add_edge(vertices[2], vertices[4], -2.0, graph);
  505. boost::add_edge(vertices[2], vertices[5], -2.0, graph);
  506. boost::add_edge(vertices[2], vertices[6], -2.0, graph);
  507. boost::add_edge(vertices[2], vertices[10], 0.0, graph);
  508. boost::add_edge(vertices[5], vertices[7], -2.0, graph);
  509. boost::add_edge(vertices[5], vertices[8], -2.0, graph);
  510. boost::add_edge(vertices[5], vertices[9], -2.0, graph);
  511. boost::add_edge(vertices[5], vertices[10], 0.0, graph);
  512. boost::add_edge(vertices[8], vertices[10], -2.0, graph);
  513. boost::add_edge(vertices[3], vertices[5], -3.0, graph);
  514. boost::add_edge(vertices[3], vertices[6], -3.0, graph);
  515. boost::add_edge(vertices[3], vertices[10], 0.0, graph);
  516. boost::add_edge(vertices[6], vertices[8], -3.0, graph);
  517. boost::add_edge(vertices[6], vertices[9], -3.0, graph);
  518. boost::add_edge(vertices[6], vertices[10], 0.0, graph);
  519. boost::add_edge(vertices[9], vertices[10], -3.0, graph);
  520. // Connect all with source and sink
  521. // boost::add_edge(vertices[1], sink, 0, graph);
  522. // boost::add_edge(source, vertices[2], 0, graph);
  523. // boost::add_edge(vertices[2], sink, 0, graph);
  524. // boost::add_edge(source, vertices[3], 0, graph);
  525. // boost::add_edge(vertices[4], sink, 0, graph);
  526. // boost::add_edge(source, vertices[5], 0, graph);
  527. // boost::add_edge(vertices[5], sink, 0, graph);
  528. // boost::add_edge(source, vertices[6], 0, graph);
  529. // boost::add_edge(vertices[8], sink, 0, graph);
  530. // boost::add_edge(source, vertices[9], 0, graph);
  531. // boost::add_edge(vertices[9], sink, 0, graph);
  532. // boost::add_edge(source, vertices[10], 0, graph);
  533. // boost::add_edge(vertices[1], vertices[7], 0.0, graph);
  534. // boost::add_edge(vertices[8], vertices[7], 0.0, graph);
  535. }
  536. void TestKBellmanFord(DirectedGraph graph, Vertex source, Vertex sink, size_t n_paths)
  537. {
  538. util::FileIO::WriteCSVMatlab(graph, "/home/wrede/Dokumente/graph_kbf.csv");
  539. MultiPredecessorMap paths;
  540. for (size_t i = 0; i < n_paths; ++i)
  541. {
  542. // Prepare variables for path finding
  543. size_t graph_size = boost::num_vertices(graph);
  544. std::vector<Vertex> pred_list(graph_size);
  545. std::vector<double> dist_list(graph_size);
  546. VertexIndexMap graph_indices = boost::get(boost::vertex_index, graph);
  547. EdgeWeightMap weight_map = boost::get(boost::edge_weight, graph);
  548. PredecessorMap pred_map(&pred_list[0], graph_indices);
  549. DistanceMap dist_map(&dist_list[0], graph_indices);
  550. // Find the shortest path
  551. boost::bellman_ford_shortest_paths(graph, graph_size,
  552. boost::root_vertex(source)
  553. .weight_map(weight_map)
  554. .predecessor_map(pred_map)
  555. .distance_map(dist_map));
  556. // Add path
  557. for (Vertex u = sink, v = pred_map[u]; u != v; u = v, v = pred_map[v])
  558. {
  559. paths[u].insert(v);
  560. if (u != sink && u != source)
  561. boost::clear_out_edges(u, graph);
  562. }
  563. }
  564. util::FileIO::WriteCSVMatlab(paths, source, sink, "/home/wrede/Dokumente/paths_kbf.csv");
  565. }
  566. void TestGrid()
  567. {
  568. int lower_index = 0;
  569. int upper_index = 5;
  570. double lower_bound = 0.0;
  571. double upper_bound = 50.0;
  572. util::Grid grid(upper_index, upper_index, upper_index,
  573. upper_bound, upper_bound, upper_bound);
  574. std::uniform_int_distribution<int> unii(lower_index, upper_index - 1);
  575. std::uniform_real_distribution<double> unif(lower_bound, upper_bound);
  576. std::default_random_engine re;
  577. // Fill with empty values
  578. std::cout << "fill with empty values\n";
  579. for (int z = lower_index; z < upper_index; ++z)
  580. {
  581. for (int y = lower_index; y < upper_index; ++y)
  582. {
  583. for (int x = lower_index; y < upper_index; ++y)
  584. {
  585. grid.SetValue(nullptr, x, y, z);
  586. }
  587. }
  588. }
  589. // Randomly add data
  590. std::cout << "randomly add data\n";
  591. for (int i = 0; i < 10; ++i)
  592. {
  593. int xi = unii(re);
  594. int yi = unii(re);
  595. int zi = unii(re);
  596. core::ObjectDataPtr value(new core::ObjectData((size_t)i));
  597. grid.SetValue(value, xi, yi, zi);
  598. std::cout << xi << "," << yi << "," << zi << " = " << *value << std::endl;
  599. }
  600. // Randomly get data
  601. std::cout << "randomly get data\n";
  602. for (int i = 0; i < 10; ++i)
  603. {
  604. double x = unif(re);
  605. double y = unif(re);
  606. double z = unif(re);
  607. std::cout << x << "," << y << "," << z << " = ";
  608. core::ObjectDataPtr value = grid.GetValue(x, y, z);
  609. if (value)
  610. {
  611. std::cout << *value << std::endl;
  612. }
  613. else
  614. {
  615. std::cout << "nullptr" << std::endl;
  616. }
  617. }
  618. }
  619. void CreateBerclazGraph(DirectedGraph& graph, Vertex& source, Vertex& sink)
  620. {
  621. util::Logger::SetDebug(true);
  622. util::Logger::SetInfo(true);
  623. util::Logger::LogInfo("Test berclaz graph");
  624. // Init grid with data
  625. util::Grid grid(3, 3, 3, 9.0, 9.0, 9.0);
  626. for (int z = 0; z < grid.GetDepthCount(); ++z)
  627. {
  628. for (int y = 0; y < grid.GetHeightCount(); ++y)
  629. {
  630. for (int x = 0; x < grid.GetWidthCount(); ++x)
  631. {
  632. core::ObjectDataPtr value(new core::ObjectData(10));
  633. grid.SetValue(value, x, y, z);
  634. }
  635. }
  636. }
  637. // Add path source->0,0,0->0,0,1->0,0,2->sink
  638. core::ObjectDataPtr value0(new core::ObjectData(1));
  639. value0->SetDetectionScore(1.0);
  640. grid.SetValue(value0, 0, 0, 0);
  641. core::ObjectDataPtr value1(new core::ObjectData(2));
  642. value1->SetDetectionScore(1.0);
  643. grid.SetValue(value1, 0, 0, 1);
  644. core::ObjectDataPtr value2(new core::ObjectData(3));
  645. value2->SetDetectionScore(1.0);
  646. grid.SetValue(value2, 0, 0, 2);
  647. // Add path source->0,1,0->0,1,1->0,1,2->sink
  648. core::ObjectDataPtr value3(new core::ObjectData(4));
  649. value3->SetDetectionScore(0.6);
  650. grid.SetValue(value3, 0, 1, 0);
  651. core::ObjectDataPtr value4(new core::ObjectData(5));
  652. value4->SetDetectionScore(0.6);
  653. grid.SetValue(value4, 0, 1, 1);
  654. core::ObjectDataPtr value5(new core::ObjectData(6));
  655. value5->SetDetectionScore(0.6);
  656. grid.SetValue(value5, 0, 1, 2);
  657. // Add path source->0,2,0->0,2,1->0,2,2->sink
  658. core::ObjectDataPtr value6(new core::ObjectData(7));
  659. value6->SetDetectionScore(0.55);
  660. grid.SetValue(value6, 0, 2, 0);
  661. core::ObjectDataPtr value7(new core::ObjectData(8));
  662. value7->SetDetectionScore(0.55);
  663. grid.SetValue(value7, 0, 2, 1);
  664. core::ObjectDataPtr value8(new core::ObjectData(9));
  665. value8->SetDetectionScore(0.55);
  666. grid.SetValue(value8, 0, 2, 2);
  667. util::Logger::LogDebug("add vertices");
  668. // Add grid vertices
  669. graph.clear();
  670. for (int z = 0; z < grid.GetDepthCount(); ++z)
  671. {
  672. for (int y = 0; y < grid.GetHeightCount(); ++y)
  673. {
  674. for (int x = 0; x < grid.GetWidthCount(); ++x)
  675. {
  676. boost::add_vertex(grid.GetValue(x, y, z), graph);
  677. }
  678. }
  679. }
  680. util::Logger::LogDebug("vertex count " + std::to_string(boost::num_vertices(graph)));
  681. util::Logger::LogDebug("edge count " + std::to_string(boost::num_edges(graph)));
  682. // Add source and sink vertex
  683. source = boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()), graph);
  684. sink = boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()), graph);
  685. util::Logger::LogDebug("add edges");
  686. // Iterate all vertices but source and sink
  687. VertexIndexMap vertices = boost::get(boost::vertex_index, graph);
  688. VertexValueMap values = boost::get(boost::vertex_name, graph);
  689. int vicinity_size = 1;
  690. int layer_size = grid.GetWidthCount() * grid.GetHeightCount();
  691. for (int z = 0; z < grid.GetDepthCount(); ++z)
  692. {
  693. for (int y = 0; y < grid.GetHeightCount(); ++y)
  694. {
  695. for (int x = 0; x < grid.GetWidthCount(); ++x)
  696. {
  697. // First vertex index
  698. int vi = x + y * grid.GetHeightCount() + z * layer_size;
  699. // Get the score, clamp it, prevent division by zero and
  700. // logarithm of zero
  701. double score = values[vi]->GetDetectionScore();
  702. if (score > 0.999999)
  703. {
  704. score = 0.999999;
  705. }
  706. else if (score < 0.000001)
  707. {
  708. score = 0.000001;
  709. }
  710. // Calculate the edge weight
  711. double weight = -std::log(score / (1 - score));
  712. // Connect with the next frame only if there is a next frame
  713. if (z < grid.GetDepthCount() - 1)
  714. {
  715. // Iterate all nearby cells in the next frame
  716. for (int ny = std::max(0, y - vicinity_size);
  717. ny < std::min(grid.GetHeightCount(), y + vicinity_size + 1);
  718. ++ny)
  719. {
  720. for (int nx = std::max(0, x - vicinity_size);
  721. nx < std::min(grid.GetWidthCount(), x + vicinity_size + 1);
  722. ++nx)
  723. {
  724. // Second vertex index
  725. int vj = nx + ny * grid.GetHeightCount() + (z + 1) * layer_size;
  726. // Connect to nearby cells
  727. boost::add_edge(vertices[vi], vertices[vj], weight, graph);
  728. }
  729. }
  730. // boost::add_edge(vertices[vi], sink, 0.0, graph);
  731. }
  732. else
  733. {
  734. boost::add_edge(vertices[vi], sink, weight, graph);
  735. }
  736. if (z < 1)
  737. {
  738. // Connect with source
  739. boost::add_edge(source, vertices[vi], 0.0, graph);
  740. }
  741. }
  742. }
  743. }
  744. util::Logger::LogDebug("vertex count " + std::to_string(boost::num_vertices(graph)));
  745. util::Logger::LogDebug("edge count " + std::to_string(boost::num_edges(graph)));
  746. }
  747. void CreatePresentationGraph(DirectedGraph& graph, Vertex& source, Vertex& sink, bool two_paths)
  748. {
  749. std::vector<Vertex> vertices;
  750. if (two_paths)
  751. {
  752. for (size_t i = 0; i < 10; ++i)
  753. {
  754. vertices.push_back(
  755. boost::add_vertex(core::ObjectDataPtr(new core::ObjectData(i)), graph));
  756. }
  757. source = vertices[0];
  758. sink = vertices[9];
  759. boost::add_edge(vertices[0], vertices[1], 1.0, graph);
  760. boost::add_edge(vertices[0], vertices[2], 1.0, graph);
  761. boost::add_edge(vertices[1], vertices[3], 12.0, graph);
  762. boost::add_edge(vertices[1], vertices[4], 15.0, graph);
  763. boost::add_edge(vertices[2], vertices[3], 15.0, graph);
  764. boost::add_edge(vertices[2], vertices[4], 10.0, graph);
  765. boost::add_edge(vertices[3], vertices[5], 15.0, graph);
  766. boost::add_edge(vertices[3], vertices[6], 12.0, graph);
  767. boost::add_edge(vertices[4], vertices[5], 12.0, graph);
  768. boost::add_edge(vertices[4], vertices[6], 11.0, graph);
  769. boost::add_edge(vertices[5], vertices[7], 12.0, graph);
  770. boost::add_edge(vertices[5], vertices[8], 12.0, graph);
  771. boost::add_edge(vertices[6], vertices[7], 11.0, graph);
  772. boost::add_edge(vertices[6], vertices[8], 10.0, graph);
  773. boost::add_edge(vertices[7], vertices[9], 1.0, graph);
  774. boost::add_edge(vertices[8], vertices[9], 1.0, graph);
  775. }
  776. else
  777. {
  778. for (size_t i = 0; i < 14; ++i)
  779. {
  780. vertices.push_back(
  781. boost::add_vertex(core::ObjectDataPtr(new core::ObjectData(i)), graph));
  782. }
  783. source = vertices[0];
  784. sink = vertices[9];
  785. boost::add_edge(vertices[0], vertices[1], 1.0, graph);
  786. boost::add_edge(vertices[0], vertices[2], 1.0, graph);
  787. boost::add_edge(vertices[1], vertices[3], 12.0, graph);
  788. boost::add_edge(vertices[1], vertices[4], 15.0, graph);
  789. boost::add_edge(vertices[2], vertices[3], 15.0, graph);
  790. boost::add_edge(vertices[2], vertices[4], 10.0, graph);
  791. boost::add_edge(vertices[3], vertices[5], 15.0, graph);
  792. boost::add_edge(vertices[3], vertices[6], 12.0, graph);
  793. boost::add_edge(vertices[4], vertices[5], 12.0, graph);
  794. boost::add_edge(vertices[4], vertices[6], 11.0, graph);
  795. boost::add_edge(vertices[5], vertices[7], 12.0, graph);
  796. boost::add_edge(vertices[5], vertices[8], 12.0, graph);
  797. boost::add_edge(vertices[6], vertices[7], 11.0, graph);
  798. boost::add_edge(vertices[6], vertices[8], 10.0, graph);
  799. boost::add_edge(vertices[7], vertices[9], 1.0, graph);
  800. boost::add_edge(vertices[8], vertices[9], 1.0, graph);
  801. boost::add_edge(vertices[0], vertices[10], 20.0, graph);
  802. boost::add_edge(vertices[10], vertices[11], 20.0, graph);
  803. boost::add_edge(vertices[10], vertices[3], 20.0, graph);
  804. boost::add_edge(vertices[10], vertices[4], 20.0, graph);
  805. boost::add_edge(vertices[11], vertices[12], 20.0, graph);
  806. boost::add_edge(vertices[11], vertices[5], 20.0, graph);
  807. boost::add_edge(vertices[12], vertices[6], 20.0, graph);
  808. boost::add_edge(vertices[13], vertices[9], 20.0, graph);
  809. }
  810. }
  811. void CreateSuurballeGraph(DirectedGraph& graph, Vertex& source, Vertex& sink, bool first)
  812. {
  813. std::vector<Vertex> vertices;
  814. if (first)
  815. {
  816. // First example graph
  817. for (int i = 0; i < 7; ++i)
  818. {
  819. vertices.push_back(boost::add_vertex(graph));
  820. }
  821. source = vertices[0];
  822. sink = vertices[6];
  823. boost::add_edge(vertices[0], vertices[1], 5.0, graph);
  824. boost::add_edge(vertices[0], vertices[4], 2.0, graph);
  825. boost::add_edge(vertices[1], vertices[2], 1.0, graph);
  826. boost::add_edge(vertices[1], vertices[4], 1.0, graph);
  827. boost::add_edge(vertices[2], vertices[6], 1.0, graph);
  828. boost::add_edge(vertices[3], vertices[2], 1.0, graph);
  829. boost::add_edge(vertices[4], vertices[3], 2.0, graph);
  830. boost::add_edge(vertices[4], vertices[5], 1.0, graph);
  831. boost::add_edge(vertices[5], vertices[2], 1.0, graph);
  832. boost::add_edge(vertices[5], vertices[6], 1.0, graph);
  833. }
  834. else
  835. {
  836. // Second example graph
  837. for (int i = 0; i < 8; ++i)
  838. {
  839. vertices.push_back(boost::add_vertex(graph));
  840. }
  841. source = vertices[0];
  842. sink = vertices[7];
  843. boost::add_edge(vertices[0], vertices[1], 1.0, graph);
  844. boost::add_edge(vertices[0], vertices[4], 8.0, graph);
  845. boost::add_edge(vertices[0], vertices[5], 1.0, graph);
  846. boost::add_edge(vertices[1], vertices[2], 1.0, graph);
  847. boost::add_edge(vertices[1], vertices[7], 8.0, graph);
  848. boost::add_edge(vertices[2], vertices[3], 1.0, graph);
  849. boost::add_edge(vertices[3], vertices[4], 1.0, graph);
  850. boost::add_edge(vertices[3], vertices[6], 2.0, graph);
  851. boost::add_edge(vertices[4], vertices[7], 1.0, graph);
  852. boost::add_edge(vertices[5], vertices[2], 2.0, graph);
  853. boost::add_edge(vertices[5], vertices[6], 6.0, graph);
  854. boost::add_edge(vertices[6], vertices[7], 1.0, graph);
  855. }
  856. }
  857. void TestYAOKSP()
  858. {
  859. Vertex source, sink;
  860. DirectedGraph graph;
  861. // CreatePresentationGraph(graph, source, sink, true);
  862. CreateSuurballeGraph(graph, source, sink, false);
  863. // CreateBerclazGraph(graph, source, sink);
  864. algo::KShortestPaths ksp(graph, source, sink);
  865. ksp.Run(3);
  866. std::vector<std::vector<Vertex>> paths;
  867. ksp.GetPaths(paths);
  868. for (auto path : paths)
  869. {
  870. std::cout << "path: ";
  871. for (auto v : path)
  872. {
  873. std::cout << std::setw(2) << v << " ";
  874. }
  875. std::cout << std::endl;
  876. }
  877. }
  878. int main(int argc, char const * const * argv)
  879. {
  880. //TODO load with frame offset
  881. //TODO check visualizer for offset errors
  882. //TODO check why SEGFAULT is caused by some berclaz resolutions
  883. Run(argc, argv);
  884. return 0;
  885. }