NStage.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. //
  2. // Created by wrede on 25.04.16.
  3. //
  4. #include "NStage.h"
  5. #include "../util/Logger.h"
  6. #include <boost/graph/dijkstra_shortest_paths.hpp>
  7. namespace algo
  8. {
  9. NStage::NStage(size_t max_frame_skip,
  10. std::vector<double> penalty_value,
  11. std::vector<size_t> max_tracklet_count)
  12. {
  13. max_frame_skip_ = max_frame_skip;
  14. penalty_values_ = penalty_value;
  15. max_tracklet_counts_ = max_tracklet_count;
  16. iterations_ = std::min(max_tracklet_count.size(), penalty_value.size());
  17. }
  18. void NStage::CreateObjectGraph(DirectedGraph& graph,
  19. const core::DetectionSequence& detections)
  20. {
  21. util::Logger::LogInfo("Creating object graph");
  22. std::vector<std::vector<Vertex>> layers;
  23. // Add source as the vertex with the lowest index
  24. Vertex source = boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()), graph);
  25. // Add vertices from detection sequence to directed graph
  26. // Save the vertices which are in one frame/layer for later use to
  27. // link easily between vertices in adjacent frames/layers
  28. for (size_t i = 0; i < detections.GetFrameCount(); ++i)
  29. {
  30. std::vector<Vertex> layer;
  31. for (size_t j = 0; j < detections.GetObjectCount(i); ++j)
  32. {
  33. Vertex v = boost::add_vertex(detections.GetObject(i, j),
  34. graph);
  35. layer.push_back(v);
  36. }
  37. layers.push_back(layer);
  38. }
  39. // Add sink as the vertex with the highest index
  40. Vertex sink = boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()), graph);
  41. // Vertex objects
  42. VertexValueMap values = boost::get(boost::vertex_name, graph);
  43. // Create edges
  44. for (size_t i = 0; i < layers.size(); ++i)
  45. {
  46. // For each edge in this frame/layer
  47. for (size_t j = 0; j < layers[i].size(); ++j)
  48. {
  49. Vertex u = layers[i][j];
  50. // For each next frame/layer until maxFrameSkip or end
  51. for (size_t k = 1;
  52. k != (max_frame_skip_ + 1) && i + k < layers.size();
  53. ++k)
  54. {
  55. // To every edge in the next frame/layer
  56. for (size_t l = 0; l < layers[i + k].size(); ++l)
  57. {
  58. Vertex v = layers[i + k][l];
  59. boost::add_edge(u, v,
  60. values[u]->CompareTo(values[v]),
  61. graph);
  62. }
  63. }
  64. // From source to vertex and from vertex to sink
  65. boost::add_edge(source, u,
  66. (i + 1) * penalty_values_[0],
  67. graph);
  68. boost::add_edge(u, sink,
  69. (layers.size() - i) * penalty_values_[0],
  70. graph);
  71. }
  72. }
  73. util::Logger::LogDebug("vertex count " + std::to_string(boost::num_vertices(graph)));
  74. util::Logger::LogDebug("edge count " + std::to_string(boost::num_edges(graph)));
  75. }
  76. void NStage::CreateTrackletGraph(DirectedGraph& obj_graph,
  77. DirectedGraph& tlt_graph,
  78. size_t frame_count,
  79. size_t iteration)
  80. {
  81. util::Logger::LogInfo("Creating tracklet graph");
  82. // Add source to tracklet graph
  83. Vertex tlt_src = boost::add_vertex(
  84. core::ObjectDataPtr(new core::ObjectData()), tlt_graph);
  85. // Prepare variables for dijkstra
  86. size_t obj_graph_size = boost::num_vertices(obj_graph);
  87. std::vector<Vertex> obj_pred_list(obj_graph_size);
  88. std::vector<double> obj_dist_list(obj_graph_size);
  89. VertexIndexMap obj_indices = boost::get(boost::vertex_index, obj_graph);
  90. VertexValueMap obj_values = boost::get(boost::vertex_name, obj_graph);
  91. PredecessorMap obj_pred_map(&obj_pred_list[0], obj_indices);
  92. DistanceMap obj_dist_map(&obj_dist_list[0], obj_indices);
  93. // Source and sink of the object graph
  94. Vertex obj_src = obj_indices[0];
  95. Vertex obj_snk = obj_indices[obj_graph_size - 1];
  96. // Iteratively run dijkstra to extract tracklets
  97. for (size_t i = 0; i != max_tracklet_counts_[iteration]; ++i)
  98. {
  99. util::Logger::LogDebug("tracklet iteration: " + std::to_string(i));
  100. boost::dijkstra_shortest_paths(obj_graph, obj_src,
  101. boost::predecessor_map(obj_pred_map)
  102. .distance_map(obj_dist_map));
  103. // No path from source to sink could be found
  104. if (obj_dist_map[obj_snk] == std::numeric_limits<double>::max())
  105. {
  106. break;
  107. }
  108. // Create the tracklet
  109. core::TrackletPtr tracklet(new core::Tracklet);
  110. for (Vertex u = obj_pred_map[obj_snk], v = obj_snk;
  111. u != v;
  112. v = u, u = obj_pred_map[v])
  113. {
  114. tracklet->AddPathObject(obj_values[u]);
  115. // Leave source and sink untouched
  116. if (!obj_values[u]->IsVirtual())
  117. {
  118. // Remove the path by setting all used edges to a weight of
  119. // infinity
  120. std::pair<DirectedGraph::out_edge_iterator,
  121. DirectedGraph::out_edge_iterator> edge_iter = boost::out_edges(u, obj_graph);
  122. for (DirectedGraph::out_edge_iterator iter = edge_iter.first;
  123. iter != edge_iter.second;
  124. ++iter)
  125. {
  126. boost::get(boost::edge_weight, obj_graph, *iter)
  127. = std::numeric_limits<double>::infinity();
  128. }
  129. }
  130. }
  131. core::ObjectDataPtr tracklet_base = tracklet;
  132. // Add tracklet into tracklet graph
  133. boost::add_vertex(tracklet_base, tlt_graph);
  134. }
  135. // Add sink to tracklet graph
  136. Vertex tlt_snk =
  137. boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()),
  138. tlt_graph);
  139. util::Logger::LogDebug("adding edges");
  140. // Create edges
  141. size_t tlt_graph_size = boost::num_vertices(tlt_graph);
  142. VertexIndexMap tlt_indices = boost::get(boost::vertex_index, tlt_graph);
  143. VertexValueMap tlt_values = boost::get(boost::vertex_name, tlt_graph);
  144. // For every tracklet but source and sink
  145. for (size_t i = 1; i < tlt_graph_size - 1; ++i)
  146. {
  147. Vertex u = tlt_indices[i];
  148. core::TrackletPtr u_ptr =
  149. std::static_pointer_cast<core::Tracklet>(tlt_values[u]);
  150. size_t u_first_frame = u_ptr->GetFirstFrameIndex();
  151. size_t u_last_frame = u_ptr->GetLastFrameIndex();
  152. // Create edges between tracklets
  153. for (size_t j = 1; j < tlt_graph_size - 1; ++j)
  154. {
  155. if (i != j)
  156. {
  157. Vertex v = tlt_indices[j];
  158. core::TrackletPtr v_ptr =
  159. std::static_pointer_cast<core::Tracklet>(tlt_values[v]);
  160. size_t v_first_frame = v_ptr->GetFirstFrameIndex();
  161. // Link only tracklets that are in temporal order
  162. if (u_last_frame < v_first_frame)
  163. {
  164. boost::add_edge(u, v,
  165. tlt_values[u]->CompareTo(tlt_values[v]),
  166. tlt_graph);
  167. }
  168. }
  169. }
  170. // From source
  171. boost::add_edge(tlt_src, u,
  172. (u_first_frame + 1) * penalty_values_[iteration],
  173. tlt_graph);
  174. // To sink
  175. boost::add_edge(u, tlt_snk,
  176. (frame_count - u_last_frame) * penalty_values_[iteration],
  177. tlt_graph);
  178. }
  179. util::Logger::LogDebug("vertex count " + std::to_string(boost::num_vertices(tlt_graph)));
  180. util::Logger::LogDebug("edge count " + std::to_string(boost::num_edges(tlt_graph)));
  181. }
  182. void NStage::ExtractTracks(DirectedGraph& tlt_graph, size_t depth,
  183. std::vector<core::TrackletPtr>& tracks)
  184. {
  185. util::Logger::LogInfo("Extracting tracks");
  186. VertexValueMap tlt_values = boost::get(boost::vertex_name, tlt_graph);
  187. for (size_t i = 0; i < boost::num_vertices(tlt_graph); ++i)
  188. {
  189. core::ObjectDataPtr obj = tlt_values[i];
  190. if (!obj->IsVirtual())
  191. {
  192. core::TrackletPtr tlt = std::static_pointer_cast<core::Tracklet>(obj);
  193. for (size_t j = 0; j < depth; j++)
  194. {
  195. tlt->Flatten();
  196. }
  197. tracks.push_back(tlt);
  198. }
  199. }
  200. util::Logger::LogDebug("track count " + std::to_string(tracks.size()));
  201. }
  202. void NStage::Run(const core::DetectionSequence& sequence,
  203. std::vector<core::TrackletPtr>& tracks)
  204. {
  205. // Running the two stage graph algorithm
  206. DirectedGraph obj_graph;
  207. CreateObjectGraph(obj_graph, sequence);
  208. // Run the tracklet creation at least once
  209. DirectedGraph tlt_graph_1, tlt_graph_2;
  210. CreateTrackletGraph(obj_graph, tlt_graph_1, sequence.GetFrameCount(), 0);
  211. // Run the tracklet creation iteratively
  212. for (size_t i = 1; i < iterations_; ++i)
  213. {
  214. if (i % 2 == 0)
  215. {
  216. CreateTrackletGraph(tlt_graph_2, tlt_graph_1, sequence.GetFrameCount(), i);
  217. }
  218. else
  219. {
  220. CreateTrackletGraph(tlt_graph_1, tlt_graph_2, sequence.GetFrameCount(), i);
  221. }
  222. }
  223. // Extract tracklets and flatten tracklets
  224. if (iterations_ % 2 == 0)
  225. {
  226. ExtractTracks(tlt_graph_2, iterations_ - 1, tracks);
  227. }
  228. else
  229. {
  230. ExtractTracks(tlt_graph_1, iterations_ - 1, tracks);
  231. }
  232. }
  233. }