Browse Source

ready for experiments

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

+ 13 - 24
algo/Berclaz.cpp

@@ -129,33 +129,14 @@ namespace algo
                       size_t batch_size, size_t max_track_count,
                       std::vector<core::TrackletPtr> & tracks, util::Filter2D & filter)
     {
-        for (size_t i = 0; i < sequence.GetFrameCount(); i += batch_size)
+        size_t batch_count = 0;
+        for (size_t i = sequence.GetFrameOffset(); i < sequence.GetFrameCount(); i += batch_size)
         {
             util::Logger::LogDebug("batch offset: " + std::to_string(i));
 
             util::Grid grid = util::Parser::ParseGrid(sequence, i, i + batch_size,
                                                       0.0, 1.0, h_res_, 0.0, 1.0, v_res_);
 
-            // Convolve with linear filter
-//            int vicinity = 1;
-//            double multiplier = 0.25;
-//            double* linear_filter = new double[9] {
-//                    0.25, 0.50, 0.25,
-//                    0.50, 1.00, 0.50,
-//                    0.25, 0.50, 0.25
-//            };
-//            grid.Convolve2D(vicinity, linear_filter, multiplier);
-//            delete[] linear_filter;
-
-            // Convolve with gaussian filter
-//            int vicinity = 1;
-//            double* gaussian_filter = new double[9] {
-//                    0.002284, 0.043222, 0.002284,
-//                    0.043222, 0.817976, 0.043222,
-//                    0.002284, 0.043222, 0.002284
-//            };
-//            grid.Convolve2D(vicinity, gaussian_filter, 1.0);
-//            delete[] gaussian_filter;
             grid.Convolve2D(filter);
 
             util::Logger::LogDebug("create graph");
@@ -173,19 +154,27 @@ namespace algo
 
             util::Logger::LogDebug("extract tracks");
             VertexValueMap values = boost::get(boost::vertex_name, graph);
-            for (auto path : paths)
+
+            util::Logger::LogDebug("");
+            for (auto p : paths)
             {
+                std::string path_string = "";
                 core::TrackletPtr tlt(new core::Tracklet());
-                for (auto v : path)
+                for (auto v : p)
                 {
+                    path_string += std::to_string(v) + " ";
                     tlt->AddPathObject(values[v]);
                 }
                 tracks.push_back(tlt);
+                util::Logger::LogDebug(path_string);
             }
+            util::Logger::LogDebug("");
+
+            batch_count++;
         }
 
         // Only connect tracks if the sequence was split
-        if (batch_size < sequence.GetFrameCount())
+        if (batch_count > 1)
         {
             //TODO find a better way to connect tracks (n-stage)
             util::Logger::LogDebug("connect tracks");

+ 4 - 1
algo/KShortestPaths.cpp

@@ -367,6 +367,8 @@ namespace algo
         // All found paths
         MultiPredecessorMap k_orig_paths;
 
+        util::Logger::LogDebug("find the 1. path (in the original graph)");
+
         // Find the first path (only path found in the original graph)
         VertexDistanceMap orig_distances;
         VertexPredecessorMap orig_first_path;
@@ -481,7 +483,8 @@ namespace algo
                 boost::add_edge(source, target, weight, trans_graph);
             }
 
-            util::Logger::LogDebug("find the second path (in the copied and transformed graph)");
+            util::Logger::LogDebug("find the " + std::to_string(i + 1) +
+                                           ". path (in the copied and transformed graph)");
 
             // Find the next path in the transformed graph
             VertexPredecessorMap trans_next_path;

+ 9 - 6
algo/NStage.cpp

@@ -10,16 +10,19 @@ namespace algo
 {
     NStage::NStage(std::vector<size_t> max_frame_skip,
                    std::vector<double> penalty_value,
-                   std::vector<size_t> max_tracklet_count)
+                   std::vector<size_t> max_tracklet_count,
+                   double edge_weight_threshold)
     {
         max_frame_skips_ = max_frame_skip;
         penalty_values_ = penalty_value;
         max_tracklet_counts_ = max_tracklet_count;
         iterations_ = std::min(max_tracklet_count.size(), penalty_value.size());
+        edge_weight_threshold_ = edge_weight_threshold;
     }
 
-    void NStage::CreateObjectGraph(DirectedGraph& graph, const core::DetectionSequence& detections)
+    void NStage::CreateObjectGraph(DirectedGraph & graph, core::DetectionSequence & detections)
     {
+        //TODO constraints to only create necessary
         util::Logger::LogInfo("Creating object graph");
 
         std::vector<std::vector<Vertex>> layers;
@@ -66,9 +69,9 @@ namespace algo
                     {
                         Vertex v = layers[i + k][l];
 
-                        boost::add_edge(u, v,
-                                        values[u]->CompareTo(values[v]),
-                                        graph);
+                        double weight = values[u]->CompareTo(values[v]);
+                        if (weight < edge_weight_threshold_)
+                            boost::add_edge(u, v, weight, graph);
                     }
                 }
 
@@ -246,7 +249,7 @@ namespace algo
         util::Logger::LogDebug("track count " + std::to_string(tracks.size()));
     }
 
-    void NStage::Run(const core::DetectionSequence& sequence,
+    void NStage::Run(core::DetectionSequence & sequence,
                      std::vector<core::TrackletPtr>& tracks)
     {
         // Running the two stage graph algorithm

+ 18 - 6
algo/NStage.h

@@ -38,43 +38,55 @@ namespace algo
          */
         size_t iterations_;
 
+        /**
+         * The maximum edge weights the edge can have to be created in the initial graph building
+         */
+        double edge_weight_threshold_;
+
         /**
          * Creates a graph with vertices for every detected object
+         *
          * @param graph The graph to write into
          * @param detections The objects to use for the graph
          */
-        void CreateObjectGraph(DirectedGraph& graph, const core::DetectionSequence& detections);
+        void CreateObjectGraph(DirectedGraph & graph, core::DetectionSequence & detections);
 
         /**
          * Reduces the object graph into linked tracklets.
+         *
          * @param obj_graph The object graph to reduce
          * @param tlt_graph The graph to write the tracklets in
          * @param frame_count The frame count of the object graph
          * @param iteration The current iteration
          */
-        void CreateTrackletGraph(DirectedGraph& obj_graph, DirectedGraph& tlt_graph,
+        void CreateTrackletGraph(DirectedGraph & obj_graph, DirectedGraph & tlt_graph,
                                  size_t frame_count, size_t iteration);
 
         /**
          * Extracts the finished tracks from the given tracklet graph.
+         *
          * @param tlt_graph The tracklet graph to extract from
          * @param depth The depth to flatten the tracklets to
          * @param tracks The vector to write the extracted tracks in
          */
         void ExtractTracks(DirectedGraph& tlt_graph, size_t depth,
-                           std::vector<core::TrackletPtr>& tracks);
+                           std::vector<core::TrackletPtr> & tracks);
     public:
         /**
          * Initializes the algorithm wih the given values.
          * The number of stages is determined by the size of the given
          * vectors.
+         *
          * @param max_frame_skip The maximum edge length to link objects
          * @param penalty_value The edge value to link to source and sink
          * @param max_tracklet_count The maximum number of tracklets to create
+         * @param edge_weight_threshold The maximum weight an edge can have in the initial graph,
+         *                              edges with higher weights are discarded
          */
         NStage(std::vector<size_t> max_frame_skip,
                std::vector<double> penalty_value,
-               std::vector<size_t> max_tracklet_count);
+               std::vector<size_t> max_tracklet_count,
+               double edge_weight_threshold);
 
         /**
          * Runs the algorithm on the specified sequence and stores the found tracks into the
@@ -83,8 +95,8 @@ namespace algo
          * @param sequence The detection values to use
          * @param tracks A vector to store the found tracks in
          */
-        void Run(const core::DetectionSequence& sequence,
-                 std::vector<core::TrackletPtr>& tracks);
+        void Run(core::DetectionSequence & sequence,
+                 std::vector<core::TrackletPtr> & tracks);
     };
 }
 

+ 33 - 12
core/DetectionSequence.cpp

@@ -9,16 +9,33 @@ namespace core
     DetectionSequence::DetectionSequence(const std::string& name)
     {
         name_ = name;
-        objects_ = std::vector<std::vector<ObjectDataPtr>>();
+        //TODO ORIGINAL
+//        objects_ = std::vector<std::vector<ObjectDataPtr>>();
+        frame_offset_ = std::numeric_limits<size_t>::max();
+        frame_count_ = 0;
     }
 
     void DetectionSequence::AddObject(ObjectDataPtr object_data)
     {
-        while (object_data->GetFrameIndex() >= objects_.size())
+        size_t frame = object_data->GetFrameIndex();
+
+        objects_[frame].push_back(object_data);
+
+        if (!object_data->IsVirtual())
         {
-            objects_.push_back(std::vector<ObjectDataPtr>());
+            if (frame < frame_offset_)
+                frame_offset_ = frame;
+
+            if (frame > frame_count_)
+                frame_count_ = frame;
         }
-        objects_[object_data->GetFrameIndex()].push_back(object_data);
+
+        //TODO ORIGINAL
+//        while (object_data->GetFrameIndex() >= objects_.size())
+//        {
+//            objects_.push_back(std::vector<ObjectDataPtr>());
+//        }
+//        objects_[object_data->GetFrameIndex()].push_back(object_data);
     }
 
     void DetectionSequence::Clear()
@@ -31,29 +48,28 @@ namespace core
         return name_;
     }
 
-    ObjectDataPtr DetectionSequence::GetObject
-            (size_t frame_index, size_t object_index) const
+    ObjectDataPtr DetectionSequence::GetObject(size_t frame_index, size_t object_index)
     {
         return objects_[frame_index][object_index];
     }
 
     size_t DetectionSequence::GetFrameCount() const
     {
-        return objects_.size();
+        return frame_count_;
     }
 
-    size_t DetectionSequence::GetObjectCount(size_t frame_index) const
+    size_t DetectionSequence::GetObjectCount(size_t frame_index)
     {
         return objects_[frame_index].size();
     }
 
-    std::ostream& operator<<(std::ostream& os, const DetectionSequence& obj)
+    std::ostream & operator<<(std::ostream & os, DetectionSequence const & obj)
     {
-        for (size_t frame = 0; frame < obj.objects_.size(); ++frame)
+        for (auto frame : obj.objects_)
         {
-            os << "Frame: " << frame << std::endl;
+            os << "Frame: " << frame.first << std::endl;
 
-            for (auto obj_in_frame : obj.objects_[frame])
+            for (auto obj_in_frame : frame.second)
             {
                 os << *obj_in_frame << std::endl;
             }
@@ -61,4 +77,9 @@ namespace core
 
         return os;
     }
+
+    size_t DetectionSequence::GetFrameOffset() const
+    {
+        return frame_offset_;
+    }
 }

+ 31 - 6
core/DetectionSequence.h

@@ -28,17 +28,31 @@ namespace core
          * The first dimension is the frame.
          * The second dimension is the object in that frame.
          */
-        std::vector<std::vector<ObjectDataPtr>> objects_;
+        std::unordered_map<size_t, std::vector<ObjectDataPtr>> objects_;
+        //TODO ORIGINAL
+//        std::vector<std::vector<ObjectDataPtr>> objects_;
+
+        /**
+         * The frame offset for the first detection
+         */
+        size_t frame_offset_;
+
+        /**
+         * The frame count
+         */
+        size_t frame_count_;
     public:
         /**
          * Creates a detection sequence with the given name.
+         *
          * @param name The name of this sequence
          */
-        DetectionSequence(const std::string& name = "DetectionSequence");
+        DetectionSequence(std::string const & name = "DetectionSequence");
 
         /**
          * Adds a new object, creates a new frame vector if the given objects
          * frame index is greater than the current frame vector size.
+         *
          * @param object_data The object to add
          */
         void AddObject(ObjectDataPtr object_data);
@@ -50,39 +64,50 @@ namespace core
 
         /**
          * Gets the name of this sequence.
+         *
          * @return The name
          */
         std::string GetName() const;
 
         /**
          * Gets a pointer to the object in the given frame with the given index.
+         *
          * @param frame_index The frame to get the object from
          * @param object_index The objects index in the corresponding frame
          * @return A pointer to the stored object data
          */
-        ObjectDataPtr GetObject(size_t frame_index, size_t object_index) const;
+        ObjectDataPtr GetObject(size_t frame_index, size_t object_index);
 
         /**
          * Gets the frame count.
+         *
          * @return The frame count
          */
         size_t GetFrameCount() const;
 
+        /**
+         * Gets the frame offset.
+         *
+         * @return The Frame offset
+         */
+        size_t GetFrameOffset() const;
+
         /**
          * Gets the object count in the given frame.
+         *
          * @param frame_index The frame to get the object count of
          * @return The number of objects in this frame
          */
-        size_t GetObjectCount(size_t frame_index) const;
+        size_t GetObjectCount(size_t frame_index);
 
         /**
          * Overrides the << operator for easy output.
+         *
          * @param os The stream to write to
          * @param obj The object to write into the stream
          * @return The stream written to
          */
-        friend std::ostream& operator<<(std::ostream& os,
-                                        const DetectionSequence& obj);
+        friend std::ostream & operator<<(std::ostream & os, DetectionSequence const & obj);
     };
 }
 

+ 5 - 0
core/ObjectData.cpp

@@ -81,6 +81,11 @@ namespace core
     {
         return detection_score_;
     }
+
+    std::string ObjectData::ToString(char delimiter) const
+    {
+        return std::to_string(frame_index_);
+    }
 }
 
 

+ 8 - 0
core/ObjectData.h

@@ -122,6 +122,14 @@ namespace core
          * @return The stream written to
          */
         friend std::ostream& operator<<(std::ostream& os, const ObjectData& obj);
+
+        /**
+         * Returns a string representing the values of this object data.
+         *
+         * @param delimiter The delimiter used to separate values
+         * @return The string containing the values
+         */
+        virtual std::string ToString(char delimiter) const;
     };
 }
 

+ 8 - 2
core/ObjectData2D.cpp

@@ -76,10 +76,16 @@ namespace core
 
     void ObjectData2D::Visualize(cv::Mat& image, cv::Scalar& color) const
     {
-        double x = position_.x * image.cols;
-        double y = position_.y * image.rows;
+        double x = position_.x;
+        double y = position_.y;
         int r = (int) (0.005 * (image.rows + image.cols) * 0.5);
 
         cv::circle(image, cv::Point2d(x, y), r, color);
     }
+
+    std::string ObjectData2D::ToString(char delimiter) const
+    {
+        return ObjectData::ToString(delimiter) + delimiter +
+                std::to_string(position_.x) + delimiter + std::to_string(position_.y);
+    }
 }

+ 2 - 2
core/ObjectData2D.h

@@ -75,9 +75,9 @@ namespace core
         double GetSpatialWeight() const;
 
         virtual double CompareTo(ObjectDataPtr obj) const override;
-        virtual ObjectDataPtr Interpolate(ObjectDataPtr obj,
-                                          double fraction) const override;
+        virtual ObjectDataPtr Interpolate(ObjectDataPtr obj, double fraction) const override;
         virtual void Visualize(cv::Mat& image, cv::Scalar& color) const override;
+        virtual std::string ToString(char delimiter) const override;
     };
 }
 

+ 5 - 0
core/ObjectDataAngular.cpp

@@ -94,4 +94,9 @@ namespace core
         << "y:" << GetPosition().y << ", "
         << "a:" << GetAngle() << "}";
     }
+
+    std::string ObjectDataAngular::ToString(char delimiter) const
+    {
+        return ObjectData2D::ToString(delimiter) + delimiter + std::to_string(angle_);
+    }
 }

+ 1 - 0
core/ObjectDataAngular.h

@@ -75,6 +75,7 @@ namespace core
         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;
+        virtual std::string ToString(char delimiter) const override;
     };
 }
 

+ 6 - 0
core/ObjectDataBox.cpp

@@ -71,4 +71,10 @@ namespace core
     {
         return size_;
     }
+
+    std::string ObjectDataBox::ToString(char delimiter) const
+    {
+        return ObjectData2D::ToString(delimiter) + delimiter +
+                std::to_string(size_.x) + delimiter + std::to_string(size_.y);
+    }
 }

+ 1 - 0
core/ObjectDataBox.h

@@ -44,6 +44,7 @@ namespace core
         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;
+        virtual std::string ToString(char delimiter) const override;
     };
 }
 

+ 7 - 0
core/Tracklet.cpp

@@ -48,6 +48,9 @@ namespace core
                      iter != path_objects_.end() && !inserted;
                      ++iter)
                 {
+                    // If the frame index is the same, either overwrite the value or do nothing
+                    // If the frame index is smaller than the stored, the new object should be
+                    // inserted here to accomplish a frame index order
                     if ((*iter)->GetFrameIndex() == obj->GetFrameIndex())
                     {
                         if (overwrite)
@@ -65,11 +68,14 @@ namespace core
                 }
             }
 
+            // If the frame index is higher than all already stored object, the new object is
+            // simple added at the end to preserve the ascending frame index order
             if (!inserted)
             {
                 path_objects_.push_back(obj);
             }
 
+            // Update the lowest and highest frame index fields
             SetFrameIndex(path_objects_.front()->GetFrameIndex());
             last_frame_index_ = path_objects_.back()->GetFrameIndex();
         }
@@ -121,6 +127,7 @@ namespace core
         }
     }
 
+    //TODO find a better method than linear interpolation
     void Tracklet::InterpolateMissingFrames()
     {
         for (size_t i = 1; i < path_objects_.size(); ++i)

+ 4 - 7
core/Tracklet.h

@@ -82,13 +82,6 @@ namespace core
          */
         void InterpolateMissingFrames();
 
-        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;
-
         /**
          * Visualizes the tracklet by visualizing the path object in the given
          * frame and the number of path objects in the given range before and
@@ -127,6 +120,10 @@ namespace core
          * @return A pointer to the detection in the given frame
          */
         ObjectDataPtr GetFrameObject(size_t frame_index);
+
+        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;
     };
 }
 

+ 55 - 29
main/main.cpp

@@ -20,6 +20,7 @@ struct
     std::string max_frame_skip;
     std::string max_tracklet_count;
     std::string penalty_value;
+    double edge_weight_threshold;
 } n_stage_params;
 
 void RunNStage(core::DetectionSequence& sequence, std::vector<core::TrackletPtr>& tracks)
@@ -79,8 +80,9 @@ void RunNStage(core::DetectionSequence& sequence, std::vector<core::TrackletPtr>
     }
     while (d_index != std::string::npos);
 
-    // Init n stage
-    algo::NStage n_stage(max_frame_skips, penalty_values, max_tracklet_counts);
+    // Init n-stage
+    algo::NStage n_stage(max_frame_skips, penalty_values, max_tracklet_counts,
+                         n_stage_params.edge_weight_threshold);
 
     n_stage.Run(sequence, tracks);
 
@@ -103,7 +105,7 @@ struct
     util::Filter2D filter;
 } berclaz_params;
 
-void RunBerclaz(core::DetectionSequence& sequence, std::vector<core::TrackletPtr>& tracks)
+void RunBerclaz(core::DetectionSequence & sequence, std::vector<core::TrackletPtr> & tracks)
 {
     util::Logger::LogInfo("Running berclaz");
 
@@ -133,7 +135,7 @@ void Run(int argc, char const * const * argv)
     // Algorithm independent values
     std::string input_file, output_path, images_folder, algorithm, config_path, header;
     std::string input_format, berclaz_filter;
-    bool info, debug, display, output, output_images;
+    bool info, debug, display, output, output_images, show_grid;
     char input_delimiter, output_delimiter;
     double temporal_weight, spatial_weight, angular_weight, image_width, image_height;
 
@@ -149,54 +151,58 @@ void Run(int argc, char const * const * argv)
              boost::program_options::value<bool>(&debug)
                      ->default_value(false),
              "if the program should show debug messages")
-            ("display",
+            ("display.enabled",
              boost::program_options::value<bool>(&display)
                      ->default_value(false),
              "if a window with the images and the detected tracks should be opened")
-            ("output",
-             boost::program_options::value<bool>(&output)
+            ("display.show-grid",
+             boost::program_options::value<bool>(&show_grid)
                      ->default_value(false),
-             "if the results should be written into the specified output folder")
-            ("output-images",
-             boost::program_options::value<bool>(&output_images)
-                     ->default_value(false),
-             "if the images containing the visualized detections should be written to the output")
+             "if a grid should be shown in the visualized tracks (will only be shown if a resolution is given)")
             ("config",
              boost::program_options::value<std::string>(&config_path),
              "the path to the config file, if no path is given the command line arguments are read")
-            ("input-file",
+            ("input.file",
              boost::program_options::value<std::string>(&input_file),
              "set detections file path")
-            ("output-path",
+            ("output.enabled",
+             boost::program_options::value<bool>(&output)
+                     ->default_value(false),
+             "if the results should be written into the specified output folder")
+            ("output.images",
+             boost::program_options::value<bool>(&output_images)
+                     ->default_value(false),
+             "if the images containing the visualized detections should be written to the output")
+            ("output.path",
              boost::program_options::value<std::string>(&output_path),
              "set the output file path")
-            ("output-delimiter",
+            ("output.delimiter",
              boost::program_options::value<char>(&output_delimiter)
                     ->default_value(';'),
              "the delimiter used to separate values in the specified output file")
-            ("images-folder",
+            ("input.images-folder",
              boost::program_options::value<std::string>(&images_folder),
              "set images folder path")
-            ("input-header",
+            ("input.header",
              boost::program_options::value<std::string>(&header),
              "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")
-            ("input-format",
+            ("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",
+            ("input.delimiter",
              boost::program_options::value<char>(&input_delimiter)
                      ->default_value(';'),
              "the delimiter used to separate values in the specified input file")
-            ("image-width",
+            ("input.image-width",
              boost::program_options::value<double>(&image_width)
-                     ->default_value(1),
+                     ->default_value(1.0),
              "the width of the image")
-            ("image-height",
+            ("input.image-height",
              boost::program_options::value<double>(&image_height)
-                     ->default_value(1),
+                     ->default_value(1.0),
              "the height of the image")
             ("algorithm",
              boost::program_options::value<std::string>(&algorithm),
@@ -226,11 +232,16 @@ void Run(int argc, char const * const * argv)
              boost::program_options::value<double>(&angular_weight)
                      ->default_value(1.0),
              "(n-stage) angular weight for difference calculations between two detections")
-            ("berclaz.horizontal-resolution",
+            ("n-stage.edge-weight-threshold",
+             boost::program_options::value<double>(&n_stage_params.edge_weight_threshold)
+                     ->default_value(1.0),
+             "(n-stage) the maximum weight an edge can have in the initial graph, edges with"
+                     "higher edge weights are discarded")
+            ("berclaz.h-res",
              boost::program_options::value<int>(&berclaz_params.h_res)
                      ->default_value(10),
              "(berclaz) the number of horizontal grid cells")
-            ("berclaz.vertical-resolution",
+            ("berclaz.v-res",
              boost::program_options::value<int>(&berclaz_params.v_res)
                      ->default_value(10),
              "(berclaz) the number of vertical grid cells")
@@ -314,10 +325,12 @@ void Run(int argc, char const * const * argv)
     {
         if (header.size() > 0)
         {
+            util::Logger::LogDebug("header specified");
             util::FileIO::ReadCSV(values, header, input_file, input_delimiter);
         }
         else
         {
+            util::Logger::LogDebug("read header from file");
             util::FileIO::ReadCSV(values, input_file, input_delimiter);
         }
     }
@@ -368,14 +381,23 @@ void Run(int argc, char const * const * argv)
     // Running the specified algorithm
     std::vector<core::TrackletPtr> tracks;
     time_t begin_time, end_time;
+    std::string output_file_name = algorithm + "_";
     util::Logger::LogInfo("Start time measurement");
     begin_time = time(0);
     if (algorithm == "n-stage")
     {
+        //TODO set the output file name
+
         RunNStage(sequence, tracks);
     }
     else if (algorithm == "berclaz")
     {
+        output_file_name += std::to_string(berclaz_params.h_res) + "x"
+                            + std::to_string(berclaz_params.v_res) + "_"
+                            + std::to_string(berclaz_params.vicinity_size) + "_"
+                            + std::to_string(berclaz_params.max_track_count) + "_"
+                            + std::to_string(berclaz_params.batch_size);
+
         berclaz_params.filter = util::Filter2D(berclaz_filter, ',');
         RunBerclaz(sequence, tracks);
     }
@@ -385,6 +407,7 @@ void Run(int argc, char const * const * argv)
         std::cout << opts << std::endl;
         exit(0);
     }
+    output_file_name += ".csv";
 
     end_time = time(0);
     util::Logger::LogInfo("Time measurement stopped");
@@ -395,7 +418,7 @@ void Run(int argc, char const * const * argv)
     // Write the output file
     if (output)
     {
-        util::FileIO::WriteTracks(tracks, output_path + "/tracks.csv", output_delimiter);
+        util::FileIO::WriteTracks(tracks, output_path + "/" + output_file_name, output_delimiter);
     }
 
     // Display the tracking data
@@ -404,10 +427,12 @@ void Run(int argc, char const * const * argv)
         util::Visualizer vis;
 
         if (algorithm == "berclaz")
-            vis.Display(tracks, images_folder, output_images, output_path, "Visualizer",
-                        0, 24, berclaz_params.h_res, berclaz_params.v_res);
+            vis.Display(tracks, sequence.GetFrameOffset(),
+                        images_folder, output_images, output_path, "Visualizer",
+                        0, 24, show_grid, berclaz_params.h_res, berclaz_params.v_res);
         else
-            vis.Display(tracks, images_folder, output_images, output_path);
+            vis.Display(tracks, sequence.GetFrameOffset(),
+                        images_folder, output_images, output_path);
     }
 }
 
@@ -928,6 +953,7 @@ int main(int argc, char const * const * argv)
 {
     //TODO load with frame offset
     //TODO check visualizer for offset errors
+    //TODO check why SEGFAULT is caused by some berclaz resolutions
 
     Run(argc, argv);
 

+ 17 - 59
util/FileIO.cpp

@@ -220,6 +220,8 @@ namespace util
         in.close();
 
         ReadCSV(values, line, file_name, delimiter);
+
+        //TODO do not read the first line
     }
 
     void FileIO::ReadCSV(ValueMapVector& values, const std::string& header,
@@ -310,8 +312,8 @@ namespace util
         in.close();
     }
 
-    void FileIO::WriteTracks(std::vector<core::TrackletPtr>& tracks, const std::string& file_name,
-                             char delimiter)
+    void FileIO::WriteTracks(std::vector<core::TrackletPtr> & tracks,
+                             std::string const & file_name, char delimiter)
     {
         // Get the frame range
         size_t first_frame = tracks[0]->GetFirstFrameIndex();
@@ -326,82 +328,38 @@ namespace util
 
         std::ofstream out(file_name, std::ios::out);
 
+        // Check if the file is open
         if (!out.is_open())
         {
             util::Logger::LogError("Unable to open file: " + file_name);
             return;
         }
 
+        // Print every track, one detection per line, sorted by frame
         for (size_t frame = first_frame; frame <= last_frame; ++frame)
         {
             for (size_t i = 0; i < tracks.size(); ++i)
             {
-                core::ObjectData2DPtr obj =
-                        std::static_pointer_cast<core::ObjectData2D>(tracks[i]->GetFrameObject(frame));
+                core::ObjectDataPtr obj = tracks[i]->GetFrameObject(frame);
 
                 if (obj != nullptr)
                 {
-                    out << obj->GetPosition().x << delimiter;
-                    out << obj->GetPosition().y;
-                }
-                else
-                {
-                    out << delimiter;
-                }
-
-                if (i < (tracks.size() - 1))
-                {
-                    out << delimiter;
-                }
-            }
-
-            out << std::endl;
-        }
-
-        out.close();
-    }
-
-    void FileIO::ReadTracks(std::vector<core::TrackletPtr>& tracks, const std::string& file_name,
-                            char delimiter)
-    {
-        std::ifstream in(file_name, std::ios::in);
-
-        if (!in.is_open())
-        {
-            util::Logger::LogError("Unable to open file: " + file_name);
-            return;
-        }
-
-        std::string line;
-        size_t line_index = 0;
-        while (in.good() && !in.eof())
-        {
-            getline(in, line);
-
-            if (line.size() == 0) continue;
-
-            std::vector<std::string> parts = Split(line, delimiter);
+                    std::string str = obj->ToString(delimiter);
+                    std::vector<std::string> parts = Split(str, delimiter);
+                    parts.insert(parts.begin() + 1, std::to_string(i + 1));
 
-            while (tracks.size() < (parts.size() / 2))
-            {
-                tracks.push_back(core::TrackletPtr(new core::Tracklet()));
-            }
-
-            for (size_t i = 1; i < parts.size(); i += 2)
-            {
-                if (!parts[i - 1].empty() && !parts[i].empty())
-                {
-                    cv::Point2d point(std::stod(parts[i - 1]), std::stod(parts[i]));
+                    out << parts[0];
+                    for (size_t j = 1; j < parts.size(); ++j)
+                    {
+                        out << delimiter << parts[j];
+                    }
 
-                    tracks[(i - 1) / 2]->AddPathObject(
-                            core::ObjectData2DPtr(new core::ObjectData2D(line_index, point)));
+                    out << std::endl;
                 }
             }
-
-            line_index++;
         }
 
-        in.close();
+        out.close();
     }
 
     std::vector<std::string> FileIO::Split(const std::string& input, char delimiter)

+ 1 - 1
util/Filter2D.cpp

@@ -51,7 +51,7 @@ namespace util
 
     int Filter2D::Index(int x, int y) const
     {
-        return static_cast<int>(y * mask_.size() + x);
+        return y * dimension_ + x;
     }
 
     int Filter2D::Vicinity(int count) const

+ 8 - 8
util/Logger.h

@@ -35,29 +35,29 @@ namespace util
          * Logs the given message.
          * @param message The message to log
          */
-        void LogMessage(const std::string& message);
+        void LogMessage(std::string const & message);
 
         /**
          * Logs the given error message.
          * @param message The error message to log
          */
-        void LogErrorMessage(const std::string& message);
+        void LogErrorMessage(std::string const & message);
     public:
         /**
          * -> Singleton
          */
-        Logger(Logger const&) = delete;
+        Logger(Logger const &) = delete;
 
         /**
          * -> Singleton
          */
-        void operator=(Logger const&) = delete;
+        void operator=(Logger const &) = delete;
 
         /**
          * Gets THE instance of this singleton.
          * Creates a new instance if not already created.
          */
-        static Logger& Instance()
+        static Logger & Instance()
         {
             static Logger instance;
             return instance;
@@ -91,19 +91,19 @@ namespace util
          * Logs the given message as an info message.
          * @param message The info message to log
          */
-        static void LogInfo(const std::string& message);
+        static void LogInfo(std::string const & message);
 
         /**
          * Logs the given message as an error message.
          * @param message The error message to log
          */
-        static void LogError(const std::string& message);
+        static void LogError(std::string const & message);
 
         /**
          * Logs the given message as an debug message.
          * @param message The debug message to log
          */
-        static void LogDebug(const std::string& message);
+        static void LogDebug(std::string const & message);
     };
 }
 

+ 9 - 6
util/Parser.cpp

@@ -10,12 +10,14 @@
 
 namespace util
 {
+    //TODO sigmoid function for detection score smoothing
+
     //TODO rename if necessary
     const std::string Parser::KEY_FRAME = "frame";
     const std::string Parser::KEY_ID = "id";
     const std::string Parser::KEY_SCORE = "score";
-    const std::string Parser::KEY_X = "x";
-    const std::string Parser::KEY_Y = "y";
+    const std::string Parser::KEY_X = "xc";
+    const std::string Parser::KEY_Y = "yc";
     const std::string Parser::KEY_WIDTH = "width";
     const std::string Parser::KEY_HEIGHT = "height";
     const std::string Parser::KEY_ANGLE = "angle";
@@ -72,6 +74,7 @@ namespace util
         }
 
         util::Logger::LogDebug("objects parsed " + std::to_string(obj_count));
+        util::Logger::LogDebug("frame offset " + std::to_string(sequence.GetFrameOffset()));
         util::Logger::LogDebug("frame count " + std::to_string(sequence.GetFrameCount()));
     }
 
@@ -138,6 +141,7 @@ namespace util
         }
 
         util::Logger::LogDebug("objects parsed " + std::to_string(obj_count));
+        util::Logger::LogDebug("frame offset " + std::to_string(sequence.GetFrameOffset()));
         util::Logger::LogDebug("frame count " + std::to_string(sequence.GetFrameCount()));
     }
 
@@ -183,13 +187,11 @@ namespace util
             cv::Point2d point(x, y);
             cv::Point2d size(width, height);
 
-            core::ObjectDataBoxPtr object(
-                    new core::ObjectDataBox(frame, point, size));
+            core::ObjectDataBoxPtr object(new core::ObjectDataBox(frame, point, size));
 
             object->SetTemporalWeight(temporal_weight);
             object->SetSpatialWeight(spatial_weight);
-            object->SetDetectionScore(
-                    util::MyMath::InverseLerp(min_score, max_score, score));
+            object->SetDetectionScore(util::MyMath::InverseLerp(min_score, max_score, score));
 
             sequence.AddObject(object);
 
@@ -197,6 +199,7 @@ namespace util
         }
 
         util::Logger::LogDebug("objects parsed " + std::to_string(obj_count));
+        util::Logger::LogDebug("frame offset " + std::to_string(sequence.GetFrameOffset()));
         util::Logger::LogDebug("frame count " + std::to_string(sequence.GetFrameCount()));
     }
 

+ 7 - 6
util/Visualizer.cpp

@@ -15,10 +15,10 @@ namespace util
                 std::chrono::system_clock::now().time_since_epoch()).count();
     }
 
-    void Visualizer::Display(std::vector<core::TrackletPtr>& tracks,
+    void Visualizer::Display(std::vector<core::TrackletPtr> & tracks, size_t frame_offset,
                              std::string image_folder, bool output,
                              std::string output_path, std::string title, size_t first_frame,
-                             int play_fps, int grid_width, int grid_height)
+                             int play_fps, bool show_grid, int grid_width, int grid_height)
     {
         util::Logger::LogInfo("Displaying data");
 
@@ -32,6 +32,7 @@ namespace util
         std::vector<cv::Scalar> colors;
         std::random_device rd;
         std::mt19937 gen(rd());
+        //TODO find better colors (more colors)
         colors.push_back(cv::Scalar(0, 255, 0));
         colors.push_back(cv::Scalar(0, 0, 255));
         colors.push_back(cv::Scalar(0, 255, 255));
@@ -75,8 +76,8 @@ namespace util
             // Display image
             cv::Mat image = cv::imread(image_folder + "/" + image_files[current_frame], 1);
 
-            // Draw grid
-            if (grid_width > 0 && grid_height > 0)
+            // Draw grid if resolution is specified
+            if (show_grid && grid_width > 0 && grid_height > 0)
             {
                 cv::Scalar gridColor(255, 255, 255);
                 double cellWidth = image.cols / grid_width;
@@ -93,10 +94,10 @@ namespace util
                 }
             }
 
-            //Visualize the tracklets
+            // Visualize the tracklets
             for (size_t i = 0; i < tracks.size(); ++i)
             {
-                tracks[i]->Visualize(image, colors[i], current_frame, 0, 0);
+                tracks[i]->Visualize(image, colors[i], current_frame + frame_offset, 0, 0);
             }
 
             cv::imshow(title, image);

+ 5 - 3
util/Visualizer.h

@@ -31,23 +31,25 @@ namespace util
          * Displays the given tracks in an window.
          * Use D for next frame, A for previous frame, F to toggle auto play and
          * ESC to exit.
-         * If a grid size greater zero is specified a grid will be overlayed.
+         * If a grid size greater zero is specified a grid will be drawn.
          *
          * @param tracks The tracks to display
+         * @param frame_offset The offset of the first frame
          * @param image_folder The images to use
          * @param output If the frames with the visualized tracks should be stored
          * @param output_path The path to store the images into (will need an images folder)
          * @param title The window title
          * @param first_frame The frame to start at
          * @param play_fps The FPS to use when auto play is activated
+         * @param If a grid should be shown
          * @param grid_width The number of cells in a row
          * @param grid_height The number of cells in a column
          */
-        void Display(std::vector<core::TrackletPtr>& tracks,
+        void Display(std::vector<core::TrackletPtr> & tracks, size_t frame_offset,
                      std::string image_folder, bool output,
                      std::string output_path, std::string title = "Visualizer",
                      size_t first_frame = 0, int play_fps = 24,
-                     int grid_width = 0, int grid_height = 0);
+                     bool show_grid = false, int grid_width = 0, int grid_height = 0);
     };
 }