Browse Source

added time measurement
berclaz more or less functional

Helge Wrede 9 năm trước cách đây
mục cha
commit
c1ffa1b708

+ 3 - 3
CMakeLists.txt

@@ -10,20 +10,20 @@ set(SOURCE_FILES
         main/main.cpp
         main/main.cpp
         core/DetectionSequence.cpp core/DetectionSequence.h
         core/DetectionSequence.cpp core/DetectionSequence.h
         core/ObjectData.cpp core/ObjectData.h
         core/ObjectData.cpp core/ObjectData.h
-        core/ObjectDataMap.cpp core/ObjectDataMap.h
         core/Tracklet.cpp core/Tracklet.h
         core/Tracklet.cpp core/Tracklet.h
         util/FileIO.cpp util/FileIO.h
         util/FileIO.cpp util/FileIO.h
         util/Parser.cpp util/Parser.h
         util/Parser.cpp util/Parser.h
         algo/NStage.cpp algo/NStage.h
         algo/NStage.cpp algo/NStage.h
         util/MyMath.cpp util/MyMath.h
         util/MyMath.cpp util/MyMath.h
-        core/ObjectData3D.cpp core/ObjectData3D.h
         util/Visualizer.cpp util/Visualizer.h
         util/Visualizer.cpp util/Visualizer.h
         util/Logger.cpp util/Logger.h
         util/Logger.cpp util/Logger.h
         core/ObjectDataAngular.cpp core/ObjectDataAngular.h
         core/ObjectDataAngular.cpp core/ObjectDataAngular.h
         algo/KShortestPaths.cpp algo/KShortestPaths.h
         algo/KShortestPaths.cpp algo/KShortestPaths.h
         graph/Definitions.h
         graph/Definitions.h
         core/ObjectData2D.cpp core/ObjectData2D.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)
 find_package(Doxygen)
 
 

+ 107 - 60
algo/Berclaz.cpp

@@ -7,6 +7,7 @@
 #include "../util/Parser.h"
 #include "../util/Parser.h"
 #include "../util/Logger.h"
 #include "../util/Logger.h"
 #include "../util/FileIO.h"
 #include "../util/FileIO.h"
+#include "KShortestPaths2.h"
 
 
 namespace algo
 namespace algo
 {
 {
@@ -17,44 +18,48 @@ namespace algo
         vicinity_size_ = vicinity_size;
         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
         // 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);
         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
         // 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
                     // 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();
                     double score = values[vi]->GetDetectionScore();
                     if (score > MAX_SCORE_VALUE)
                     if (score > MAX_SCORE_VALUE)
                     {
                     {
@@ -65,40 +70,54 @@ namespace algo
                         score = MIN_SCORE_VALUE;
                         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_);
                         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)
                              ++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)
                                 std::vector<core::TrackletPtr>& tracks)
     {
     {
         VertexValueMap values = boost::get(boost::vertex_name, graph);
         VertexValueMap values = boost::get(boost::vertex_name, graph);
@@ -121,31 +140,59 @@ namespace algo
     }
     }
 
 
     void Berclaz::Run(core::DetectionSequence& sequence,
     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)
                       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:
     private:
         const double VIRTUAL_EDGE_WEIGHT = 0.0;
         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
          * Horizontal grid resolution
@@ -40,6 +36,7 @@ namespace algo
 
 
         /**
         /**
          * Creates a graph from the given sequence.
          * Creates a graph from the given sequence.
+         *
          * @param graph The graph to write into
          * @param graph The graph to write into
          * @param source A reference to the source vertex
          * @param source A reference to the source vertex
          * @param sink A reference to the sink 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.
          * Extracts the final tracks from the given graph and predecessor map.
+         *
          * @param graph The graph to read the values from
          * @param graph The graph to read the values from
          * @param map The predecessor map to read the paths from
          * @param map The predecessor map to read the paths from
          * @param origin The vertex to start the reverse path traversal from
          * @param origin The vertex to start the reverse path traversal from
@@ -58,9 +56,13 @@ namespace algo
         void ExtractTracks(DirectedGraph& graph,
         void ExtractTracks(DirectedGraph& graph,
                            MultiPredecessorMap& map, Vertex origin,
                            MultiPredecessorMap& map, Vertex origin,
                            std::vector<core::TrackletPtr>& tracks);
                            std::vector<core::TrackletPtr>& tracks);
+
+        //TODO comment
+        void ConnectTracks(std::vector<core::TrackletPtr>& tracks);
     public:
     public:
         /**
         /**
          * Instantiate with the given parameters.
          * Instantiate with the given parameters.
+         *
          * @param h_res The horizontal grid resolution
          * @param h_res The horizontal grid resolution
          * @param v_res The vertical grid resolution
          * @param v_res The vertical grid resolution
          * @param vicinity_size The maximum number of cells a detection can skip
          * @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);
         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 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 max_track_count The maximum number of tracks to extract
          * @param tracks The vector to store the found tracks into
          * @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
         // Clear all data from previous runs
         i_shortest_paths_.clear();
         i_shortest_paths_.clear();
 
 
-        util::Logger::LogDebug("find shortest path #1");
+        util::Logger::LogDebug("find shortest path #0");
 
 
         util::Logger::LogDebug("find");
         util::Logger::LogDebug("find");
-        FindAndAugmentPath(1, true);
+        FindAndAugmentPath(0, true);
 
 
         // Find the k shortest paths
         // 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))
                 if (OverallCosts(i) > OverallCosts(i - 1))
                 {
                 {
                     return i_shortest_paths_[i];
                     return i_shortest_paths_[i];
@@ -47,13 +48,32 @@ namespace algo
             // for the graph and edge transformations
             // for the graph and edge transformations
             CopyOriginalGraph();
             CopyOriginalGraph();
 
 
+            util::FileIO::WriteCSVMatlab(copied_graph_,
+                                         "/home/wrede/Dokumente/graph_" +
+                                         std::to_string(i) + "_c.csv");
+
             util::Logger::LogDebug("extend");
             util::Logger::LogDebug("extend");
             // Extend the graph (has negative and positive edge weights)
             // Extend the graph (has negative and positive edge weights)
             ExtendGraph(i);
             ExtendGraph(i);
 
 
+            util::FileIO::WriteCSVMatlab(copied_graph_,
+                                         "/home/wrede/Dokumente/graph_" +
+                                         std::to_string(i) + "_e.csv");
+
             util::Logger::LogDebug("transform");
             util::Logger::LogDebug("transform");
             // Transforms the edge costs (has only positive edge weights)
             // 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");
             util::Logger::LogDebug("find");
             // Finds the next path and adds it to the found paths
             // Finds the next path and adds it to the found paths
@@ -65,7 +85,7 @@ namespace algo
         }
         }
 
 
         // All k shortest paths have been found
         // 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)
     void KShortestPaths::ExtendGraph(size_t i)
@@ -79,7 +99,11 @@ namespace algo
         for (boost::tie(vi, vi_end) = boost::vertices(original_graph_);
         for (boost::tie(vi, vi_end) = boost::vertices(original_graph_);
              vi != vi_end; ++vi)
              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_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
             // Ignore vertices off the paths, the source and the sink
             if (i_shortest_paths_[i].count(v_original) == 0 ||
             if (i_shortest_paths_[i].count(v_original) == 0 ||
@@ -88,8 +112,6 @@ namespace algo
                 continue;
                 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_to_original_[v_out] = v_original;
 
 
             // Copy outgoing edges to v_out
             // Copy outgoing edges to v_out
@@ -107,8 +129,8 @@ namespace algo
                 QueueRemoveEdge(v_in, boost::target(*oei, copied_graph_));
                 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();
         UpdateEdges();
@@ -137,6 +159,9 @@ namespace algo
         }
         }
 
 
         UpdateEdges();
         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)
     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));
         util::Logger::LogDebug("cost in " + std::to_string(i) + " : " + std::to_string(value));
 
 
         return value;
         return value;
@@ -238,7 +268,7 @@ namespace algo
         }
         }
 
 
         // Only copy old paths if old paths exist
         // Only copy old paths if old paths exist
-        if (i > 1)
+        if (i > 0)
         {
         {
             // Copy the old paths
             // Copy the old paths
             for (auto it = i_shortest_paths_[i - 1].begin();
             for (auto it = i_shortest_paths_[i - 1].begin();
@@ -252,7 +282,6 @@ namespace algo
         {
         {
             // Prepare variables for path finding
             // Prepare variables for path finding
             size_t graph_size = boost::num_vertices(original_graph_);
             size_t graph_size = boost::num_vertices(original_graph_);
-            Vertex root_vertex = source_;
             std::vector<Vertex> pred_list(graph_size);
             std::vector<Vertex> pred_list(graph_size);
             std::vector<double> dist_list(graph_size);
             std::vector<double> dist_list(graph_size);
             VertexIndexMap graph_indices = boost::get(boost::vertex_index,
             VertexIndexMap graph_indices = boost::get(boost::vertex_index,
@@ -265,7 +294,7 @@ namespace algo
             // Find the shortest path
             // Find the shortest path
             boost::bellman_ford_shortest_paths(original_graph_,
             boost::bellman_ford_shortest_paths(original_graph_,
                                                graph_size,
                                                graph_size,
-                                               boost::root_vertex(root_vertex)
+                                               boost::root_vertex(source_)
                                                        .weight_map(weight_map)
                                                        .weight_map(weight_map)
                                                        .predecessor_map(pred_map)
                                                        .predecessor_map(pred_map)
                                                        .distance_map(dist_map));
                                                        .distance_map(dist_map));
@@ -287,34 +316,26 @@ namespace algo
 
 
                 ++path_length;
                 ++path_length;
             }
             }
+
             util::Logger::LogDebug("path length " + std::to_string(path_length));
             util::Logger::LogDebug("path length " + std::to_string(path_length));
         }
         }
         else
         else
         {
         {
             // Prepare variables for path finding
             // Prepare variables for path finding
             size_t graph_size = boost::num_vertices(copied_graph_);
             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<Vertex> pred_list(graph_size);
             std::vector<double> dist_list(graph_size);
             std::vector<double> dist_list(graph_size);
             VertexIndexMap graph_indices = boost::get(boost::vertex_index,
             VertexIndexMap graph_indices = boost::get(boost::vertex_index,
                                                       copied_graph_);
                                                       copied_graph_);
-            EdgeWeightMap weight_map = boost::get(boost::edge_weight,
-                                                     copied_graph_);
             PredecessorMap pred_map(&pred_list[0], graph_indices);
             PredecessorMap pred_map(&pred_list[0], graph_indices);
             DistanceMap dist_map(&dist_list[0], graph_indices);
             DistanceMap dist_map(&dist_list[0], graph_indices);
 
 
             // Find the shortest path
             // 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)
                                            boost::predecessor_map(pred_map)
                                                    .distance_map(dist_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");
             util::Logger::LogDebug("add the path");
 
 
             // Add the new distances
             // Add the new distances
@@ -323,22 +344,15 @@ namespace algo
                  vi != vi_end; ++vi)
                  vi != vi_end; ++vi)
             {
             {
                 Vertex v_copy = *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
             // Add the new path (the given path is in the copied graph, so the
             // vertices need to be mapped to the original graph)
             // vertices need to be mapped to the original graph)
             size_t path_length = 0;
             size_t path_length = 0;
             Vertex sink_copy = original_to_copy_[sink_];
             Vertex sink_copy = original_to_copy_[sink_];
+            std::cout << sink_;
             for (Vertex u_copy = sink_copy, v_copy = pred_map[u_copy];
             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])
                  u_copy != v_copy; u_copy = v_copy, v_copy = pred_map[v_copy])
             {
             {
@@ -351,54 +365,60 @@ namespace algo
                     continue;
                     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_shortest_paths_[i][u_original].insert(v_original);
-                i_distances_[i][u_original] = dist_map[u_copy];
 
 
                 ++path_length;
                 ++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
         // Add source
         i_shortest_paths_[i][source_].insert(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_);
         EdgeWeightMap weights = boost::get(boost::edge_weight, copied_graph_);
         boost::graph_traits<DirectedGraph>::edge_iterator ei, ei_end;
         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_;
         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.
          * shortest path found in the i-th iteration.
          */
          */
         std::vector<std::unordered_map<Vertex, double>> i_distances_;
         std::vector<std::unordered_map<Vertex, double>> i_distances_;
@@ -79,7 +79,7 @@ namespace algo
         void ExtendGraph(size_t i);
         void ExtendGraph(size_t i);
 
 
         //TODO comment
         //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.
          * 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
         // Iteratively run dijkstra to extract tracklets
         for (size_t i = 0; i != max_tracklet_counts_[iteration]; ++i)
         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::dijkstra_shortest_paths(obj_graph, obj_src,
                                            boost::predecessor_map(obj_pred_map)
                                            boost::predecessor_map(obj_pred_map)
                                                    .distance_map(obj_dist_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())
             if (obj_dist_map[obj_snk] == std::numeric_limits<double>::max())
             {
             {
                 break;
                 break;
@@ -163,6 +166,8 @@ namespace algo
                 boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()),
                 boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()),
                                   tlt_graph);
                                   tlt_graph);
 
 
+        util::Logger::LogDebug("adding edges");
+
         // Create edges
         // Create edges
         size_t tlt_graph_size = boost::num_vertices(tlt_graph);
         size_t tlt_graph_size = boost::num_vertices(tlt_graph);
         VertexIndexMap tlt_indices = boost::get(boost::vertex_index, tlt_graph);
         VertexIndexMap tlt_indices = boost::get(boost::vertex_index, tlt_graph);

+ 0 - 1
core/DetectionSequence.h

@@ -8,7 +8,6 @@
 
 
 #include <string>
 #include <string>
 #include "ObjectData.h"
 #include "ObjectData.h"
-#include "ObjectDataMap.h"
 
 
 namespace core
 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());
         SetFrameIndex(path_objects_.front()->GetFrameIndex());
         last_frame_index_ = path_objects_.back()->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.
          * removed.
          */
          */
         void Flatten();
         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;
         VertexValueMap;
 typedef boost::iterator_property_map<Vertex*, VertexIndexMap, Vertex, Vertex&>
 typedef boost::iterator_property_map<Vertex*, VertexIndexMap, Vertex, Vertex&>
         PredecessorMap;
         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&>
 typedef boost::iterator_property_map<double*, VertexIndexMap, double, double&>
         DistanceMap;
         DistanceMap;
 typedef boost::iterator_property_map<
 typedef boost::iterator_property_map<

+ 239 - 110
main/main.cpp

@@ -10,6 +10,7 @@
 #include "../util/Logger.h"
 #include "../util/Logger.h"
 #include "../core/ObjectDataAngular.h"
 #include "../core/ObjectDataAngular.h"
 #include "../algo/Berclaz.h"
 #include "../algo/Berclaz.h"
+#include "../algo/KShortestPaths2.h"
 #include <boost/program_options.hpp>
 #include <boost/program_options.hpp>
 
 
 struct
 struct
@@ -20,9 +21,7 @@ struct
 } n_stage_params;
 } n_stage_params;
 
 
 void RunNStage(core::DetectionSequence& sequence,
 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");
     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,
     algo::NStage n_stage(n_stage_params.max_frame_skip,
                          penalty_values, max_tracklet_counts);
                          penalty_values, max_tracklet_counts);
 
 
-    std::vector<core::TrackletPtr> tracks;
     n_stage.Run(sequence, tracks);
     n_stage.Run(sequence, tracks);
 
 
     // Interpolate tracks
     // Interpolate tracks
@@ -76,13 +74,6 @@ void RunNStage(core::DetectionSequence& sequence,
         track->InterpolateMissingFrames();
         track->InterpolateMissingFrames();
     }
     }
 
 
-    // Display the tracking data
-    if (display)
-    {
-        util::Visualizer vis;
-        vis.Display(tracks, images_folder);
-    }
-
     util::Logger::LogInfo("Finished");
     util::Logger::LogInfo("Finished");
 }
 }
 
 
@@ -91,14 +82,13 @@ struct
     int h_res;
     int h_res;
     int v_res;
     int v_res;
     int vicinity_size;
     int vicinity_size;
+    size_t batch_size;
     size_t max_track_count;
     size_t max_track_count;
 } berclaz_params;
 } berclaz_params;
 
 
 
 
 void RunBerclaz(core::DetectionSequence& sequence,
 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");
     util::Logger::LogInfo("Running berclaz");
 
 
@@ -106,8 +96,8 @@ void RunBerclaz(core::DetectionSequence& sequence,
     algo::Berclaz berclaz(berclaz_params.h_res,
     algo::Berclaz berclaz(berclaz_params.h_res,
                           berclaz_params.v_res,
                           berclaz_params.v_res,
                           berclaz_params.vicinity_size);
                           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");
     util::Logger::LogInfo("Interpolate tracks");
 
 
@@ -117,13 +107,6 @@ void RunBerclaz(core::DetectionSequence& sequence,
         track->InterpolateMissingFrames();
         track->InterpolateMissingFrames();
     }
     }
 
 
-    // Display the tracking data
-    if (display)
-    {
-        util::Visualizer vis;
-        vis.Display(tracks, images_folder);
-    }
-
     util::Logger::LogInfo("Finished");
     util::Logger::LogInfo("Finished");
 }
 }
 
 
@@ -134,7 +117,8 @@ void Run(int argc, char** argv)
     bool info, debug, display;
     bool info, debug, display;
 
 
     // Input dependent variables
     // Input dependent variables
-    std::string header;
+    std::string header, input_format;
+    char input_delimiter;
     double temporal_weight, spatial_weight, angular_weight;
     double temporal_weight, spatial_weight, angular_weight;
     double image_width, image_height;
     double image_width, image_height;
 
 
@@ -157,13 +141,13 @@ void Run(int argc, char** argv)
             ("config",
             ("config",
              boost::program_options::value<std::string>(&config_path),
              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")
              "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),
              boost::program_options::value<std::string>(&input_file),
              "set detections file path")
              "set detections file path")
-            ("output-file,o",
+            ("output-file",
              boost::program_options::value<std::string>(&output_file),
              boost::program_options::value<std::string>(&output_file),
              "set the output file path")
              "set the output file path")
-            ("images-folder,f",
+            ("images-folder",
              boost::program_options::value<std::string>(&images_folder),
              boost::program_options::value<std::string>(&images_folder),
              "set images folder path")
              "set images folder path")
             ("input-header",
             ("input-header",
@@ -171,7 +155,24 @@ void Run(int argc, char** argv)
                     ->default_value(""),
                     ->default_value(""),
              "sets the input header, this value is optional if the input file has a header labeling the values,"
              "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")
                      "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),
              boost::program_options::value<std::string>(&algorithm),
              "set the algorithm to use, current viable options: n-stage berclaz")
              "set the algorithm to use, current viable options: n-stage berclaz")
             ("max-frame-skip",
             ("max-frame-skip",
@@ -215,14 +216,10 @@ void Run(int argc, char** argv)
              boost::program_options::value<size_t>(&berclaz_params.max_track_count)
              boost::program_options::value<size_t>(&berclaz_params.max_track_count)
                      ->default_value(1),
                      ->default_value(1),
              "(berclaz) the maximal number of tracks to extract")
              "(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;
     boost::program_options::variables_map opt_var_map;
 #pragma clang diagnostic push
 #pragma clang diagnostic push
@@ -243,12 +240,29 @@ void Run(int argc, char** argv)
     // Read config
     // Read config
     if (opt_var_map.count("config") != 0)
     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
     // Enable info logging
@@ -268,35 +282,92 @@ void Run(int argc, char** argv)
     // Reading the input file
     // Reading the input file
     util::Logger::LogInfo("Reading input");
     util::Logger::LogInfo("Reading input");
     util::ValueMapVector values;
     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
     // Parsing the read input
     core::DetectionSequence sequence;
     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
     // 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")
     if (algorithm == "n-stage")
     {
     {
-        RunNStage(sequence, output_file, images_folder, display);
+        RunNStage(sequence, tracks);
     }
     }
     else if (algorithm == "berclaz")
     else if (algorithm == "berclaz")
     {
     {
-        RunBerclaz(sequence, output_file, images_folder, display);
+        RunBerclaz(sequence, tracks);
     }
     }
     else
     else
     {
     {
+        // No valid algorithm specified
         std::cout << opts << std::endl;
         std::cout << opts << std::endl;
         exit(0);
         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)
 void CreateTestGraph(DirectedGraph& graph, Vertex& source, Vertex& sink)
@@ -312,24 +383,31 @@ void CreateTestGraph(DirectedGraph& graph, Vertex& source, Vertex& sink)
 //
 //
 //    // AB
 //    // AB
 //    boost::add_edge(vertices[0], vertices[1], 1.0, graph);
 //    boost::add_edge(vertices[0], vertices[1], 1.0, graph);
+//    boost::add_edge(vertices[1], vertices[0], 1.0, graph);
 //
 //
 //    // AC
 //    // AC
 //    boost::add_edge(vertices[0], vertices[2], 2.0, graph);
 //    boost::add_edge(vertices[0], vertices[2], 2.0, graph);
+//    boost::add_edge(vertices[2], vertices[0], 2.0, graph);
 //
 //
 //    // BD
 //    // BD
 //    boost::add_edge(vertices[1], vertices[3], 1.0, graph);
 //    boost::add_edge(vertices[1], vertices[3], 1.0, graph);
+//    boost::add_edge(vertices[3], vertices[1], 1.0, graph);
 //
 //
 //    // BE
 //    // BE
 //    boost::add_edge(vertices[1], vertices[4], 2.0, graph);
 //    boost::add_edge(vertices[1], vertices[4], 2.0, graph);
+//    boost::add_edge(vertices[4], vertices[1], 2.0, graph);
 //
 //
 //    // CD
 //    // CD
 //    boost::add_edge(vertices[2], vertices[3], 2.0, graph);
 //    boost::add_edge(vertices[2], vertices[3], 2.0, graph);
+//    boost::add_edge(vertices[3], vertices[2], 2.0, graph);
 //
 //
 //    // DF
 //    // DF
 //    boost::add_edge(vertices[3], vertices[5], 1.0, graph);
 //    boost::add_edge(vertices[3], vertices[5], 1.0, graph);
+//    boost::add_edge(vertices[5], vertices[3], 1.0, graph);
 //
 //
 //    // EF
 //    // EF
 //    boost::add_edge(vertices[4], vertices[5], 2.0, graph);
 //    boost::add_edge(vertices[4], vertices[5], 2.0, graph);
+//    boost::add_edge(vertices[5], vertices[4], 2.0, graph);
 //
 //
 //    source = vertices[0];
 //    source = vertices[0];
 //    sink = vertices[5];
 //    sink = vertices[5];
@@ -343,29 +421,73 @@ void CreateTestGraph(DirectedGraph& graph, Vertex& source, Vertex& sink)
                         core::ObjectDataPtr(new core::ObjectData(i)),graph));
                         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];
     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()
 void TestKSP()
@@ -378,12 +500,12 @@ void TestKSP()
 
 
     CreateTestGraph(graph, source, sink);
     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(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()
 void TestGrid()
@@ -449,7 +571,9 @@ void TestGrid()
 
 
 void TestBerclazGraph()
 void TestBerclazGraph()
 {
 {
-    std::cout << "init\n";
+    util::Logger::SetDebug(true);
+    util::Logger::SetInfo(true);
+    util::Logger::LogInfo("Test berclaz graph");
 
 
     // Init grid with data
     // Init grid with data
     util::Grid grid(3, 3, 3, 9.0, 9.0, 9.0);
     util::Grid grid(3, 3, 3, 9.0, 9.0, 9.0);
@@ -476,7 +600,7 @@ void TestBerclazGraph()
     value2->SetDetectionScore(1.0);
     value2->SetDetectionScore(1.0);
     grid.SetValue(value2, 0, 0, 2);
     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));
     core::ObjectDataPtr value3(new core::ObjectData(4));
     value3->SetDetectionScore(0.6);
     value3->SetDetectionScore(0.6);
     grid.SetValue(value3, 0, 1, 0);
     grid.SetValue(value3, 0, 1, 0);
@@ -487,18 +611,18 @@ void TestBerclazGraph()
     value5->SetDetectionScore(0.6);
     value5->SetDetectionScore(0.6);
     grid.SetValue(value5, 0, 1, 2);
     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));
     core::ObjectDataPtr value6(new core::ObjectData(7));
-    value6->SetDetectionScore(0.3);
+    value6->SetDetectionScore(0.55);
     grid.SetValue(value6, 0, 2, 0);
     grid.SetValue(value6, 0, 2, 0);
     core::ObjectDataPtr value7(new core::ObjectData(8));
     core::ObjectDataPtr value7(new core::ObjectData(8));
-    value7->SetDetectionScore(0.3);
+    value7->SetDetectionScore(0.55);
     grid.SetValue(value7, 0, 2, 1);
     grid.SetValue(value7, 0, 2, 1);
     core::ObjectDataPtr value8(new core::ObjectData(9));
     core::ObjectDataPtr value8(new core::ObjectData(9));
-    value8->SetDetectionScore(0.3);
+    value8->SetDetectionScore(0.55);
     grid.SetValue(value8, 0, 2, 2);
     grid.SetValue(value8, 0, 2, 2);
 
 
-    std::cout << "add vertices\n";
+    util::Logger::LogDebug("add vertices");
 
 
     // Add grid vertices
     // Add grid vertices
     DirectedGraph graph;
     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
     // Add source and sink vertex
     Vertex source = boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()), graph);
     Vertex source = boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()), graph);
     Vertex sink = 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
     // Iterate all vertices but source and sink
     VertexIndexMap vertices = boost::get(boost::vertex_index, graph);
     VertexIndexMap vertices = boost::get(boost::vertex_index, graph);
@@ -536,24 +660,24 @@ void TestBerclazGraph()
                 // First vertex index
                 // First vertex index
                 int vi = x + y * grid.GetHeightCount() + z * layer_size;
                 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
                     // Iterate all nearby cells in the next frame
                     for (int ny = std::max(0, y - vicinity_size);
                     for (int ny = std::max(0, y - vicinity_size);
                          ny <
                          ny <
@@ -574,34 +698,39 @@ void TestBerclazGraph()
                                             weight, graph);
                                             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
                 // Connect with source and sink
                 boost::add_edge(source, vertices[vi], 0.0, graph);
                 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
     // 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(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)
 int main(int argc, char** argv)
 {
 {
-    //Run(argc, argv);
+    Run(argc, argv);
 
 
     //TestTracklet();
     //TestTracklet();
 
 
-    TestKSP();
+    //TestKSP();
 
 
     //TestGrid();
     //TestGrid();
 
 

+ 26 - 6
util/FileIO.cpp

@@ -177,20 +177,26 @@ namespace util
     }
     }
 
 
     void FileIO::WriteCSVMatlab(MultiPredecessorMap& map,
     void FileIO::WriteCSVMatlab(MultiPredecessorMap& map,
-                                Vertex& origin,
+                                Vertex& source, Vertex& sink,
                                 const std::string& file_name)
                                 const std::string& file_name)
     {
     {
         char delimiter = ',';
         char delimiter = ',';
 
 
         std::ofstream out("/home/wrede/Dokumente/paths.csv", std::ofstream::out);
         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());
             for (Vertex u = first, v = (*map[u].begin());
                  u != v; u = v, v = (*map[v].begin()))
                  u != v; u = v, v = (*map[v].begin()))
             {
             {
                 out << delimiter << (v + 1);
                 out << delimiter << (v + 1);
+
+                if (v == source)
+                {
+                    break;
+                }
             }
             }
 
 
             out << std::endl;
             out << std::endl;
@@ -204,6 +210,13 @@ namespace util
     {
     {
         // Read the file
         // Read the file
         std::ifstream in(file_name, std::ifstream::in);
         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;
         std::string line;
 
 
         // Get the first line that is not empty
         // Get the first line that is not empty
@@ -226,10 +239,17 @@ namespace util
 
 
         // Read the file
         // Read the file
         std::ifstream in(file_name, std::ifstream::in);
         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;
         std::string line, part;
         size_t d_index;
         size_t d_index;
 
 
-        // Split the first line into separate keys
+        // Split the header into separate keys
         std::vector<std::string> key_vector;
         std::vector<std::string> key_vector;
         line = header;
         line = header;
         do
         do
@@ -291,10 +311,10 @@ namespace util
             values.push_back(detection_values);
             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)
         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();
         in.close();

+ 7 - 6
util/FileIO.h

@@ -37,7 +37,7 @@ namespace util
          */
          */
         static void ReadCSV(Vector3d& values,
         static void ReadCSV(Vector3d& values,
                             const std::string& file_name,
                             const std::string& file_name,
-                            char delimiter = ';');
+                            char delimiter);
 
 
         /**
         /**
          * Reads a CSV file and stores the values in a 2D array.
          * Reads a CSV file and stores the values in a 2D array.
@@ -48,7 +48,7 @@ namespace util
          */
          */
         static void ReadCSV(Vector2d& values,
         static void ReadCSV(Vector2d& values,
                             const std::string& file_name,
                             const std::string& file_name,
-                            char delimiter = ';');
+                            char delimiter);
 
 
         /**
         /**
          * Lists all file names in the given folder.
          * 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.
          * readable by Matlab to display all paths in the corresponding graph.
          *
          *
          * @param map The multi predecessor map to extract the paths from
          * @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
          * @param file_name The name of the file to write
          */
          */
         static void  WriteCSVMatlab(MultiPredecessorMap& map,
         static void  WriteCSVMatlab(MultiPredecessorMap& map,
-                                    Vertex& origin,
+                                    Vertex& source, Vertex& sink,
                                     const std::string& file_name);
                                     const std::string& file_name);
 
 
         /**
         /**
@@ -93,7 +94,7 @@ namespace util
          */
          */
         static void ReadCSV(ValueMapVector& values,
         static void ReadCSV(ValueMapVector& values,
                             const std::string& file_name,
                             const std::string& file_name,
-                            char delimiter = ',');
+                            char delimiter);
 
 
         /**
         /**
          * Reads a CSV file.
          * Reads a CSV file.
@@ -108,7 +109,7 @@ namespace util
         static void ReadCSV(ValueMapVector& values,
         static void ReadCSV(ValueMapVector& values,
                             const std::string& header,
                             const std::string& header,
                             const std::string& file_name,
                             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_SCORE = "score";
     const std::string Parser::KEY_X = "x";
     const std::string Parser::KEY_X = "x";
     const std::string Parser::KEY_Y = "y";
     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_WIDTH = "width";
     const std::string Parser::KEY_HEIGHT = "height";
     const std::string Parser::KEY_HEIGHT = "height";
-    const std::string Parser::KEY_DEPTH = "depth";
     const std::string Parser::KEY_ANGLE = "angle";
     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
         // Calculate max and min score to normalize the score
         double max_score = std::numeric_limits<double>::min();
         double max_score = std::numeric_limits<double>::min();
         double min_score = std::numeric_limits<double>::max();
         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
         // 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,
                                         core::DetectionSequence& sequence,
+                                        double image_width,
+                                        double image_height,
                                         double temporal_weight,
                                         double temporal_weight,
                                         double spatial_weight,
                                         double spatial_weight,
                                         double angular_weight)
                                         double angular_weight)
     {
     {
-        util::Logger::LogInfo("Parsing ObjectDataAngular");
+        util::Logger::LogInfo("Parsing ObjectDataAngular detections");
 
 
         // Calculate max and min score to normalize the score
         // Calculate max and min score to normalize the score
         double max_score = std::numeric_limits<double>::min();
         double max_score = std::numeric_limits<double>::min();
         double min_score = std::numeric_limits<double>::max();
         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)
                  ++object_i)
             {
             {
-                double score = values[frame_i][object_i][1];
+                double score = values[line_index][KEY_SCORE];
                 if (score > max_score)
                 if (score > max_score)
                 {
                 {
                     max_score = score;
                     max_score = score;
@@ -125,77 +108,42 @@ namespace util
         util::Logger::LogDebug("max score " + std::to_string(max_score));
         util::Logger::LogDebug("max score " + std::to_string(max_score));
 
 
         // Create objects
         // 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,
     void Parser::ParseObjectDataBox(ValueMapVector& values,
                                     core::DetectionSequence& sequence,
                                     core::DetectionSequence& sequence,
-                                    double image_width, double image_height,
+                                    double image_width,
+                                    double image_height,
                                     double temporal_weight,
                                     double temporal_weight,
                                     double spatial_weight)
                                     double spatial_weight)
     {
     {
@@ -234,15 +182,13 @@ namespace util
             cv::Point2d point(x, y);
             cv::Point2d point(x, y);
             cv::Point2d size(width, height);
             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->SetTemporalWeight(temporal_weight);
             object->SetSpatialWeight(spatial_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);
             sequence.AddObject(object);
 
 
@@ -252,6 +198,58 @@ namespace util
         util::Logger::LogDebug("objects parsed " + std::to_string(obj_count));
         util::Logger::LogDebug("objects parsed " + std::to_string(obj_count));
         util::Logger::LogDebug("frame count " + std::to_string(sequence.GetFrameCount()));
         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/DetectionSequence.h"
 #include "../core/ObjectData.h"
 #include "../core/ObjectData.h"
-#include "../core/ObjectDataMap.h"
-#include "../core/ObjectData3D.h"
 #include "Grid.h"
 #include "Grid.h"
 #include "FileIO.h"
 #include "FileIO.h"
 #include <opencv2/core/core.hpp>
 #include <opencv2/core/core.hpp>
@@ -35,54 +33,76 @@ namespace util
         static const std::string KEY_DEPTH;
         static const std::string KEY_DEPTH;
         static const std::string KEY_ANGLE;
         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 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 temporal_weight The temporal weight
          * @param spatial_weight The spatial weight
          * @param spatial_weight The spatial weight
          * @param angular_weight The angular weight
          * @param angular_weight The angular weight
          */
          */
-        static void ParseObjectDataAngular(const Vector3d& values,
+        static void ParseObjectDataAngular(ValueMapVector& values,
                                            core::DetectionSequence& sequence,
                                            core::DetectionSequence& sequence,
+                                           double image_width,
+                                           double image_height,
                                            double temporal_weight,
                                            double temporal_weight,
                                            double spatial_weight,
                                            double spatial_weight,
                                            double angular_weight);
                                            double angular_weight);
+
         /**
         /**
          * Parses the given sequence into a grid.
          * Parses the given sequence into a grid.
          * The sequence data need to be a ObjectData2D.
          * The sequence data need to be a ObjectData2D.
          * The frame index is the depth of the grid.
          * The frame index is the depth of the grid.
+         *
          * @param sequence The detection sequence to parse
          * @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 min_x The minimal x value
          * @param max_x The maximal x value
          * @param max_x The maximal x value
          * @param res_x The number of cells on the x axis
          * @param res_x The number of cells on the x axis
@@ -93,16 +113,9 @@ namespace util
          */
          */
         static Grid ParseGrid(
         static Grid ParseGrid(
                 core::DetectionSequence& sequence,
                 core::DetectionSequence& sequence,
+                size_t start, size_t stop,
                 double min_x, double max_x, int res_x,
                 double min_x, double max_x, int res_x,
                 double min_y, double max_y, int res_y);
                 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/core/core.hpp>
 #include <opencv2/opencv.hpp>
 #include <opencv2/opencv.hpp>
 #include "../core/DetectionSequence.h"
 #include "../core/DetectionSequence.h"
-#include "../core/ObjectData3D.h"
 #include "../core/Tracklet.h"
 #include "../core/Tracklet.h"
 #include "dirent.h"
 #include "dirent.h"
 #include <chrono>
 #include <chrono>