Browse Source

added time measurement
berclaz more or less functional

Helge Wrede 9 years ago
parent
commit
c1ffa1b708

+ 3 - 3
CMakeLists.txt

@@ -10,20 +10,20 @@ set(SOURCE_FILES
         main/main.cpp
         core/DetectionSequence.cpp core/DetectionSequence.h
         core/ObjectData.cpp core/ObjectData.h
-        core/ObjectDataMap.cpp core/ObjectDataMap.h
         core/Tracklet.cpp core/Tracklet.h
         util/FileIO.cpp util/FileIO.h
         util/Parser.cpp util/Parser.h
         algo/NStage.cpp algo/NStage.h
         util/MyMath.cpp util/MyMath.h
-        core/ObjectData3D.cpp core/ObjectData3D.h
         util/Visualizer.cpp util/Visualizer.h
         util/Logger.cpp util/Logger.h
         core/ObjectDataAngular.cpp core/ObjectDataAngular.h
         algo/KShortestPaths.cpp algo/KShortestPaths.h
         graph/Definitions.h
         core/ObjectData2D.cpp core/ObjectData2D.h
-        algo/Berclaz.cpp algo/Berclaz.h util/Grid.cpp util/Grid.h core/ObjectDataBox.cpp core/ObjectDataBox.h)
+        algo/Berclaz.cpp algo/Berclaz.h
+        util/Grid.cpp util/Grid.h
+        core/ObjectDataBox.cpp core/ObjectDataBox.h algo/KShortestPaths2.cpp algo/KShortestPaths2.h)
 
 find_package(Doxygen)
 

+ 107 - 60
algo/Berclaz.cpp

@@ -7,6 +7,7 @@
 #include "../util/Parser.h"
 #include "../util/Logger.h"
 #include "../util/FileIO.h"
+#include "KShortestPaths2.h"
 
 namespace algo
 {
@@ -17,44 +18,48 @@ namespace algo
         vicinity_size_ = vicinity_size;
     }
 
-    void Berclaz::CreateGraph(DirectedGraph& graph, Vertex& source, Vertex& sink,
-                              util::Grid& grid)
+    void Berclaz::CreateGraph(DirectedGraph& graph, Vertex& source, Vertex& sink, util::Grid& grid)
     {
-        // Add source vertex
-        source = boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()), graph);
+        util::Logger::LogDebug("add vertices");
 
         // Add grid vertices
-        for (int f = 0; f < grid.GetDepthCount(); ++f)
+        for (int z = 0; z < grid.GetDepthCount(); ++z)
         {
-            for (int y = 0; y < v_res_; ++y)
+            for (int y = 0; y < grid.GetHeightCount(); ++y)
             {
-                for (int x = 0; x < h_res_; ++x)
+                for (int x = 0; x < grid.GetWidthCount(); ++x)
                 {
-                    boost::add_vertex(grid.GetValue(x, y, f), graph);
+                    boost::add_vertex(grid.GetValue(x, y, z), graph);
                 }
             }
         }
 
-        // Add sink vertex
+        util::Logger::LogDebug("vertex count " + std::to_string(boost::num_vertices(graph)));
+        util::Logger::LogDebug("edge count " + std::to_string(boost::num_edges(graph)));
+
+        // Add source and sink vertex
+        source = boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()), graph);
         sink = boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()), graph);
-        
-        // Store the vertex indices
-        VertexIndexMap vertices = boost::get(boost::vertex_index, graph);
 
-        // Store the vertex values
-        VertexValueMap values = boost::get(boost::vertex_name, graph);
+        util::Logger::LogDebug("source index: " + std::to_string(source));
+        util::Logger::LogDebug("sink index: " + std::to_string(sink));
+        util::Logger::LogDebug("add edges");
 
-        util::Logger::LogDebug("num vertices " + std::to_string(boost::num_vertices(graph)));
-        
         // Iterate all vertices but source and sink
-        for (int f = 0; f < grid.GetDepthCount(); ++f)
+        VertexIndexMap vertices = boost::get(boost::vertex_index, graph);
+        VertexValueMap values = boost::get(boost::vertex_name, graph);
+        int layer_size = grid.GetWidthCount() * grid.GetHeightCount();
+        for (int z = 0; z < grid.GetDepthCount(); ++z)
         {
-            for (int y = 0; y < v_res_; ++y)
+            for (int y = 0; y < grid.GetHeightCount(); ++y)
             {
-                for (int x = 0; x < h_res_; ++x)
+                for (int x = 0; x < grid.GetWidthCount(); ++x)
                 {
                     // First vertex index
-                    int vi = x + y * h_res_ + f * h_res_ * v_res_ + 1;
+                    int vi = x + y * grid.GetHeightCount() + z * layer_size;
+
+                    // Get the score, clamp it, prevent division by zero and
+                    // logarithm of zero
                     double score = values[vi]->GetDetectionScore();
                     if (score > MAX_SCORE_VALUE)
                     {
@@ -65,40 +70,54 @@ namespace algo
                         score = MIN_SCORE_VALUE;
                     }
 
-                    // Iterate all nearby cells in the next frame
-                    for (int nx = std::max(0, x - vicinity_size_);
-                         nx < std::min(h_res_, x + vicinity_size_ + 1);
-                         ++nx)
+                    // Calculate the edge weight
+                    double weight = -std::log(score / (1 - score));
+
+                    // Connect with the next frame only if there is a next frame
+                    if (z < grid.GetDepthCount() - 1)
                     {
+                        // Iterate all nearby cells in the next frame
                         for (int ny = std::max(0, y - vicinity_size_);
-                             ny < std::min(v_res_, y + vicinity_size_ + 1);
+                             ny <
+                             std::min(grid.GetHeightCount(),
+                                      y + vicinity_size_ + 1);
                              ++ny)
                         {
-                            // Second vertex index
-                            int vj = nx + ny * h_res_ + (f + 1) * h_res_ * v_res_ + 1;
-
-                            // Connect to nearby cells
-                            double weight = -std::log(score / (1 - score));
-                            boost::add_edge(vertices[vi], vertices[vj],
-                                            weight, graph);
+                            for (int nx = std::max(0, x - vicinity_size_);
+                                 nx < std::min(grid.GetWidthCount(),
+                                               x + vicinity_size_ + 1);
+                                 ++nx)
+                            {
+                                // Second vertex index
+                                int vj = nx + ny * grid.GetHeightCount() +
+                                         (z + 1) * layer_size;
+
+                                // Connect to nearby cells
+                                boost::add_edge(vertices[vi], vertices[vj],
+                                                weight, graph);
+                            }
                         }
+
+                        boost::add_edge(vertices[vi], sink, VIRTUAL_EDGE_WEIGHT,
+                                        graph);
+                    }
+                    else
+                    {
+                        boost::add_edge(vertices[vi], sink, weight, graph);
                     }
-                    
-                    // Connect with source and sink
-                    boost::add_edge(source, vertices[vi],
-                                    VIRTUAL_EDGE_WEIGHT, graph);
 
-                    boost::add_edge(vertices[vi], sink,
-                                    VIRTUAL_EDGE_WEIGHT, graph);
+                    // Connect with source and sink
+                    boost::add_edge(source, vertices[vi], VIRTUAL_EDGE_WEIGHT,
+                                    graph);
                 }
             }
         }
 
-        util::Logger::LogDebug("num edges " + std::to_string(boost::num_edges(graph)));
+        util::Logger::LogDebug("vertex count " + std::to_string(boost::num_vertices(graph)));
+        util::Logger::LogDebug("edge count " + std::to_string(boost::num_edges(graph)));
     }
 
-    void Berclaz::ExtractTracks(DirectedGraph& graph,
-                                MultiPredecessorMap& map, Vertex origin,
+    void Berclaz::ExtractTracks(DirectedGraph& graph, MultiPredecessorMap& map, Vertex origin,
                                 std::vector<core::TrackletPtr>& tracks)
     {
         VertexValueMap values = boost::get(boost::vertex_name, graph);
@@ -121,31 +140,59 @@ namespace algo
     }
 
     void Berclaz::Run(core::DetectionSequence& sequence,
-                      size_t max_track_count,
+                      size_t batch_size, size_t max_track_count,
                       std::vector<core::TrackletPtr>& tracks)
     {
-        Vertex source, sink;
-        DirectedGraph graph;
-        util::Grid grid = util::Parser::ParseGrid(sequence,
-                                                  MIN_H_VALUE,
-                                                  MAX_H_VALUE,
-                                                  h_res_,
-                                                  MIN_V_VALUE,
-                                                  MAX_V_VALUE,
-                                                  v_res_);
+        for (size_t i = 0; i < sequence.GetFrameCount(); i += batch_size)
+        {
+            util::Logger::LogDebug("batch offset: " + std::to_string(i));
 
-        util::Logger::LogDebug("create graph");
-        CreateGraph(graph, source, sink, grid);
+            util::Grid grid = util::Parser::ParseGrid(sequence, i, i + batch_size,
+                                                      0.0, 1.0, h_res_, 0.0, 1.0, v_res_);
 
-        util::FileIO::WriteCSVMatlab(graph, "/home/wrede/Dokumente/graph.csv");
+            util::Logger::LogDebug("create graph");
+            DirectedGraph graph;
+            Vertex source, sink;
+            CreateGraph(graph, source, sink, grid);
 
-        util::Logger::LogDebug("init ksp");
-        KShortestPaths ksp(graph, source, sink);
+            util::Logger::LogDebug("run ksp");
+            KShortestPaths2 ksp;
+            MultiPredecessorMap ksp_result = ksp.Run(graph, source, sink, max_track_count);
 
-        util::Logger::LogDebug("run ksp");
-        MultiPredecessorMap ksp_result = ksp.Run(max_track_count);
+            util::Logger::LogDebug("extract tracks");
+            ExtractTracks(graph, ksp_result, sink, tracks);
+        }
+
+        util::Logger::LogDebug("connect tracks");
+        ConnectTracks(tracks);
+    }
 
-        util::Logger::LogDebug("extract tracks");
-        ExtractTracks(graph, ksp_result, sink, tracks);
+    void Berclaz::ConnectTracks(std::vector<core::TrackletPtr>& tracks)
+    {
+        for (size_t i = 0; i < tracks.size(); ++i)
+        {
+            // find the best matching tracklet
+            double best_value = std::numeric_limits<double>::max();
+            size_t best_index = 0;
+            for (size_t k = i + 1; k < tracks.size(); ++k)
+            {
+                if (tracks[i]->GetLastFrameIndex() < tracks[k]->GetFirstFrameIndex())
+                {
+                    double value = tracks[i]->CompareTo(tracks[k]);
+                    if (value < best_value)
+                    {
+                        best_index = k;
+                    }
+                }
+            }
+
+            // if a match was found
+            if (best_index != 0)
+            {
+                // merge the two tracks
+                tracks[i]->Combine(tracks[best_index]);
+                tracks.erase(tracks.begin() + best_index);
+            }
+        }
     }
 }

+ 14 - 9
algo/Berclaz.h

@@ -16,12 +16,8 @@ namespace algo
     {
     private:
         const double VIRTUAL_EDGE_WEIGHT = 0.0;
-        const double MAX_SCORE_VALUE = 0.9999999999;
-        const double MIN_SCORE_VALUE = 0.0000000001;
-        const double MIN_H_VALUE = 0.0;
-        const double MAX_H_VALUE = 1.0;
-        const double MIN_V_VALUE = 0.0;
-        const double MAX_V_VALUE = 1.0;
+        const double MAX_SCORE_VALUE = 0.999999;
+        const double MIN_SCORE_VALUE = 0.000001;
 
         /**
          * Horizontal grid resolution
@@ -40,6 +36,7 @@ namespace algo
 
         /**
          * Creates a graph from the given sequence.
+         *
          * @param graph The graph to write into
          * @param source A reference to the source vertex
          * @param sink A reference to the sink vertex
@@ -50,6 +47,7 @@ namespace algo
 
         /**
          * Extracts the final tracks from the given graph and predecessor map.
+         *
          * @param graph The graph to read the values from
          * @param map The predecessor map to read the paths from
          * @param origin The vertex to start the reverse path traversal from
@@ -58,9 +56,13 @@ namespace algo
         void ExtractTracks(DirectedGraph& graph,
                            MultiPredecessorMap& map, Vertex origin,
                            std::vector<core::TrackletPtr>& tracks);
+
+        //TODO comment
+        void ConnectTracks(std::vector<core::TrackletPtr>& tracks);
     public:
         /**
          * Instantiate with the given parameters.
+         *
          * @param h_res The horizontal grid resolution
          * @param v_res The vertical grid resolution
          * @param vicinity_size The maximum number of cells a detection can skip
@@ -69,13 +71,16 @@ namespace algo
         Berclaz(int h_res, int v_res, int vicinity_size);
 
         /**
-         * Runs the algorithm on the given sequence.
+         * Runs the algorithm on the given sequence. Splits the sequence into
+         * batches to allow faster processing.
+         *
          * @param sequence The detection to use
+         * @param batch_size The number of frames one batch will have at maximum
          * @param max_track_count The maximum number of tracks to extract
          * @param tracks The vector to store the found tracks into
          */
-        void Run(core::DetectionSequence& sequence, size_t max_track_count,
-                 std::vector<core::TrackletPtr>& tracks);
+        void Run(core::DetectionSequence& sequence, size_t batch_size,
+                 size_t max_track_count, std::vector<core::TrackletPtr>& tracks);
     };
 }
 

+ 83 - 63
algo/KShortestPaths.cpp

@@ -23,17 +23,18 @@ namespace algo
         // Clear all data from previous runs
         i_shortest_paths_.clear();
 
-        util::Logger::LogDebug("find shortest path #1");
+        util::Logger::LogDebug("find shortest path #0");
 
         util::Logger::LogDebug("find");
-        FindAndAugmentPath(1, true);
+        FindAndAugmentPath(0, true);
 
         // Find the k shortest paths
-        for (size_t i = 1; i < max_path_count; ++i)
+        for (size_t i = 0; i < max_path_count - 1; ++i)
         {
-            if (i != 1)
+            if (i > 0)
             {
-                //If the costs are increasing, no further shortest paths will be found
+                // If the costs are increasing, no further shortest paths will
+                // be found
                 if (OverallCosts(i) > OverallCosts(i - 1))
                 {
                     return i_shortest_paths_[i];
@@ -47,13 +48,32 @@ namespace algo
             // for the graph and edge transformations
             CopyOriginalGraph();
 
+            util::FileIO::WriteCSVMatlab(copied_graph_,
+                                         "/home/wrede/Dokumente/graph_" +
+                                         std::to_string(i) + "_c.csv");
+
             util::Logger::LogDebug("extend");
             // Extend the graph (has negative and positive edge weights)
             ExtendGraph(i);
 
+            util::FileIO::WriteCSVMatlab(copied_graph_,
+                                         "/home/wrede/Dokumente/graph_" +
+                                         std::to_string(i) + "_e.csv");
+
             util::Logger::LogDebug("transform");
             // Transforms the edge costs (has only positive edge weights)
-            TransformEdgeCosts(i);
+            if (i > 0)
+            {
+                TransformEdgeCosts(i - 1, false);
+            }
+            else
+            {
+                TransformEdgeCosts(0, true);
+            }
+
+            util::FileIO::WriteCSVMatlab(copied_graph_,
+                                         "/home/wrede/Dokumente/graph_" +
+                                         std::to_string(i) + "_t.csv");
 
             util::Logger::LogDebug("find");
             // Finds the next path and adds it to the found paths
@@ -65,7 +85,7 @@ namespace algo
         }
 
         // All k shortest paths have been found
-        return i_shortest_paths_[max_path_count];
+        return i_shortest_paths_[max_path_count - 1];
     }
 
     void KShortestPaths::ExtendGraph(size_t i)
@@ -79,7 +99,11 @@ namespace algo
         for (boost::tie(vi, vi_end) = boost::vertices(original_graph_);
              vi != vi_end; ++vi)
         {
+            // Create a copy of each vertex for easy index matching with
+            // preceding and succeeding iterations
             Vertex v_original = (*vi);
+            Vertex v_in = original_to_copy_[v_original];
+            Vertex v_out = boost::add_vertex(graph_values[v_in], copied_graph_);
 
             // Ignore vertices off the paths, the source and the sink
             if (i_shortest_paths_[i].count(v_original) == 0 ||
@@ -88,8 +112,6 @@ namespace algo
                 continue;
             }
 
-            Vertex v_in = original_to_copy_[v_original];
-            Vertex v_out = boost::add_vertex(graph_values[v_in], copied_graph_);
             copy_to_original_[v_out] = v_original;
 
             // Copy outgoing edges to v_out
@@ -107,8 +129,8 @@ namespace algo
                 QueueRemoveEdge(v_in, boost::target(*oei, copied_graph_));
             }
 
-            // Create auxiliary edge
-            QueueAddEdge(v_in, v_out, 0.0);
+            // Create auxiliary edge (inverted -> won't be iterated in the next step)
+            QueueAddEdge(v_out, v_in, 0.0);
         }
 
         UpdateEdges();
@@ -137,6 +159,9 @@ namespace algo
         }
 
         UpdateEdges();
+
+        util::Logger::LogDebug("num vertices original " + std::to_string(boost::num_vertices(original_graph_)));
+        util::Logger::LogDebug("num vertices copy " + std::to_string(boost::num_vertices(copied_graph_)));
     }
 
     double KShortestPaths::OverallCosts(size_t i)
@@ -160,6 +185,11 @@ namespace algo
             }
         }
 
+//        for (size_t cost_i = 0; cost_i <= i; ++cost_i)
+//        {
+//            value += i_distances_[cost_i][sink_];
+//        }
+
         util::Logger::LogDebug("cost in " + std::to_string(i) + " : " + std::to_string(value));
 
         return value;
@@ -238,7 +268,7 @@ namespace algo
         }
 
         // Only copy old paths if old paths exist
-        if (i > 1)
+        if (i > 0)
         {
             // Copy the old paths
             for (auto it = i_shortest_paths_[i - 1].begin();
@@ -252,7 +282,6 @@ namespace algo
         {
             // Prepare variables for path finding
             size_t graph_size = boost::num_vertices(original_graph_);
-            Vertex root_vertex = source_;
             std::vector<Vertex> pred_list(graph_size);
             std::vector<double> dist_list(graph_size);
             VertexIndexMap graph_indices = boost::get(boost::vertex_index,
@@ -265,7 +294,7 @@ namespace algo
             // Find the shortest path
             boost::bellman_ford_shortest_paths(original_graph_,
                                                graph_size,
-                                               boost::root_vertex(root_vertex)
+                                               boost::root_vertex(source_)
                                                        .weight_map(weight_map)
                                                        .predecessor_map(pred_map)
                                                        .distance_map(dist_map));
@@ -287,34 +316,26 @@ namespace algo
 
                 ++path_length;
             }
+
             util::Logger::LogDebug("path length " + std::to_string(path_length));
         }
         else
         {
             // Prepare variables for path finding
             size_t graph_size = boost::num_vertices(copied_graph_);
-            Vertex root_vertex = original_to_copy_[source_];
             std::vector<Vertex> pred_list(graph_size);
             std::vector<double> dist_list(graph_size);
             VertexIndexMap graph_indices = boost::get(boost::vertex_index,
                                                       copied_graph_);
-            EdgeWeightMap weight_map = boost::get(boost::edge_weight,
-                                                     copied_graph_);
             PredecessorMap pred_map(&pred_list[0], graph_indices);
             DistanceMap dist_map(&dist_list[0], graph_indices);
 
             // Find the shortest path
-            boost::dijkstra_shortest_paths(copied_graph_, root_vertex,
+            boost::dijkstra_shortest_paths(copied_graph_,
+                                           original_to_copy_[source_],
                                            boost::predecessor_map(pred_map)
                                                    .distance_map(dist_map));
 
-//            boost::bellman_ford_shortest_paths(copied_graph_,
-//                                               graph_size,
-//                                               boost::root_vertex(root_vertex)
-//                                                       .weight_map(weight_map)
-//                                                       .predecessor_map(pred_map)
-//                                                       .distance_map(dist_map));
-
             util::Logger::LogDebug("add the path");
 
             // Add the new distances
@@ -323,22 +344,15 @@ namespace algo
                  vi != vi_end; ++vi)
             {
                 Vertex v_copy = *vi;
-                Vertex v_orig = copy_to_original_[v_copy];
-                i_distances_[i][v_orig] = dist_map[v_copy];
-            }
 
-            // Prevent cycles
-//            unsigned long vertex_count = boost::num_vertices(original_graph_);
-//            bool* visited = new bool[vertex_count];
-//            for (unsigned long j = 0; j < vertex_count; j++)
-//            {
-//                visited[j] = false;
-//            }
+                i_distances_[i][v_copy] = dist_map[v_copy];
+            }
 
             // Add the new path (the given path is in the copied graph, so the
             // vertices need to be mapped to the original graph)
             size_t path_length = 0;
             Vertex sink_copy = original_to_copy_[sink_];
+            std::cout << sink_;
             for (Vertex u_copy = sink_copy, v_copy = pred_map[u_copy];
                  u_copy != v_copy; u_copy = v_copy, v_copy = pred_map[v_copy])
             {
@@ -351,54 +365,60 @@ namespace algo
                     continue;
                 }
 
-                // Cycle found
-//                if (visited[u_original])
-//                {
-//                    break;
-//                }
-//
-//                visited[u_original] = true;
-
+                std::cout << "->" << v_original;
                 i_shortest_paths_[i][u_original].insert(v_original);
-                i_distances_[i][u_original] = dist_map[u_copy];
 
                 ++path_length;
             }
-            util::Logger::LogDebug("path length " + std::to_string(path_length));
+            std::cout << std::endl;
 
-//            delete[] visited;
+            util::Logger::LogDebug("path length " + std::to_string(path_length));
         }
 
         // Add source
         i_shortest_paths_[i][source_].insert(source_);
     }
 
-    void KShortestPaths::TransformEdgeCosts(size_t i)
+    void KShortestPaths::TransformEdgeCosts(size_t i, bool original)
     {
         EdgeWeightMap weights = boost::get(boost::edge_weight, copied_graph_);
         boost::graph_traits<DirectedGraph>::edge_iterator ei, ei_end;
-        double min_weight = 0.0;
 
-        for (boost::tie(ei, ei_end) = boost::edges(copied_graph_);
-             ei != ei_end; ++ei)
+        if (original)
         {
-            Vertex s_copy = boost::source(*ei, copied_graph_);
-            Vertex t_copy = boost::target(*ei, copied_graph_);
-            Vertex s_orig = copy_to_original_[s_copy];
-            Vertex t_orig = copy_to_original_[t_copy];
-
-            weights[*ei] += i_distances_[i][s_orig] - i_distances_[i][t_orig];
-
-            if (weights[*ei] < min_weight)
+            for (boost::tie(ei, ei_end) = boost::edges(copied_graph_);
+                 ei != ei_end; ++ei)
             {
-                min_weight = weights[*ei];
+                Vertex s_copy = boost::source(*ei, copied_graph_);
+                Vertex t_copy = boost::target(*ei, copied_graph_);
+                Vertex s_orig = copy_to_original_[s_copy];
+                Vertex t_orig = copy_to_original_[t_copy];
+
+                if (i_distances_[i].count(s_orig) > 0 &&
+                        i_distances_[i].count(t_orig) > 0)
+                {
+                    weights[*ei] +=
+                            i_distances_[i][s_orig] - i_distances_[i][t_orig];
+                    util::Logger::LogDebug(std::to_string(weights[*ei]));
+                }
             }
         }
-
-        for (boost::tie(ei, ei_end) = boost::edges(copied_graph_);
-             ei != ei_end; ++ei)
+        else
         {
-            weights[*ei] -= min_weight;
+            for (boost::tie(ei, ei_end) = boost::edges(copied_graph_);
+                 ei != ei_end; ++ei)
+            {
+                Vertex s_copy = boost::source(*ei, copied_graph_);
+                Vertex t_copy = boost::target(*ei, copied_graph_);
+
+                if (i_distances_[i].count(s_copy) > 0 &&
+                        i_distances_[i].count(t_copy) > 0)
+                {
+                    weights[*ei] +=
+                            i_distances_[i][s_copy] - i_distances_[i][t_copy];
+                    util::Logger::LogDebug(std::to_string(weights[*ei]));
+                }
+            }
         }
     }
 

+ 2 - 2
algo/KShortestPaths.h

@@ -52,7 +52,7 @@ namespace algo
         std::unordered_map<Vertex, Vertex> copy_to_original_;
 
         /**
-         * Maps the vertices in the original graph to the distances of the
+         * Maps the vertices in the i-th copied graph to the distances of the
          * shortest path found in the i-th iteration.
          */
         std::vector<std::unordered_map<Vertex, double>> i_distances_;
@@ -79,7 +79,7 @@ namespace algo
         void ExtendGraph(size_t i);
 
         //TODO comment
-        void TransformEdgeCosts(size_t i);
+        void TransformEdgeCosts(size_t i, bool original);
 
         /**
          * Calculates the path costs of every path at the iteration given.

+ 450 - 0
algo/KShortestPaths2.cpp

@@ -0,0 +1,450 @@
+//
+// Created by wrede on 15.06.16.
+//
+
+#include <boost/graph/copy.hpp>
+#include <boost/graph/bellman_ford_shortest_paths.hpp>
+#include <boost/graph/dijkstra_shortest_paths.hpp>
+#include "KShortestPaths2.h"
+#include "../util/Logger.h"
+#include "../util/FileIO.h"
+
+namespace algo
+{
+    void KShortestPaths2::CreateCopy()
+    {
+        util::Logger::LogDebug("create copy");
+
+        // Clear all previous data
+        graph_copy_.clear();
+        orig_to_copy_.clear();
+        copy_to_orig_.clear();
+        in_to_out_.clear();
+        out_to_in_.clear();
+
+        // Copy the graph and store the vertex map temporarily
+        std::vector<Vertex> original_to_copy_vector(boost::num_vertices(graph_orig_));
+        VertexVertexMap temp_map(original_to_copy_vector.begin());
+        boost::copy_graph(graph_orig_, graph_copy_, boost::orig_to_copy(temp_map));
+
+        // Copy the vertex map into the two persistent maps, one for each
+        // mapping direction
+        boost::graph_traits<DirectedGraph>::vertex_iterator vi, vi_end;
+        for (boost::tie(vi, vi_end) = boost::vertices(graph_orig_);
+             vi != vi_end; ++vi)
+        {
+            Vertex v_original = (*vi);
+            Vertex v_copy = temp_map[v_original];
+
+            orig_to_copy_[v_original] = v_copy;
+            copy_to_orig_[v_copy] = v_original;
+        }
+
+        // Split every vertex in the copied graph
+        for (boost::tie(vi, vi_end) = boost::vertices(graph_orig_);
+             vi != vi_end; ++vi)
+        {
+            Vertex v_orig = *vi;
+            Vertex v_copy_in = orig_to_copy_[v_orig];
+            Vertex v_copy_out = boost::add_vertex(graph_copy_);
+
+            in_to_out_[v_copy_in] = v_copy_out;
+            out_to_in_[v_copy_out] = v_copy_in;
+            copy_to_orig_[v_copy_out] = v_orig;
+        }
+    }
+
+    void KShortestPaths2::UpdateEdges()
+    {
+        // Remove the old edges, needs to be done without any iterator since
+        // the removal invalidates any iterators
+        for (auto edge : edges_to_remove_)
+        {
+            boost::remove_edge(edge.first, edge.second, graph_copy_);
+        }
+        edges_to_remove_.clear();
+
+        // Add the new edges, needs to be done without any iterator since
+        // the addition invalidates any iterators
+        for (auto edge : edges_to_add_)
+        {
+            boost::add_edge(edge.first.first, edge.first.second,
+                            edge.second, graph_copy_);
+        }
+        edges_to_add_.clear();
+    }
+
+    void KShortestPaths2::QueueAddEdge(Vertex source, Vertex target, double weight)
+    {
+        edges_to_add_.push_back(
+                std::pair<std::pair<Vertex, Vertex>, double>(
+                        std::pair<Vertex, Vertex>(source, target), weight));
+    }
+
+    void KShortestPaths2::QueueRemoveEdge(Vertex source, Vertex target)
+    {
+        edges_to_remove_.push_back(std::pair<Vertex, Vertex>(source, target));
+    }
+
+    void KShortestPaths2::QueueCopyEdges()
+    {
+        EdgeWeightMap weights = boost::get(boost::edge_weight, graph_orig_);
+        boost::graph_traits<DirectedGraph>::edge_iterator ei, ei_end;
+        for (boost::tie(ei, ei_end) = boost::edges(graph_orig_);
+             ei != ei_end; ++ei)
+        {
+            Vertex s_orig = boost::source(*ei, graph_orig_);
+            Vertex t_orig = boost::target(*ei, graph_orig_);
+            Vertex s_copy = orig_to_copy_[s_orig];
+            Vertex t_copy = orig_to_copy_[t_orig];
+            double weight = weights[*ei];
+            QueueAddEdge(s_copy, t_copy, weight);
+        }
+    }
+
+    void KShortestPaths2::QueueRemoveAll()
+    {
+        boost::graph_traits<DirectedGraph>::edge_iterator ei, ei_end;
+        for (boost::tie(ei, ei_end) = boost::edges(graph_copy_);
+             ei != ei_end; ++ei)
+        {
+            Vertex s_copy = boost::source(*ei, graph_copy_);
+            Vertex t_copy = boost::target(*ei, graph_copy_);
+            QueueRemoveEdge(s_copy, t_copy);
+        }
+    }
+
+    MultiPredecessorMap KShortestPaths2::Run(DirectedGraph& graph_orig,
+                                             Vertex source, Vertex sink,
+                                             size_t iterations)
+    {
+        // Clear all previous data
+        edges_to_add_.clear();
+        edges_to_remove_.clear();
+        i_distances_.clear();
+        i_paths_.clear();
+
+        graph_orig_ = graph_orig;
+        source_ = source;
+        sink_ = sink;
+
+        CreateCopy();
+        FindAndAugment(0);
+        for (size_t i = 0; i < iterations; ++i)
+        {
+            util::Logger::LogDebug("ksp iteration: " + std::to_string(i));
+
+            if (i > 0)
+            {
+                if (PathCosts(i) >= PathCosts(i - 1))
+                {
+                    return i_paths_[i];
+                }
+            }
+
+            ExtendGraph(i);
+            i > 0 ? TransformEdges(i - 1) : TransformEdges(0);
+            FindAndAugment(i + 1);
+            Interlace(i + 1);
+        }
+
+        return i_paths_[iterations];
+    }
+
+    void KShortestPaths2::ExtendGraph(size_t iteration)
+    {
+        util::Logger::LogDebug("extend graph iteration: " + std::to_string(iteration));
+
+        // Clear all previous working data
+        util::Logger::LogDebug("remove all");
+        QueueRemoveAll();
+        util::Logger::LogDebug("copy all");
+        QueueCopyEdges();
+        util::Logger::LogDebug("update edges");
+        UpdateEdges();
+
+        util::Logger::LogDebug("iterate vertices");
+        MultiPredecessorMap& paths = i_paths_[iteration];
+        boost::graph_traits<DirectedGraph>::out_edge_iterator oei, oei_end;
+        boost::graph_traits<DirectedGraph>::edge_iterator ei, ei_end;
+        boost::graph_traits<DirectedGraph>::vertex_iterator vi, vi_end;
+        EdgeWeightMap weights = boost::get(boost::edge_weight, graph_copy_);
+
+        // Iterate all vertices within the original graph
+        for (boost::tie(vi, vi_end) = boost::vertices(graph_orig_);
+             vi != vi_end; ++vi)
+        {
+            Vertex v_orig = *vi;
+
+            // Ignore vertices off the paths, the source and the sink
+            if (paths.count(v_orig) == 0 || v_orig == source_ || v_orig == sink_)
+            {
+                continue;
+            }
+
+            Vertex v_copy_in = orig_to_copy_[v_orig];
+            Vertex v_copy_out = in_to_out_[v_copy_in];
+
+            // Iterate all input vertices
+            for (boost::tie(oei, oei_end) = boost::out_edges(v_copy_in, graph_copy_);
+                 oei != oei_end; ++oei)
+            {
+                // Copy the output edges to the output vertices
+                QueueAddEdge(v_copy_out,
+                             boost::target(*oei, graph_copy_),
+                             weights[*oei]);
+
+                // Remove the old output edge
+                QueueRemoveEdge(v_copy_in, boost::target(*oei, graph_copy_));
+            }
+
+            // Create auxiliary edge
+            // Is already inverted, because it will not be iterated later
+            QueueAddEdge(v_copy_out, v_copy_in, 0.0);
+        }
+
+        util::Logger::LogDebug("update edges");
+        UpdateEdges();
+
+        util::Logger::LogDebug("iterate edges");
+        // Iterate all edges within the copied graph
+        weights = boost::get(boost::edge_weight, graph_copy_);
+        for (boost::tie(ei, ei_end) = boost::edges(graph_copy_);
+             ei != ei_end; ++ei)
+        {
+            Vertex s_copy = boost::source(*ei, graph_copy_);
+            Vertex t_copy = boost::target(*ei, graph_copy_);
+            Vertex s_orig = copy_to_orig_[s_copy];
+            Vertex t_orig = copy_to_orig_[t_copy];
+            double weight = weights[*ei];
+
+            // If the edge is part of the paths
+            if (paths.count(t_orig) > 0 && paths[t_orig].count(s_orig) > 0)
+            {
+                // Add the edge with direction and weight inverted
+                QueueAddEdge(t_copy, s_copy, -weight);
+
+                // Remove the old edge
+                QueueRemoveEdge(s_copy, t_copy);
+            }
+        }
+
+        util::Logger::LogDebug("update edges");
+        UpdateEdges();
+    }
+
+    void KShortestPaths2::TransformEdges(size_t iteration)
+    {
+        util::Logger::LogDebug("transform edges iteration: " + std::to_string(iteration));
+
+        std::unordered_map<Vertex, double>& distances = i_distances_[iteration];
+
+        EdgeWeightMap weights = boost::get(boost::edge_weight, graph_copy_);
+        boost::graph_traits<DirectedGraph>::edge_iterator ei, ei_end;
+        for (boost::tie(ei, ei_end) = boost::edges(graph_copy_);
+             ei != ei_end; ++ei)
+        {
+            Vertex s_copy = boost::source(*ei, graph_copy_);
+            Vertex t_copy = boost::target(*ei, graph_copy_);
+
+            // Transform the edge weights with the distances calculated in
+            // the specified path finding iteration
+            if (distances.count(s_copy) > 0 && distances.count(t_copy) > 0)
+            {
+                //TODO set all edges to source to zero (experimental)
+                if (t_copy == orig_to_copy_[source_]) {
+                    weights[*ei] = 0.0;
+                    continue;
+                }
+
+                // check if the vertex was found in previous iterations
+                if (distances[s_copy] == std::numeric_limits<double>::max() ||
+                        distances[t_copy] == std::numeric_limits<double>::max())
+                {
+                    weights[*ei] = std::numeric_limits<double>::infinity();
+                }
+                else
+                {
+                    weights[*ei] += distances[s_copy] - distances[t_copy];
+                }
+            }
+
+            // Correct rounding errors
+            if (weights[*ei] >= -0.0000001 && weights[*ei] <= 0.0000001)
+            {
+                weights[*ei] = 0.0;
+            }
+
+            //TODO debug output (experimental)
+            if (weights[*ei] < 0.0)
+            {
+                util::Logger::LogDebug(std::to_string(s_copy)
+                                       + " -> " + std::to_string(weights[*ei])
+                                       + " -> " + std::to_string(t_copy));
+            }
+        }
+
+//        util::FileIO::WriteCSVMatlab(graph_copy_, "/home/wrede/Dokumente/graph_t.csv");
+    }
+
+    void KShortestPaths2::FindAndAugment(size_t iteration)
+    {
+        util::Logger::LogDebug("find and augment iteration: " + std::to_string(iteration));
+
+        // Add new path maps until the needed iteration is reached
+        while (i_paths_.size() < (iteration + 1))
+        {
+            i_paths_.push_back(MultiPredecessorMap());
+        }
+
+        // Add new distance maps until the needed iteration is reached
+        while (i_distances_.size() < (iteration + 1))
+        {
+            i_distances_.push_back(std::unordered_map<Vertex, double>());
+        }
+
+        // Only copy old paths if old paths exist
+        if (iteration > 0)
+        {
+            // Copy the old paths
+            for (auto it = i_paths_[iteration - 1].begin();
+                 it != i_paths_[iteration - 1].end(); ++it)
+            {
+                i_paths_[iteration][it->first] = it->second;
+            }
+        }
+
+        // Prepare variables for path finding
+        size_t graph_size = boost::num_vertices(graph_copy_);
+        Vertex root_vertex = orig_to_copy_[source_];
+        std::vector<Vertex> pred_list(graph_size);
+        std::vector<double> dist_list(graph_size);
+        VertexIndexMap graph_indices = boost::get(boost::vertex_index,
+                                                  graph_copy_);
+        EdgeWeightMap weight_map = boost::get(boost::edge_weight,
+                                              graph_copy_);
+        PredecessorMap pred_map(&pred_list[0], graph_indices);
+        DistanceMap dist_map(&dist_list[0], graph_indices);
+
+        // Find the shortest path
+        if (iteration == 0)
+        {
+            boost::bellman_ford_shortest_paths(graph_copy_,
+                                               graph_size,
+                                               boost::root_vertex(root_vertex)
+                                                       .weight_map(weight_map)
+                                                       .predecessor_map(pred_map)
+                                                       .distance_map(dist_map));
+        }
+        else
+        {
+            boost::dijkstra_shortest_paths(graph_copy_,
+                                           root_vertex,
+                                           boost::predecessor_map(pred_map)
+                                                   .distance_map(dist_map));
+        }
+
+        // Add the new distances
+        boost::graph_traits<DirectedGraph>::vertex_iterator vi, vi_end;
+        for (boost::tie(vi, vi_end) = boost::vertices(graph_copy_);
+             vi != vi_end; ++vi)
+        {
+            i_distances_[iteration][*vi] = dist_map[*vi];
+        }
+
+        // Add the new path (the given path is in the copied graph, so the
+        // vertices need to be mapped to the original graph)
+        Vertex sink_copy = orig_to_copy_[sink_];
+        for (Vertex u_copy = sink_copy, v_copy = pred_map[u_copy];
+             u_copy != v_copy; u_copy = v_copy, v_copy = pred_map[v_copy])
+        {
+            Vertex u_orig = copy_to_orig_[u_copy];
+            Vertex v_orig = copy_to_orig_[v_copy];
+
+            // Ignore loops
+            // Loops are caused by mapping the input and output vertices in the
+            // copied graph to the same vertex in the original graph
+            if (u_orig == v_orig)
+            {
+                continue;
+            }
+
+            i_paths_[iteration][u_orig].insert(v_orig);
+        }
+    }
+
+    void KShortestPaths2::Interlace(size_t iteration)
+    {
+        util::Logger::LogDebug("interlace iteration: " + std::to_string(iteration));
+
+        MultiPredecessorMap& paths = i_paths_[iteration];
+
+        boost::graph_traits<DirectedGraph>::edge_iterator ei, ei_end;
+        for (boost::tie(ei, ei_end) = boost::edges(graph_orig_);
+             ei != ei_end; ++ei)
+        {
+            Vertex s_orig = boost::source(*ei, graph_orig_);
+            Vertex t_orig = boost::target(*ei, graph_orig_);
+
+            // Ignore source and sink
+            if (s_orig == source_ || t_orig == sink_)
+            {
+                continue;
+            }
+
+            // Is edge within paths?
+            if (paths.count(t_orig) > 0 && paths.count(s_orig) > 0)
+            {
+                // Is edge duplicate?
+                if (paths.count(s_orig) > 0 && paths[s_orig].count(t_orig) > 0)
+                {
+                    paths[t_orig].erase(s_orig);
+                    paths[s_orig].erase(t_orig);
+                }
+            }
+        }
+    }
+
+    double KShortestPaths2::PathCosts(size_t iteration)
+    {
+        util::Logger::LogDebug("path costs iteration: " + std::to_string(iteration));
+
+        MultiPredecessorMap& paths = i_paths_[iteration];
+        double value = 0.0;
+
+//        EdgeWeightMap weights = boost::get(boost::edge_weight, graph_orig_);
+//        boost::graph_traits<DirectedGraph>::edge_iterator ei, ei_end;
+//        for (boost::tie(ei, ei_end) = boost::edges(graph_orig_);
+//             ei != ei_end; ++ei)
+//        {
+//            Vertex s_orig = boost::source(*ei, graph_orig_);
+//            Vertex t_orig = boost::target(*ei, graph_orig_);
+//
+//            // If the edge is on the path, add the edge weight to the overall
+//            // path costs
+//            if (paths.count(t_orig) > 0 && paths[t_orig].count(s_orig) > 0)
+//            {
+//                value += weights[*ei];
+//            }
+//        }
+
+        for (int i = 0; i < iteration; ++i)
+        {
+            value += i_distances_[i][orig_to_copy_[sink_]];
+        }
+
+        util::Logger::LogDebug("calculated costs: " + std::to_string(value));
+
+        return value;
+    }
+
+    KShortestPaths2::KShortestPaths2()
+    {
+        /* EMPTY */
+    }
+
+    KShortestPaths2::~KShortestPaths2()
+    {
+        /* EMPTY */
+    }
+}

+ 50 - 0
algo/KShortestPaths2.h

@@ -0,0 +1,50 @@
+//
+// Created by wrede on 15.06.16.
+//
+
+#ifndef GBMOT_KSHORTESTPATHS2_H
+#define GBMOT_KSHORTESTPATHS2_H
+
+#include "../graph/Definitions.h"
+
+namespace algo
+{
+    class KShortestPaths2
+    {
+    private:
+        DirectedGraph graph_orig_;
+        DirectedGraph graph_copy_;
+        Vertex source_;
+        Vertex sink_;
+        std::unordered_map<Vertex, Vertex> orig_to_copy_;
+        std::unordered_map<Vertex, Vertex> copy_to_orig_;
+        std::unordered_map<Vertex, Vertex> in_to_out_;
+        std::unordered_map<Vertex, Vertex> out_to_in_;
+        std::vector<std::pair<std::pair<Vertex, Vertex>, double>> edges_to_add_;
+        std::vector<std::pair<Vertex, Vertex>> edges_to_remove_;
+        std::vector<std::unordered_map<Vertex, double>> i_distances_;
+        std::vector<MultiPredecessorMap> i_paths_;
+
+        void CreateCopy();
+        void ExtendGraph(size_t iteration);
+        void TransformEdges(size_t iteration);
+        void FindAndAugment(size_t iteration);
+        void Interlace(size_t iteration);
+        double PathCosts(size_t iteration);
+
+        void QueueCopyEdges();
+        void QueueRemoveAll();
+        void QueueRemoveEdge(Vertex source, Vertex target);
+        void QueueAddEdge(Vertex source, Vertex target, double weight);
+        void UpdateEdges();
+    public:
+        KShortestPaths2();
+        ~KShortestPaths2();
+        MultiPredecessorMap Run(DirectedGraph& graph_orig,
+                                Vertex source, Vertex sink,
+                                size_t iterations);
+    };
+}
+
+
+#endif //GBMOT_KSHORTESTPATHS2_H

+ 5 - 0
algo/NStage.cpp

@@ -118,10 +118,13 @@ namespace algo
         // Iteratively run dijkstra to extract tracklets
         for (size_t i = 0; i != max_tracklet_counts_[iteration]; ++i)
         {
+            util::Logger::LogDebug("tracklet iteration: " + std::to_string(i));
+
             boost::dijkstra_shortest_paths(obj_graph, obj_src,
                                            boost::predecessor_map(obj_pred_map)
                                                    .distance_map(obj_dist_map));
 
+            // No path from source to sink could be found
             if (obj_dist_map[obj_snk] == std::numeric_limits<double>::max())
             {
                 break;
@@ -163,6 +166,8 @@ namespace algo
                 boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()),
                                   tlt_graph);
 
+        util::Logger::LogDebug("adding edges");
+
         // Create edges
         size_t tlt_graph_size = boost::num_vertices(tlt_graph);
         VertexIndexMap tlt_indices = boost::get(boost::vertex_index, tlt_graph);

+ 0 - 1
core/DetectionSequence.h

@@ -8,7 +8,6 @@
 
 #include <string>
 #include "ObjectData.h"
-#include "ObjectDataMap.h"
 
 namespace core
 {

+ 0 - 89
core/ObjectData3D.cpp

@@ -1,89 +0,0 @@
-//
-// Created by wrede on 04.05.16.
-//
-
-#include "ObjectData3D.h"
-#include "../util/MyMath.h"
-
-namespace core
-{
-    ObjectData3D::ObjectData3D(size_t frame_index, cv::Point3d position)
-            : ObjectData(frame_index),
-              position_(position),
-              temporal_weight_(1.0),
-              spatial_weight_(1.0)
-    {
-    }
-
-    void ObjectData3D::SetTemporalWeight(double weight)
-    {
-        temporal_weight_ = weight;
-    }
-
-    void ObjectData3D::SetSpatialWeight(double weight)
-    {
-        spatial_weight_ = weight;
-    }
-
-    cv::Point3d ObjectData3D::GetPosition() const
-    {
-        return position_;
-    }
-
-    double ObjectData3D::GetTemporalWeight() const
-    {
-        return temporal_weight_;
-    }
-
-    double ObjectData3D::GetSpatialWeight() const
-    {
-        return spatial_weight_;
-    }
-
-    double ObjectData3D::CompareTo(ObjectDataPtr obj) const
-    {
-        ObjectData3DPtr obj_3d = std::static_pointer_cast<ObjectData3D>(obj);
-
-        double d_temp = obj_3d->GetFrameIndex() - GetFrameIndex();
-        double d_spat = util::MyMath::EuclideanDistance(position_, obj_3d->position_);
-
-        return d_temp * temporal_weight_ + d_spat * spatial_weight_;
-    }
-
-    ObjectDataPtr ObjectData3D::Interpolate(ObjectDataPtr obj,
-                                            double fraction) const
-    {
-        ObjectDataPtr obj_in = ObjectData::Interpolate(obj, fraction);
-
-        ObjectData3DPtr obj_3d = std::static_pointer_cast<ObjectData3D>(obj);
-
-        double x = util::MyMath::Lerp(position_.x, obj_3d->position_.x, fraction);
-        double y = util::MyMath::Lerp(position_.y, obj_3d->position_.y, fraction);
-        double z = util::MyMath::Lerp(position_.z, obj_3d->position_.z, fraction);
-
-        ObjectData3DPtr obj_out(
-                new ObjectData3D(obj_in->GetFrameIndex(), cv::Point3d(x, y, z)));
-
-        return obj_out;
-    }
-
-    void ObjectData3D::Print(std::ostream& os) const
-    {
-        os << "ObjectData3D{"
-           << "frame: " << GetFrameIndex() << ","
-           << "x: " << position_.x << ","
-           << "y: " << position_.y << ","
-           << "z: " << position_.z << "}";
-    }
-
-    void ObjectData3D::Visualize(cv::Mat& image, cv::Scalar& color) const
-    {
-        double x = position_.x * image.cols;
-        double y = position_.y * image.rows;
-        int r = (int) (0.005 * (image.rows + image.cols) * 0.5);
-
-        cv::circle(image, cv::Point2d(x, y), r, color);
-    }
-}
-
-

+ 0 - 86
core/ObjectData3D.h

@@ -1,86 +0,0 @@
-//
-// Created by wrede on 04.05.16.
-//
-
-#ifndef GBMOT_OBJECTDATA3D_H
-#define GBMOT_OBJECTDATA3D_H
-
-#include "ObjectData.h"
-#include <opencv2/opencv.hpp>
-
-namespace core
-{
-    class ObjectData3D;
-    typedef std::shared_ptr<ObjectData3D> ObjectData3DPtr;
-
-    /**
-     * Class for storing a detection in three dimensional space.
-     */
-    class ObjectData3D : public ObjectData
-    {
-    private:
-        /**
-         * The position in the three dimensional space
-         */
-        cv::Point3d position_;
-
-        /**
-         * The weight of the temporal distance for the comparison.
-         * The temporal distance is the frame difference.
-         */
-        double temporal_weight_;
-
-        /**
-         * The weight of the spatial distance for the comparison.
-         * The spatial distance is the euclidean distance of the positions.
-         */
-        double spatial_weight_;
-
-        virtual void Print(std::ostream& os) const override;
-    public:
-        /**
-         * Creates a new detection with the given index and position.
-         * @param frame_index The frame index
-         * @param position The position in three dimensional space
-         */
-        ObjectData3D(size_t frame_index, cv::Point3d position);
-
-        /**
-         * Sets the temporal weight.
-         * @param weight The temporal weight
-         */
-        void SetTemporalWeight(double weight);
-
-        /**
-         * Sets the spatial weight
-         * @param weight The spatial weight
-         */
-        void SetSpatialWeight(double weight);
-
-        /**
-         * Gets the position in three dimensional space.
-         * @return The position
-         */
-        cv::Point3d GetPosition() const;
-
-        /**
-         * Gets the temporal weight.
-         * @return The temporal weight
-         */
-        double GetTemporalWeight() const;
-
-        /**
-         * Gets the spatial weight
-         * @return The spatial weight
-         */
-        double GetSpatialWeight() const;
-
-        virtual double CompareTo(ObjectDataPtr obj) const override;
-        virtual ObjectDataPtr Interpolate(ObjectDataPtr obj,
-                                          double fraction) const override;
-        virtual void Visualize(cv::Mat& image, cv::Scalar& color) const override;
-    };
-}
-
-
-#endif //GBMOT_OBJECTDATA3D_H

+ 0 - 141
core/ObjectDataMap.cpp

@@ -1,141 +0,0 @@
-//
-// Created by wrede on 22.04.16.
-//
-
-#include "ObjectDataMap.h"
-#include "../util/MyMath.h"
-
-namespace core
-{
-    void ObjectDataMap::Print(std::ostream& os) const
-    {
-        os << "ObjectDataMap{frame:" << GetFrameIndex();
-
-        for (auto it = value_weight_map_.begin(); it != value_weight_map_.end(); ++it)
-        {
-            os << "," << it->first
-            << ":" << it->second.first
-            << "*" << it->second.second;
-        }
-
-        os << "}";
-    }
-
-    ObjectDataMap::ObjectDataMap(size_t frame_index)
-            : ObjectData(frame_index)
-    {
-        value_weight_map_ = std::unordered_map<std::string, std::pair<double, double>>();
-    }
-
-    ObjectDataMap::ObjectDataMap(size_t frame_index,
-                                 std::vector<std::string> keys,
-                                 std::vector<double> value_list)
-            : ObjectDataMap(frame_index)
-    {
-        double weight = 1.0 / value_list.size();
-
-        for (size_t i = 0; i < value_list.size() && i < keys.size(); ++i)
-        {
-            value_weight_map_[keys[i]] = std::make_pair(value_list[i], weight);
-        }
-    }
-
-    ObjectDataMap::ObjectDataMap(size_t frame_index,
-                                 std::vector<std::string> keys,
-                                 std::vector<double> value_list,
-                                 std::vector<double> weight_list)
-            : ObjectDataMap(frame_index)
-    {
-        for (size_t i = 0;
-             i < value_list.size() && i < keys.size() && i < weight_list.size();
-             ++i)
-        {
-            value_weight_map_[keys[i]] = std::make_pair(value_list[i], weight_list[i]);
-        }
-    }
-
-    ObjectDataMap::ObjectDataMap(size_t frame_index,
-                                 std::vector<std::string> keys,
-                                 std::vector<std::pair<double, double>> value_weight_list)
-            : ObjectDataMap(frame_index)
-    {
-        for (size_t i = 0; i < value_weight_list.size() && i < keys.size(); ++i)
-        {
-            value_weight_map_[keys[i]] = value_weight_list[i];
-        }
-    }
-
-    double ObjectDataMap::GetValue(std::string key)
-    {
-        return value_weight_map_[key].first;
-    }
-
-    double ObjectDataMap::GetWeight(std::string key)
-    {
-        return value_weight_map_[key].second;
-    }
-
-    void ObjectDataMap::Put(std::string key, double value,
-                            double weight)
-    {
-        value_weight_map_[key] = std::make_pair(value, weight);
-    }
-
-    void ObjectDataMap::Put(std::string key,
-                            std::pair<double, double> value_weight)
-    {
-        value_weight_map_[key] = value_weight;
-    }
-
-    double ObjectDataMap::CompareTo(ObjectDataPtr obj) const
-    {
-        ObjectDataMapPtr obj_map = std::static_pointer_cast<ObjectDataMap>(obj);
-
-        double diff = 0.0;
-
-        for (auto it = value_weight_map_.begin(); it != value_weight_map_.end(); ++it)
-        {
-            // |other_value - this_value| * this_weight;
-            diff += fabs(obj_map->value_weight_map_[it->first].first - it->second.first)
-                    * it->second.second;
-        }
-
-        return diff;
-    }
-
-    ObjectDataPtr ObjectDataMap::Interpolate(ObjectDataPtr obj,
-                                          double fraction) const
-    {
-        ObjectDataMapPtr obj_map = std::static_pointer_cast<ObjectDataMap>(obj);
-
-        fraction = util::MyMath::Clamp(0.0, 1.0, fraction);
-
-        double frame_index = util::MyMath::Lerp(GetFrameIndex(),
-                                              obj_map->GetFrameIndex(),
-                                              fraction);
-
-        ObjectDataMapPtr obj_out(new ObjectDataMap(static_cast<size_t>(fabs(frame_index))));
-
-        // Interpolate all values but leave the weights untouched
-        for (auto iter = value_weight_map_.begin();
-             iter != value_weight_map_.end();
-             ++iter)
-        {
-            obj_out->Put(
-                    iter->first,
-                    util::MyMath::Lerp(iter->second.first,
-                                     obj_map->value_weight_map_[iter->first].first,
-                                     fraction),
-                    iter->second.second
-            );
-        }
-
-        return obj_out;
-    }
-
-    void ObjectDataMap::Visualize(cv::Mat& image, cv::Scalar& color) const
-    {
-        ObjectData::Visualize(image, color);
-    }
-}
-

+ 0 - 118
core/ObjectDataMap.h

@@ -1,118 +0,0 @@
-//
-// Created by wrede on 22.04.16.
-//
-
-#ifndef GBMOT_OBJECTDATAMAP_H
-#define GBMOT_OBJECTDATAMAP_H
-
-#include <string>
-#include <unordered_map>
-#include <vector>
-#include <cmath>
-#include "ObjectData.h"
-
-namespace core
-{
-    class ObjectDataMap;
-    typedef std::shared_ptr<ObjectDataMap> ObjectDataMapPtr;
-
-    //TODO RENAME
-    /**
-     * Stores a map of key-value-weight pairs.
-     * The weight is used to compare this object with other objects.
-     */
-    class ObjectDataMap : public ObjectData
-    {
-    private:
-        /**
-         * The stored value-weight-pairs.
-         */
-        std::unordered_map<std::string, std::pair<double, double>> value_weight_map_;
-
-        virtual void Print(std::ostream& os) const;
-    public:
-        /**
-         * Creates a new empty object data map.
-         * @param frame_index The index of the frame this object was detected in
-         */
-        ObjectDataMap(size_t frame_index);
-
-        /**
-         * Creates a object data map with the given keys and values and an
-         * equal weight for every value.
-         * @param frame_index The index of the frame this object was detected in
-         * @param keys The keys for the values to store
-         * @param value_list The values to store with the given keys
-         */
-        ObjectDataMap(
-                size_t frame_index,
-                std::vector<std::string> keys,
-                std::vector<double> value_list);
-
-        /**
-         * Creates a object data map with the given keys and values and an
-         * given weight for the corresponding key-value pair.
-         * @param frame_index The index of the frame this object was detected in
-         * @param keys The keys for the values to store
-         * @param value_list The values to store with the given keys
-         * @param weight_list The weights to store with the given key-value pairs
-         */
-        ObjectDataMap(
-                size_t frame_index,
-                std::vector<std::string> keys,
-                std::vector<double> value_list,
-                std::vector<double> weight_list);
-
-        /**
-         * Creates a object data map with the given keys and value-weight pairs.
-         * @param frame_index The index of the frame this object was detected in
-         * @param keys The keys for the values to store
-         * @param value_weight_list The value-weight-pairs to store with the keys
-         */
-        ObjectDataMap(
-                size_t frame_index,
-                std::vector<std::string> keys,
-                std::vector<std::pair<double, double>> value_weight_list);
-
-        /**
-         * Gets the value of the given key.
-         * @param key The key for the value
-         * @return The value
-         */
-        double GetValue(std::string key);
-
-        /**
-         * Gets the weight of the given key.
-         * @param key The key for the value
-         * @return The weight
-         */
-        double GetWeight(std::string key);
-
-        //TODO RENAME
-        /**
-         * Stores the given value-weight pair with the given key.
-         * If the key is already stored it will be overridden with the new pair.
-         * @param key The key to store the value-weight pair at
-         * @param value The value of the value-weight pair
-         * @param weight The weight of the value-weight pair
-         */
-        void Put(std::string key, double value, double weight);
-
-        /**
-         * Stores the given value-weight pair with the given key.
-         * If the key is already stored it will be overridden with the new pair.
-         * @param key The key to store the value-weight pair at
-         * @param value_weight The value-weight pair
-         */
-        void Put(std::string key, std::pair<double, double> value_weight);
-
-        virtual double CompareTo(ObjectDataPtr obj) const override;
-
-        virtual ObjectDataPtr Interpolate(ObjectDataPtr obj, double fraction) const override;
-
-        virtual void Visualize(cv::Mat& image, cv::Scalar& color) const override;
-    };
-}
-
-
-#endif //GBMOT_OBJECTDATAMAP_H

+ 8 - 0
core/Tracklet.cpp

@@ -164,6 +164,14 @@ namespace core
         SetFrameIndex(path_objects_.front()->GetFrameIndex());
         last_frame_index_ = path_objects_.back()->GetFrameIndex();
     }
+
+    void Tracklet::Combine(TrackletPtr other)
+    {
+        for (auto obj : other->path_objects_)
+        {
+            AddPathObject(obj);
+        }
+    }
 }
 
 

+ 2 - 0
core/Tracklet.h

@@ -112,6 +112,8 @@ namespace core
          * removed.
          */
         void Flatten();
+
+        void Combine(TrackletPtr other);
     };
 }
 

+ 1 - 1
graph/Definitions.h

@@ -25,7 +25,7 @@ typedef boost::property_map<DirectedGraph, boost::vertex_name_t>::type
         VertexValueMap;
 typedef boost::iterator_property_map<Vertex*, VertexIndexMap, Vertex, Vertex&>
         PredecessorMap;
-typedef std::map<Vertex, std::set<Vertex>> MultiPredecessorMap;
+typedef std::unordered_map<Vertex, std::set<Vertex>> MultiPredecessorMap;
 typedef boost::iterator_property_map<double*, VertexIndexMap, double, double&>
         DistanceMap;
 typedef boost::iterator_property_map<

+ 239 - 110
main/main.cpp

@@ -10,6 +10,7 @@
 #include "../util/Logger.h"
 #include "../core/ObjectDataAngular.h"
 #include "../algo/Berclaz.h"
+#include "../algo/KShortestPaths2.h"
 #include <boost/program_options.hpp>
 
 struct
@@ -20,9 +21,7 @@ struct
 } n_stage_params;
 
 void RunNStage(core::DetectionSequence& sequence,
-               const std::string& output_file,
-               const std::string& images_folder,
-               bool display)
+               std::vector<core::TrackletPtr>& tracks)
 {
     util::Logger::LogInfo("Running n-stage");
 
@@ -67,7 +66,6 @@ void RunNStage(core::DetectionSequence& sequence,
     algo::NStage n_stage(n_stage_params.max_frame_skip,
                          penalty_values, max_tracklet_counts);
 
-    std::vector<core::TrackletPtr> tracks;
     n_stage.Run(sequence, tracks);
 
     // Interpolate tracks
@@ -76,13 +74,6 @@ void RunNStage(core::DetectionSequence& sequence,
         track->InterpolateMissingFrames();
     }
 
-    // Display the tracking data
-    if (display)
-    {
-        util::Visualizer vis;
-        vis.Display(tracks, images_folder);
-    }
-
     util::Logger::LogInfo("Finished");
 }
 
@@ -91,14 +82,13 @@ struct
     int h_res;
     int v_res;
     int vicinity_size;
+    size_t batch_size;
     size_t max_track_count;
 } berclaz_params;
 
 
 void RunBerclaz(core::DetectionSequence& sequence,
-                const std::string& output_file,
-                const std::string& images_folder,
-                bool display)
+                std::vector<core::TrackletPtr>& tracks)
 {
     util::Logger::LogInfo("Running berclaz");
 
@@ -106,8 +96,8 @@ void RunBerclaz(core::DetectionSequence& sequence,
     algo::Berclaz berclaz(berclaz_params.h_res,
                           berclaz_params.v_res,
                           berclaz_params.vicinity_size);
-    std::vector<core::TrackletPtr> tracks;
-    berclaz.Run(sequence, berclaz_params.max_track_count, tracks);
+    berclaz.Run(sequence, berclaz_params.batch_size,
+                berclaz_params.max_track_count, tracks);
 
     util::Logger::LogInfo("Interpolate tracks");
 
@@ -117,13 +107,6 @@ void RunBerclaz(core::DetectionSequence& sequence,
         track->InterpolateMissingFrames();
     }
 
-    // Display the tracking data
-    if (display)
-    {
-        util::Visualizer vis;
-        vis.Display(tracks, images_folder);
-    }
-
     util::Logger::LogInfo("Finished");
 }
 
@@ -134,7 +117,8 @@ void Run(int argc, char** argv)
     bool info, debug, display;
 
     // Input dependent variables
-    std::string header;
+    std::string header, input_format;
+    char input_delimiter;
     double temporal_weight, spatial_weight, angular_weight;
     double image_width, image_height;
 
@@ -157,13 +141,13 @@ void Run(int argc, char** argv)
             ("config",
              boost::program_options::value<std::string>(&config_path),
              "the path to the config file, if no path is given the command line arguments are read")
-            ("input-file,i",
+            ("input-file",
              boost::program_options::value<std::string>(&input_file),
              "set detections file path")
-            ("output-file,o",
+            ("output-file",
              boost::program_options::value<std::string>(&output_file),
              "set the output file path")
-            ("images-folder,f",
+            ("images-folder",
              boost::program_options::value<std::string>(&images_folder),
              "set images folder path")
             ("input-header",
@@ -171,7 +155,24 @@ void Run(int argc, char** argv)
                     ->default_value(""),
              "sets the input header, this value is optional if the input file has a header labeling the values,"
                      "the delimiter used for the header needs to be the same as for the rest of the file")
-            ("algorithm,a",
+            ("image-width",
+             boost::program_options::value<double>(&image_width)
+                     ->default_value(1),
+             "the width of the image")
+            ("image-height",
+             boost::program_options::value<double>(&image_height)
+                     ->default_value(1),
+             "the height of the image")
+            ("input-format",
+             boost::program_options::value<std::string>(&input_format)
+                     ->default_value("ObjectData"),
+             "the format the input should be parsed into, valid formats are: "
+                     "2D, Box, Angular")
+            ("input-delimiter",
+             boost::program_options::value<char>(&input_delimiter)
+                     ->default_value(';'),
+             "the delimiter used to separate values in the specified input file")
+            ("algorithm",
              boost::program_options::value<std::string>(&algorithm),
              "set the algorithm to use, current viable options: n-stage berclaz")
             ("max-frame-skip",
@@ -215,14 +216,10 @@ void Run(int argc, char** argv)
              boost::program_options::value<size_t>(&berclaz_params.max_track_count)
                      ->default_value(1),
              "(berclaz) the maximal number of tracks to extract")
-            ("image-width",
-             boost::program_options::value<double>(&image_width)
-                    ->default_value(1920),
-             "the width of the image")
-            ("image-height",
-             boost::program_options::value<double>(&image_height)
-                     ->default_value(1080),
-             "the height of the image");
+            ("batch-size",
+             boost::program_options::value<size_t>(&berclaz_params.batch_size)
+                     ->default_value(100),
+             "(berclaz) the size of one processing batch");
 
     boost::program_options::variables_map opt_var_map;
 #pragma clang diagnostic push
@@ -243,12 +240,29 @@ void Run(int argc, char** argv)
     // Read config
     if (opt_var_map.count("config") != 0)
     {
-        std::ifstream config_file(config_path , std::ifstream::in);
-        boost::program_options::store(
-                boost::program_options::parse_config_file(config_file , opts),
-                opt_var_map);
-        config_file.close();
-        boost::program_options::notify(opt_var_map);
+        std::ifstream config_file(config_path, std::ifstream::in);
+
+        if (config_file.is_open())
+        {
+            boost::program_options::store(
+                    boost::program_options::parse_config_file(config_file,
+                                                              opts),
+                    opt_var_map);
+            config_file.close();
+            boost::program_options::notify(opt_var_map);
+        }
+        else
+        {
+            util::Logger::LogError("Unable to open config file!");
+            exit(0);
+        }
+    }
+    else if (opt_var_map.count("input-file") == 0 ||
+             opt_var_map.count("input-format") == 0 ||
+             opt_var_map.count("output-file") == 0)
+    {
+        std::cout << opts << std::endl;
+        exit(0);
     }
 
     // Enable info logging
@@ -268,35 +282,92 @@ void Run(int argc, char** argv)
     // Reading the input file
     util::Logger::LogInfo("Reading input");
     util::ValueMapVector values;
-    if (header.size() > 0)
+    try
     {
-        util::FileIO::ReadCSV(values, header, input_file);
+        if (header.size() > 0)
+        {
+            util::FileIO::ReadCSV(values, header, input_file, input_delimiter);
+        }
+        else
+        {
+            util::FileIO::ReadCSV(values, input_file, input_delimiter);
+        }
     }
-    else
+    catch (std::exception& e)
     {
-        util::FileIO::ReadCSV(values, input_file);
+        util::Logger::LogError("Failed to read input file!");
+        util::Logger::LogError(e.what());
+        exit(0);
     }
 
     // Parsing the read input
     core::DetectionSequence sequence;
-    util::Parser::ParseObjectDataBox(values, sequence,
-                                     image_width, image_height,
-                                     temporal_weight, spatial_weight);
+    if (input_format == "2D")
+    {
+        util::Parser::ParseObjectData2D(values,
+                                        sequence,
+                                        image_width,
+                                        image_height,
+                                        temporal_weight,
+                                        spatial_weight);
+    }
+    else if (input_format == "Box")
+    {
+        util::Parser::ParseObjectDataBox(values,
+                                         sequence,
+                                         image_width,
+                                         image_height,
+                                         temporal_weight,
+                                         spatial_weight);
+    }
+    else if (input_format == "Angular")
+    {
+        util::Parser::ParseObjectDataAngular(values,
+                                             sequence,
+                                             image_width,
+                                             image_height,
+                                             temporal_weight,
+                                             spatial_weight,
+                                             angular_weight);
+    }
+    else
+    {
+        // No valid input-format specified
+        std::cout << opts << std::endl;
+        exit(0);
+    }
 
     // Running the specified algorithm
+    std::vector<core::TrackletPtr> tracks;
+    time_t begin_time, end_time;
+    util::Logger::LogInfo("Start time measurement");
+    begin_time = time(0);
     if (algorithm == "n-stage")
     {
-        RunNStage(sequence, output_file, images_folder, display);
+        RunNStage(sequence, tracks);
     }
     else if (algorithm == "berclaz")
     {
-        RunBerclaz(sequence, output_file, images_folder, display);
+        RunBerclaz(sequence, tracks);
     }
     else
     {
+        // No valid algorithm specified
         std::cout << opts << std::endl;
         exit(0);
     }
+    end_time = time(0);
+    util::Logger::LogInfo("Time measurement stopped");
+    util::Logger::LogInfo("Time passed: "
+                          + std::to_string(difftime(end_time, begin_time))
+                          + " seconds");
+
+    // Display the tracking data
+    if (display)
+    {
+        util::Visualizer vis;
+        vis.Display(tracks, images_folder);
+    }
 }
 
 void CreateTestGraph(DirectedGraph& graph, Vertex& source, Vertex& sink)
@@ -312,24 +383,31 @@ void CreateTestGraph(DirectedGraph& graph, Vertex& source, Vertex& sink)
 //
 //    // AB
 //    boost::add_edge(vertices[0], vertices[1], 1.0, graph);
+//    boost::add_edge(vertices[1], vertices[0], 1.0, graph);
 //
 //    // AC
 //    boost::add_edge(vertices[0], vertices[2], 2.0, graph);
+//    boost::add_edge(vertices[2], vertices[0], 2.0, graph);
 //
 //    // BD
 //    boost::add_edge(vertices[1], vertices[3], 1.0, graph);
+//    boost::add_edge(vertices[3], vertices[1], 1.0, graph);
 //
 //    // BE
 //    boost::add_edge(vertices[1], vertices[4], 2.0, graph);
+//    boost::add_edge(vertices[4], vertices[1], 2.0, graph);
 //
 //    // CD
 //    boost::add_edge(vertices[2], vertices[3], 2.0, graph);
+//    boost::add_edge(vertices[3], vertices[2], 2.0, graph);
 //
 //    // DF
 //    boost::add_edge(vertices[3], vertices[5], 1.0, graph);
+//    boost::add_edge(vertices[5], vertices[3], 1.0, graph);
 //
 //    // EF
 //    boost::add_edge(vertices[4], vertices[5], 2.0, graph);
+//    boost::add_edge(vertices[5], vertices[4], 2.0, graph);
 //
 //    source = vertices[0];
 //    sink = vertices[5];
@@ -343,29 +421,73 @@ void CreateTestGraph(DirectedGraph& graph, Vertex& source, Vertex& sink)
                         core::ObjectDataPtr(new core::ObjectData(i)),graph));
     }
 
-    boost::add_edge(vertices[0], vertices[1], 1.0, graph);
-    boost::add_edge(vertices[0], vertices[8], 1.0, graph);
-    boost::add_edge(vertices[0], vertices[4], 1.0, graph);
-    boost::add_edge(vertices[1], vertices[2], 2.0, graph);
-    boost::add_edge(vertices[1], vertices[5], 1.0, graph);
-    boost::add_edge(vertices[2], vertices[3], 1.0, graph);
-    boost::add_edge(vertices[2], vertices[6], 2.0, graph);
-    boost::add_edge(vertices[2], vertices[10], 2.0, graph);
-    boost::add_edge(vertices[3], vertices[7], 1.0, graph);
-    boost::add_edge(vertices[4], vertices[2], 1.0, graph);
-    boost::add_edge(vertices[4], vertices[5], 2.0, graph);
-    boost::add_edge(vertices[4], vertices[9], 2.0, graph);
-    boost::add_edge(vertices[5], vertices[6], 1.0, graph);
-    boost::add_edge(vertices[5], vertices[3], 2.0, graph);
-    boost::add_edge(vertices[6], vertices[7], 1.0, graph);
-    boost::add_edge(vertices[8], vertices[2], 2.0, graph);
-    boost::add_edge(vertices[8], vertices[9], 1.0, graph);
-    boost::add_edge(vertices[9], vertices[3], 2.0, graph);
-    boost::add_edge(vertices[9], vertices[10], 1.0, graph);
-    boost::add_edge(vertices[10], vertices[7], 1.0, graph);
+//    boost::add_edge(vertices[0], vertices[1], 0.0, graph);
+//    boost::add_edge(vertices[0], vertices[8], 0.0, graph);
+//    boost::add_edge(vertices[0], vertices[4], 0.0, graph);
+//    boost::add_edge(vertices[1], vertices[2], -1.0, graph);
+//    boost::add_edge(vertices[1], vertices[5], -1.0, graph);
+//    boost::add_edge(vertices[2], vertices[3], -1.0, graph);
+//    boost::add_edge(vertices[2], vertices[6], -1.0, graph);
+//    boost::add_edge(vertices[2], vertices[10], -1.0, graph);
+//    boost::add_edge(vertices[3], vertices[7], 4.0, graph);
+//    boost::add_edge(vertices[4], vertices[2], 1.0, graph);
+//    boost::add_edge(vertices[4], vertices[5], 1.0, graph);
+//    boost::add_edge(vertices[4], vertices[9], 1.0, graph);
+//    boost::add_edge(vertices[5], vertices[6], 2.0, graph);
+//    boost::add_edge(vertices[5], vertices[3], 2.0, graph);
+//    boost::add_edge(vertices[6], vertices[7], 4.0, graph);
+//    boost::add_edge(vertices[8], vertices[2], -3.0, graph);
+//    boost::add_edge(vertices[8], vertices[9], -3.0, graph);
+//    boost::add_edge(vertices[9], vertices[3], 3.0, graph);
+//    boost::add_edge(vertices[9], vertices[10], 3.0, graph);
+//    boost::add_edge(vertices[10], vertices[7], 4.0, graph);
 
     source = vertices[0];
-    sink = vertices[7];
+    sink = vertices[10];
+
+    for (int i = 1; i < vertices.size() - 1; ++i)
+    {
+        boost::add_edge(source, vertices[i], 0.0, graph);
+        boost::add_edge(vertices[i], sink, 0.0, graph);
+    }
+
+    boost::add_edge(vertices[1], vertices[4], -1.0, graph);
+    boost::add_edge(vertices[1], vertices[5], -1.0, graph);
+    boost::add_edge(vertices[4], vertices[7], -1.0, graph);
+    boost::add_edge(vertices[4], vertices[8], -1.0, graph);
+//    boost::add_edge(vertices[7], vertices[10], -1.0, graph);
+
+    boost::add_edge(vertices[2], vertices[4], -2.0, graph);
+    boost::add_edge(vertices[2], vertices[5], -2.0, graph);
+    boost::add_edge(vertices[2], vertices[6], -2.0, graph);
+    boost::add_edge(vertices[5], vertices[7], -2.0, graph);
+    boost::add_edge(vertices[5], vertices[8], -2.0, graph);
+    boost::add_edge(vertices[5], vertices[9], -2.0, graph);
+//    boost::add_edge(vertices[8], vertices[10], -2.0, graph);
+
+    boost::add_edge(vertices[3], vertices[5], -3.0, graph);
+    boost::add_edge(vertices[3], vertices[6], -3.0, graph);
+    boost::add_edge(vertices[6], vertices[8], -3.0, graph);
+    boost::add_edge(vertices[6], vertices[9], -3.0, graph);
+//    boost::add_edge(vertices[9], vertices[10], -3.0, graph);
+
+
+//     Connect all with source and sink
+//    boost::add_edge(vertices[1], sink, 0, graph);
+//    boost::add_edge(source, vertices[2], 0, graph);
+//    boost::add_edge(vertices[2], sink, 0, graph);
+//    boost::add_edge(source, vertices[3], 0, graph);
+//    boost::add_edge(vertices[4], sink, 0, graph);
+//    boost::add_edge(source, vertices[5], 0, graph);
+//    boost::add_edge(vertices[5], sink, 0, graph);
+//    boost::add_edge(source, vertices[6], 0, graph);
+//    boost::add_edge(vertices[8], sink, 0, graph);
+//    boost::add_edge(source, vertices[9], 0, graph);
+//    boost::add_edge(vertices[9], sink, 0, graph);
+//    boost::add_edge(source, vertices[10], 0, graph);
+
+//    boost::add_edge(vertices[1], vertices[7], 0.0, graph);
+//    boost::add_edge(vertices[8], vertices[7], 0.0, graph);
 }
 
 void TestKSP()
@@ -378,12 +500,12 @@ void TestKSP()
 
     CreateTestGraph(graph, source, sink);
 
-    algo::KShortestPaths ksp(graph, source, sink);
-    MultiPredecessorMap paths = ksp.Run(5);
+    algo::KShortestPaths2 ksp;
+    MultiPredecessorMap paths = ksp.Run(graph, source, sink, 10);
 
     util::FileIO::WriteCSVMatlab(graph, "/home/wrede/Dokumente/graph.csv");
-    util::FileIO::WriteCSVMatlab(paths,
-                                 sink, "/home/wrede/Dokumente/paths.csv");
+    util::FileIO::WriteCSVMatlab(paths, source, sink,
+                                 "/home/wrede/Dokumente/paths.csv");
 }
 
 void TestGrid()
@@ -449,7 +571,9 @@ void TestGrid()
 
 void TestBerclazGraph()
 {
-    std::cout << "init\n";
+    util::Logger::SetDebug(true);
+    util::Logger::SetInfo(true);
+    util::Logger::LogInfo("Test berclaz graph");
 
     // Init grid with data
     util::Grid grid(3, 3, 3, 9.0, 9.0, 9.0);
@@ -476,7 +600,7 @@ void TestBerclazGraph()
     value2->SetDetectionScore(1.0);
     grid.SetValue(value2, 0, 0, 2);
 
-    // Add path source->1,1,0->1,1,0->1,1,2->sink
+    // Add path source->0,1,0->0,1,1->0,1,2->sink
     core::ObjectDataPtr value3(new core::ObjectData(4));
     value3->SetDetectionScore(0.6);
     grid.SetValue(value3, 0, 1, 0);
@@ -487,18 +611,18 @@ void TestBerclazGraph()
     value5->SetDetectionScore(0.6);
     grid.SetValue(value5, 0, 1, 2);
 
-    // Add path source->2,2,0->2,2,0->2,2,2->sink
+    // Add path source->0,2,0->0,2,1->0,2,2->sink
     core::ObjectDataPtr value6(new core::ObjectData(7));
-    value6->SetDetectionScore(0.3);
+    value6->SetDetectionScore(0.55);
     grid.SetValue(value6, 0, 2, 0);
     core::ObjectDataPtr value7(new core::ObjectData(8));
-    value7->SetDetectionScore(0.3);
+    value7->SetDetectionScore(0.55);
     grid.SetValue(value7, 0, 2, 1);
     core::ObjectDataPtr value8(new core::ObjectData(9));
-    value8->SetDetectionScore(0.3);
+    value8->SetDetectionScore(0.55);
     grid.SetValue(value8, 0, 2, 2);
 
-    std::cout << "add vertices\n";
+    util::Logger::LogDebug("add vertices");
 
     // Add grid vertices
     DirectedGraph graph;
@@ -513,14 +637,14 @@ void TestBerclazGraph()
         }
     }
 
-    std::cout << "vertex count = " << boost::num_vertices(graph) << std::endl;
-    std::cout << "edge count = " << boost::num_edges(graph) << std::endl;
+    util::Logger::LogDebug("vertex count " + std::to_string(boost::num_vertices(graph)));
+    util::Logger::LogDebug("edge count " + std::to_string(boost::num_edges(graph)));
 
     // Add source and sink vertex
     Vertex source = boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()), graph);
     Vertex sink = boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()), graph);
 
-    std::cout << "add edges\n";
+    util::Logger::LogDebug("add edges");
 
     // Iterate all vertices but source and sink
     VertexIndexMap vertices = boost::get(boost::vertex_index, graph);
@@ -536,24 +660,24 @@ void TestBerclazGraph()
                 // First vertex index
                 int vi = x + y * grid.GetHeightCount() + z * layer_size;
 
-                // Connect with the next frame only if there is a next frame
-                if (z < grid.GetDepthCount() - 1)
+                // Get the score, clamp it, prevent division by zero and
+                // logarithm of zero
+                double score = values[vi]->GetDetectionScore();
+                if (score > 0.999999)
                 {
-                    // Get the score, clamp it, prevent division by zero and
-                    // logarithm of zero
-                    double score = values[vi]->GetDetectionScore();
-                    if (score > 0.999999)
-                    {
-                        score = 0.999999;
-                    }
-                    else if (score < 0.000001)
-                    {
-                        score = 0.000001;
-                    }
+                    score = 0.999999;
+                }
+                else if (score < 0.000001)
+                {
+                    score = 0.000001;
+                }
 
-                    // Calculate the edge weight
-                    double weight = -std::log(score / (1 - score));
+                // Calculate the edge weight
+                double weight = -std::log(score / (1 - score));
 
+                // Connect with the next frame only if there is a next frame
+                if (z < grid.GetDepthCount() - 1)
+                {
                     // Iterate all nearby cells in the next frame
                     for (int ny = std::max(0, y - vicinity_size);
                          ny <
@@ -574,34 +698,39 @@ void TestBerclazGraph()
                                             weight, graph);
                         }
                     }
+
+                    boost::add_edge(vertices[vi], sink, 0.0, graph);
+                }
+                else
+                {
+                    boost::add_edge(vertices[vi], sink, weight, graph);
                 }
 
                 // Connect with source and sink
                 boost::add_edge(source, vertices[vi], 0.0, graph);
-                boost::add_edge(vertices[vi], sink, 0.0, graph);
             }
         }
     }
 
-    std::cout << "vertex count = " << boost::num_vertices(graph) << std::endl;
-    std::cout << "edge count = " << boost::num_edges(graph) << std::endl;
+    util::Logger::LogDebug("vertex count " + std::to_string(boost::num_vertices(graph)));
+    util::Logger::LogDebug("edge count " + std::to_string(boost::num_edges(graph)));
 
     // Running KSP with 5 possible paths although only 3 are worth it
-    algo::KShortestPaths ksp(graph, source, sink);
-    MultiPredecessorMap ksp_result = ksp.Run(5);
+    algo::KShortestPaths2 ksp;
+    MultiPredecessorMap ksp_result = ksp.Run(graph, source, sink, 5);
 
     util::FileIO::WriteCSVMatlab(graph, "/home/wrede/Dokumente/graph.csv");
-    util::FileIO::WriteCSVMatlab(ksp_result,
-                                 sink, "/home/wrede/Dokumente/paths.csv");
+    util::FileIO::WriteCSVMatlab(ksp_result, source, sink,
+                                 "/home/wrede/Dokumente/paths.csv");
 }
 
 int main(int argc, char** argv)
 {
-    //Run(argc, argv);
+    Run(argc, argv);
 
     //TestTracklet();
 
-    TestKSP();
+    //TestKSP();
 
     //TestGrid();
 

+ 26 - 6
util/FileIO.cpp

@@ -177,20 +177,26 @@ namespace util
     }
 
     void FileIO::WriteCSVMatlab(MultiPredecessorMap& map,
-                                Vertex& origin,
+                                Vertex& source, Vertex& sink,
                                 const std::string& file_name)
     {
         char delimiter = ',';
 
         std::ofstream out("/home/wrede/Dokumente/paths.csv", std::ofstream::out);
-        for (Vertex first : map[origin])
+        for (Vertex first : map[sink])
         {
-            out << (origin + 1) << delimiter << (first + 1);
+            out << (sink + 1) << delimiter << (first + 1);
 
+            //TODO change (count index)
             for (Vertex u = first, v = (*map[u].begin());
                  u != v; u = v, v = (*map[v].begin()))
             {
                 out << delimiter << (v + 1);
+
+                if (v == source)
+                {
+                    break;
+                }
             }
 
             out << std::endl;
@@ -204,6 +210,13 @@ namespace util
     {
         // Read the file
         std::ifstream in(file_name, std::ifstream::in);
+
+        // Only proceed if the file could be opened
+        if (!in.is_open())
+        {
+            throw "Unable to open file: " + file_name;
+        }
+
         std::string line;
 
         // Get the first line that is not empty
@@ -226,10 +239,17 @@ namespace util
 
         // Read the file
         std::ifstream in(file_name, std::ifstream::in);
+
+        // Only proceed if the file could be opened
+        if (!in.is_open())
+        {
+            throw "Unable to open file: " + file_name;
+        }
+
         std::string line, part;
         size_t d_index;
 
-        // Split the first line into separate keys
+        // Split the header into separate keys
         std::vector<std::string> key_vector;
         line = header;
         do
@@ -291,10 +311,10 @@ namespace util
             values.push_back(detection_values);
         }
 
-        util::Logger::LogDebug("parsed values in line 1:");
+        util::Logger::LogDebug("parsed values in line 2:");
         for (std::string str : key_vector)
         {
-            util::Logger::LogDebug(str + "=" + std::to_string(values[0][str]));
+            util::Logger::LogDebug(str + "=" + std::to_string(values[1][str]));
         }
 
         in.close();

+ 7 - 6
util/FileIO.h

@@ -37,7 +37,7 @@ namespace util
          */
         static void ReadCSV(Vector3d& values,
                             const std::string& file_name,
-                            char delimiter = ';');
+                            char delimiter);
 
         /**
          * Reads a CSV file and stores the values in a 2D array.
@@ -48,7 +48,7 @@ namespace util
          */
         static void ReadCSV(Vector2d& values,
                             const std::string& file_name,
-                            char delimiter = ';');
+                            char delimiter);
 
         /**
          * Lists all file names in the given folder.
@@ -75,11 +75,12 @@ namespace util
          * readable by Matlab to display all paths in the corresponding graph.
          *
          * @param map The multi predecessor map to extract the paths from
-         * @param origin The origin, this is the vertex where all paths end
+         * @param source The sink, this is the vertex where all paths begin
+         * @param sink The sink, this is the vertex where all paths end
          * @param file_name The name of the file to write
          */
         static void  WriteCSVMatlab(MultiPredecessorMap& map,
-                                    Vertex& origin,
+                                    Vertex& source, Vertex& sink,
                                     const std::string& file_name);
 
         /**
@@ -93,7 +94,7 @@ namespace util
          */
         static void ReadCSV(ValueMapVector& values,
                             const std::string& file_name,
-                            char delimiter = ',');
+                            char delimiter);
 
         /**
          * Reads a CSV file.
@@ -108,7 +109,7 @@ namespace util
         static void ReadCSV(ValueMapVector& values,
                             const std::string& header,
                             const std::string& file_name,
-                            char delimiter = ',');
+                            char delimiter);
     };
 }
 

+ 122 - 124
util/Parser.cpp

@@ -15,101 +15,84 @@ namespace util
     const std::string Parser::KEY_SCORE = "score";
     const std::string Parser::KEY_X = "x";
     const std::string Parser::KEY_Y = "y";
-    const std::string Parser::KEY_Z = "z";
     const std::string Parser::KEY_WIDTH = "width";
     const std::string Parser::KEY_HEIGHT = "height";
-    const std::string Parser::KEY_DEPTH = "depth";
     const std::string Parser::KEY_ANGLE = "angle";
 
-    void Parser::ParseObjectDataMap(const std::vector<std::string>& keys,
-                                    const Vector3d& values,
-                                    core::DetectionSequence& sequence)
+    void Parser::ParseObjectData2D(ValueMapVector& values,
+                                   core::DetectionSequence& sequence,
+                                   double image_width, double image_height,
+                                   double temporal_weight,
+                                   double spatial_weight)
     {
-        util::Logger::LogInfo("Parsing ObjectDataMap");
-
-        for (size_t frame_i = 0; frame_i < values.size(); ++frame_i)
-        {
-            for (size_t object_i = 0; object_i < values[frame_i].size();
-                 ++object_i)
-            {
-                core::ObjectDataMapPtr object(
-                        new core::ObjectDataMap(frame_i, keys,
-                                                values[frame_i][object_i]));
-
-                sequence.AddObject(object);
-            }
-        }
-    }
-
-    void Parser::ParseObjectData3D(const Vector3d& values,
-                                   core::DetectionSequence& sequence)
-    {
-        util::Logger::LogInfo("Parsing ObjectData3D");
+        util::Logger::LogInfo("Parsing ObjectData2D detections");
 
         // Calculate max and min score to normalize the score
         double max_score = std::numeric_limits<double>::min();
         double min_score = std::numeric_limits<double>::max();
-        for (size_t frame_i = 0; frame_i < values.size(); ++frame_i)
+        for (size_t line_index = 0; line_index < values.size(); ++line_index)
         {
-            for (size_t object_i = 0; object_i < values[frame_i].size();
-                 ++object_i)
+            double score = values[line_index][KEY_SCORE];
+            if (score > max_score)
             {
-                double score = values[frame_i][object_i][1];
-                if (score > max_score)
-                {
-                    max_score = score;
-                }
-                if (score < min_score)
-                {
-                    min_score = score;
-                }
+                max_score = score;
+            }
+            if (score < min_score)
+            {
+                min_score = score;
             }
         }
 
+        util::Logger::LogDebug("min score " + std::to_string(min_score));
+        util::Logger::LogDebug("max score " + std::to_string(max_score));
+
         // Create objects
-        for (size_t frame_i = 0; frame_i < values.size(); ++frame_i)
+        size_t obj_count = 0;
+        for (size_t line_index = 0; line_index < values.size(); ++line_index)
         {
-            for (size_t object_i = 0; object_i < values[frame_i].size();
-                 ++object_i)
-            {
-                double score = values[frame_i][object_i][1];
-                double x = values[frame_i][object_i][2];
-                double y = values[frame_i][object_i][3];
-                double z = 0.0;
-                cv::Point3d point(x, y, z);
+            size_t frame = (size_t) fabs(values[line_index][KEY_FRAME]);
+            double x = values[line_index][KEY_X] / image_width;
+            double y = values[line_index][KEY_Y] / image_height;
+            double score = values[line_index][KEY_SCORE];
 
-                core::ObjectData3DPtr object(new core::ObjectData3D(frame_i, point));
+            cv::Point2d point(x, y);
 
-                object->SetDetectionScore(util::MyMath::InverseLerp(min_score, max_score, score));
+            core::ObjectData2DPtr object(
+                    new core::ObjectData2D(frame, point));
 
-                sequence.AddObject(object);
-            }
+            object->SetTemporalWeight(temporal_weight);
+            object->SetSpatialWeight(spatial_weight);
+            object->SetDetectionScore(
+                    util::MyMath::InverseLerp(min_score, max_score, score));
+
+            sequence.AddObject(object);
+
+            obj_count++;
         }
-    }
 
-    void Parser::ParseObjectDataAngular(const Vector3d& values,
-                                        core::DetectionSequence& sequence)
-    {
-        ParseObjectDataAngular(values, sequence, 1.0, 1.0, 1.0);
+        util::Logger::LogDebug("objects parsed " + std::to_string(obj_count));
+        util::Logger::LogDebug("frame count " + std::to_string(sequence.GetFrameCount()));
     }
 
-    void Parser::ParseObjectDataAngular(const Vector3d& values,
+    void Parser::ParseObjectDataAngular(ValueMapVector& values,
                                         core::DetectionSequence& sequence,
+                                        double image_width,
+                                        double image_height,
                                         double temporal_weight,
                                         double spatial_weight,
                                         double angular_weight)
     {
-        util::Logger::LogInfo("Parsing ObjectDataAngular");
+        util::Logger::LogInfo("Parsing ObjectDataAngular detections");
 
         // Calculate max and min score to normalize the score
         double max_score = std::numeric_limits<double>::min();
         double min_score = std::numeric_limits<double>::max();
-        for (size_t frame_i = 0; frame_i < values.size(); ++frame_i)
+        for (size_t line_index = 0; line_index < values.size(); ++line_index)
         {
-            for (size_t object_i = 0; object_i < values[frame_i].size();
+            for (size_t object_i = 0; object_i < values[line_index].size();
                  ++object_i)
             {
-                double score = values[frame_i][object_i][1];
+                double score = values[line_index][KEY_SCORE];
                 if (score > max_score)
                 {
                     max_score = score;
@@ -125,77 +108,42 @@ namespace util
         util::Logger::LogDebug("max score " + std::to_string(max_score));
 
         // Create objects
-        for (size_t frame_i = 0; frame_i < values.size(); ++frame_i)
+        size_t obj_count = 0;
+        for (size_t line_index = 0; line_index < values.size(); ++line_index)
         {
-            for (size_t object_i = 0; object_i < values[frame_i].size();
-                 ++object_i)
-            {
-                double angle = MyMath::Radian(values[frame_i][object_i][0]);
-                double score = values[frame_i][object_i][1];
-                double x = values[frame_i][object_i][2];
-                double y = values[frame_i][object_i][3];
-                cv::Point2d point(x, y);
-
-                //util::Logger::LogDebug("score " + std::to_string(score));
-
-                core::ObjectDataAngularPtr object(
-                        new core::ObjectDataAngular(frame_i, point, angle,
-                                                    temporal_weight,
-                                                    spatial_weight,
-                                                    angular_weight));
+            size_t frame = (size_t) fabs(values[line_index][KEY_FRAME]);
+            double x = values[line_index][KEY_X] / image_width;
+            double y = values[line_index][KEY_Y] / image_height;
+            double angle = MyMath::Radian(values[line_index][KEY_ANGLE]);
+            double score = values[line_index][KEY_SCORE];
 
-                object->SetDetectionScore(util::MyMath::InverseLerp(min_score, max_score, score));
+            //TODO detection score interpolation (0.5 <-> 1.0) (experimental)
+            score = util::MyMath::InverseLerp(min_score, max_score, score);
+            score = score * 0.5 + 0.5;
 
-                sequence.AddObject(object);
-            }
-        }
-    }
+            cv::Point2d point(x, y);
 
-    Grid Parser::ParseGrid(core::DetectionSequence& sequence,
-                           double min_x, double max_x, int res_x,
-                           double min_y, double max_y, int res_y)
-    {
-        int res_z = (int) sequence.GetFrameCount();
-        double width = max_x - min_x;
-        double height = max_y - min_y;
-        double depth = sequence.GetFrameCount();
-        Grid grid(res_x, res_y, res_z, width, height, depth);
+            core::ObjectDataAngularPtr object(
+                    new core::ObjectDataAngular(frame, point, angle));
 
-        // Fill with elements with detection score of zero
-        for (int z = 0; z < grid.GetDepthCount(); ++z)
-        {
-            for (int y = 0; y < grid.GetHeightCount(); ++y)
-            {
-                for (int x = 0; x < grid.GetWidthCount(); ++x)
-                {
-                    core::ObjectDataPtr value(new core::ObjectData((size_t)z));
-                    grid.SetValue(value, x, y, z);
-                }
-            }
-        }
+            object->SetTemporalWeight(temporal_weight);
+            object->SetSpatialWeight(spatial_weight);
+            object->SetAngularWeight(angular_weight);
+            object->SetDetectionScore(score);
 
-        // Add the detections
-        for (size_t f = 0; f < sequence.GetFrameCount(); ++f)
-        {
-            for (size_t i = 0; i < sequence.GetObjectCount(f); ++i)
-            {
-                core::ObjectDataPtr original_value = sequence.GetObject(f, i);
-                core::ObjectData2DPtr value =
-                        std::static_pointer_cast<core::ObjectData2D>(original_value);
+            sequence.AddObject(object);
 
-                grid.SetValue(original_value,
-                              value->GetPosition().x,
-                              value->GetPosition().y,
-                              f);
-            }
+            obj_count++;
         }
 
-        return grid;
+        util::Logger::LogDebug("objects parsed " + std::to_string(obj_count));
+        util::Logger::LogDebug("frame count " + std::to_string(sequence.GetFrameCount()));
     }
 
     void Parser::ParseObjectDataBox(ValueMapVector& values,
                                     core::DetectionSequence& sequence,
-                                    double image_width, double image_height,
+                                    double image_width,
+                                    double image_height,
                                     double temporal_weight,
                                     double spatial_weight)
     {
@@ -234,15 +182,13 @@ namespace util
             cv::Point2d point(x, y);
             cv::Point2d size(width, height);
 
-            core::ObjectDataBoxPtr object(new core::ObjectDataBox(frame,
-                                                                  point,
-                                                                  size));
+            core::ObjectDataBoxPtr object(
+                    new core::ObjectDataBox(frame, point, size));
 
             object->SetTemporalWeight(temporal_weight);
             object->SetSpatialWeight(spatial_weight);
-            object->SetDetectionScore(util::MyMath::InverseLerp(min_score,
-                                                                max_score,
-                                                                score));
+            object->SetDetectionScore(
+                    util::MyMath::InverseLerp(min_score, max_score, score));
 
             sequence.AddObject(object);
 
@@ -252,6 +198,58 @@ namespace util
         util::Logger::LogDebug("objects parsed " + std::to_string(obj_count));
         util::Logger::LogDebug("frame count " + std::to_string(sequence.GetFrameCount()));
     }
+
+    Grid Parser::ParseGrid(core::DetectionSequence& sequence,
+                           size_t start, size_t stop,
+                           double min_x, double max_x, int res_x,
+                           double min_y, double max_y, int res_y)
+    {
+        stop = std::min(stop, sequence.GetFrameCount());
+        int res_z = (int) (stop - start);
+        double width = max_x - min_x;
+        double height = max_y - min_y;
+        double depth = (double) (stop - start);
+        Grid grid(res_x, res_y, res_z, width, height, depth);
+
+        // Fill with elements with detection score of zero
+        for (int z = 0; z < grid.GetDepthCount(); ++z)
+        {
+            for (int y = 0; y < grid.GetHeightCount(); ++y)
+            {
+                for (int x = 0; x < grid.GetWidthCount(); ++x)
+                {
+                    core::ObjectDataPtr value(
+                            new core::ObjectData((size_t)(z + start)));
+
+                    grid.SetValue(value, x, y, z);
+                }
+            }
+        }
+
+        // Add the detections
+        for (size_t f = start; f < stop; ++f)
+        {
+            for (size_t i = 0; i < sequence.GetObjectCount(f); ++i)
+            {
+                core::ObjectDataPtr original_value = sequence.GetObject(f, i);
+                core::ObjectData2DPtr value =
+                        std::static_pointer_cast<core::ObjectData2D>(original_value);
+
+                double x = value->GetPosition().x;
+                double y = value->GetPosition().y;
+                double stored_score = grid.GetValue(x, y, f - start)->GetDetectionScore();
+
+                // Only overwrite if the new detection score is at least as good
+                // as the detection score of the already stored value
+                if (stored_score <= original_value->GetDetectionScore())
+                {
+                    grid.SetValue(original_value, x, y, f - start);
+                }
+            }
+        }
+
+        return grid;
+    }
 }
 
 

+ 50 - 37
util/Parser.h

@@ -7,8 +7,6 @@
 
 #include "../core/DetectionSequence.h"
 #include "../core/ObjectData.h"
-#include "../core/ObjectDataMap.h"
-#include "../core/ObjectData3D.h"
 #include "Grid.h"
 #include "FileIO.h"
 #include <opencv2/core/core.hpp>
@@ -35,54 +33,76 @@ namespace util
         static const std::string KEY_DEPTH;
         static const std::string KEY_ANGLE;
 
-        //TODO rework old parsers
         /**
-         * Parses the keys and values into a DetectionSequence of ObjectDataMap
-         * objects.
-         * The keys are used for the third dimension in the values list.
-         * @param keys A 1D vector of keys
-         * @param values A 3D vector of values
-         * @param sequence The sequence to store the created objects in
-         */
-        static void ParseObjectDataMap(const std::vector<std::string>& keys,
-                                       const Vector3d& values,
-                                       core::DetectionSequence& sequence);
-
-        /**
-         * Parses the values into a DetectionSequence of ObjectData3D
-         * @param values A 3D vector of values
-         * @param sequence The sequence to store the created objects in
+         * Parses the specified values into the specified sequence.
+         * The used format is ObjectData2D.
+         *
+         * @param values The input values
+         * @param sequence The output sequence containing the parsed values
+         * @param image_width The width of the image used for normalized
+         *                    coordinates
+         * @param image_height The height of the image used for normalized
+         *                     coordinates
+         * @param temporal_weight The temporal weight
+         * @param spatial_weight The spatial weight
          */
-        static void ParseObjectData3D(const Vector3d& values,
-                                      core::DetectionSequence& sequence);
+        static void ParseObjectData2D(ValueMapVector& values,
+                                       core::DetectionSequence& sequence,
+                                       double image_width,
+                                       double image_height,
+                                       double temporal_weight,
+                                       double spatial_weight);
 
         /**
-         * Parses the values into a DetectionSequence of ObjectDataAngular objects.
-         * @param values A 3D vector of values
-         * @param sequence The sequence to store the created objects in
+         * Parses the specified values into the specified sequence.
+         * The used format is ObjectDataBox.
+         *
+         * @param values The input values
+         * @param sequence The output sequence containing the parsed values
+         * @param image_width The width of the image used for normalized
+         *                    coordinates
+         * @param image_height The height of the image used for normalized
+         *                     coordinates
+         * @param temporal_weight The temporal weight
+         * @param spatial_weight The spatial weight
          */
-        static void ParseObjectDataAngular(const Vector3d& values,
-                                           core::DetectionSequence& sequence);
+        static void ParseObjectDataBox(ValueMapVector& values,
+                                       core::DetectionSequence& sequence,
+                                       double image_width,
+                                       double image_height,
+                                       double temporal_weight,
+                                       double spatial_weight);
 
         /**
-         * Parses the values into a DetectionSequence of ObjectDataAngular objects.
-         * The keys are used for the third dimension in the values list.
-         * @param values A 3D vector of values
+         * Parses the specified values into the specified sequence.
+         * The used format is ObjectDataAngular.
+         *
+         * @param values The input values
          * @param sequence The sequence to store the created objects in
+         * @param image_width The width of the image used for normalized
+         *                    coordinates
+         * @param image_height The height of the image used for normalized
+         *                     coordinates
          * @param temporal_weight The temporal weight
          * @param spatial_weight The spatial weight
          * @param angular_weight The angular weight
          */
-        static void ParseObjectDataAngular(const Vector3d& values,
+        static void ParseObjectDataAngular(ValueMapVector& values,
                                            core::DetectionSequence& sequence,
+                                           double image_width,
+                                           double image_height,
                                            double temporal_weight,
                                            double spatial_weight,
                                            double angular_weight);
+
         /**
          * Parses the given sequence into a grid.
          * The sequence data need to be a ObjectData2D.
          * The frame index is the depth of the grid.
+         *
          * @param sequence The detection sequence to parse
+         * @param start The first frame to use
+         * @param stop The first frame not to use
          * @param min_x The minimal x value
          * @param max_x The maximal x value
          * @param res_x The number of cells on the x axis
@@ -93,16 +113,9 @@ namespace util
          */
         static Grid ParseGrid(
                 core::DetectionSequence& sequence,
+                size_t start, size_t stop,
                 double min_x, double max_x, int res_x,
                 double min_y, double max_y, int res_y);
-
-        //TODO comment
-        static void ParseObjectDataBox(ValueMapVector& values,
-                                       core::DetectionSequence& sequence,
-                                       double image_width = 1.0,
-                                       double image_height = 1.0,
-                                       double temporal_weight = 1.0,
-                                       double spatial_weight = 1.0);
     };
 }
 

+ 0 - 1
util/Visualizer.h

@@ -8,7 +8,6 @@
 #include <opencv2/core/core.hpp>
 #include <opencv2/opencv.hpp>
 #include "../core/DetectionSequence.h"
-#include "../core/ObjectData3D.h"
 #include "../core/Tracklet.h"
 #include "dirent.h"
 #include <chrono>