|
@@ -4,88 +4,113 @@
|
|
|
#include "../core/DetectionSequence.h"
|
|
|
#include "../util/FileIO.h"
|
|
|
#include "../util/Parser.h"
|
|
|
-#include "../algo/TwoStage.h"
|
|
|
+#include "../algo/NStage.h"
|
|
|
#include "../algo/KShortestPaths.h"
|
|
|
-#include "../visual/Visualizer.h"
|
|
|
+#include "../util/Visualizer.h"
|
|
|
#include "../util/Logger.h"
|
|
|
#include "../core/ObjectDataAngular.h"
|
|
|
+#include "../algo/Berclaz.h"
|
|
|
#include <boost/program_options.hpp>
|
|
|
|
|
|
-void ReadInput(const std::string& input_file, core::DetectionSequence& sequence,
|
|
|
- double temporal_weight, double spatial_weight, double angular_weight)
|
|
|
-{
|
|
|
- util::Logger::LogInfo("Reading input");
|
|
|
-
|
|
|
- util::Vector3d values;
|
|
|
- util::FileIO::ReadCSV(values, input_file);
|
|
|
- util::Parser::ParseObjectDataAngular(values, sequence,
|
|
|
- temporal_weight,
|
|
|
- spatial_weight,
|
|
|
- angular_weight);
|
|
|
-
|
|
|
- if (util::Logger::IsDebugEnabled())
|
|
|
- {
|
|
|
- size_t sequence_object_count = 0;
|
|
|
- for (size_t i = 0; i < sequence.GetFrameCount(); i++)
|
|
|
- {
|
|
|
- sequence_object_count += sequence.GetObjectCount(i);
|
|
|
- }
|
|
|
- util::Logger::LogDebug("sequence object count " + std::to_string(sequence_object_count));
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
struct
|
|
|
{
|
|
|
- size_t iterations;
|
|
|
size_t max_frame_skip;
|
|
|
- size_t max_tracklet_count;
|
|
|
- double penalty_value;
|
|
|
-} two_stage_params;
|
|
|
-
|
|
|
-void RunTwoStage(core::DetectionSequence& sequence, const std::string& output_file,
|
|
|
- const std::string& images_folder, bool display)
|
|
|
+ std::string max_tracklet_count;
|
|
|
+ std::string penalty_value;
|
|
|
+} n_stage_params;
|
|
|
+
|
|
|
+void RunNStage(core::DetectionSequence& sequence,
|
|
|
+ const std::string& output_file,
|
|
|
+ const std::string& images_folder,
|
|
|
+ bool display)
|
|
|
{
|
|
|
- util::Logger::LogInfo("Running two-stage");
|
|
|
+ util::Logger::LogInfo("Running n-stage");
|
|
|
|
|
|
- algo::TwoStage two_stage(two_stage_params.max_frame_skip,
|
|
|
- two_stage_params.penalty_value,
|
|
|
- two_stage_params.max_tracklet_count);
|
|
|
+ std::vector<double> penalty_values;
|
|
|
+ std::vector<size_t> max_tracklet_counts;
|
|
|
|
|
|
- // Running the two stage graph algorithm
|
|
|
- DirectedGraph obj_graph;
|
|
|
- two_stage.CreateObjectGraph(obj_graph, sequence);
|
|
|
+ // Parse strings to vectors
|
|
|
+ size_t d_index;
|
|
|
+ std::string str, part;
|
|
|
+ str = n_stage_params.max_tracklet_count;
|
|
|
+ do
|
|
|
+ {
|
|
|
+ d_index = str.find(",");
|
|
|
|
|
|
- // Run the tracklet creation at least once
|
|
|
- DirectedGraph tlt_graph_1, tlt_graph_2;
|
|
|
- two_stage.CreateTrackletGraph(obj_graph, tlt_graph_1,
|
|
|
- sequence.GetFrameCount());
|
|
|
+ part = str.substr(0, d_index);
|
|
|
|
|
|
- // Run the tracklet creation iteratively
|
|
|
- for (size_t i = 1; i < two_stage_params.iterations; ++i)
|
|
|
- {
|
|
|
- if (i % 2 == 0)
|
|
|
+ if (part.size() > 0)
|
|
|
{
|
|
|
- two_stage.CreateTrackletGraph(tlt_graph_2, tlt_graph_1,
|
|
|
- sequence.GetFrameCount());
|
|
|
+ max_tracklet_counts.push_back((unsigned long&&) std::atoi(part.c_str()));
|
|
|
}
|
|
|
- else
|
|
|
+
|
|
|
+ str = str.substr(d_index + 1);
|
|
|
+ }
|
|
|
+ while (d_index != std::string::npos);
|
|
|
+ str = n_stage_params.penalty_value;
|
|
|
+ do
|
|
|
+ {
|
|
|
+ d_index = str.find(",");
|
|
|
+
|
|
|
+ part = str.substr(0, d_index);
|
|
|
+
|
|
|
+ if (part.size() > 0)
|
|
|
{
|
|
|
- two_stage.CreateTrackletGraph(tlt_graph_1, tlt_graph_2,
|
|
|
- sequence.GetFrameCount());
|
|
|
+ penalty_values.push_back(std::atof(part.c_str()));
|
|
|
}
|
|
|
+
|
|
|
+ str = str.substr(d_index + 1);
|
|
|
}
|
|
|
+ while (d_index != std::string::npos);
|
|
|
+
|
|
|
+ // Init n stage
|
|
|
+ algo::NStage n_stage(n_stage_params.max_frame_skip,
|
|
|
+ penalty_values, max_tracklet_counts);
|
|
|
|
|
|
- // Extract tracklets and flatten tracklets
|
|
|
std::vector<core::TrackletPtr> tracks;
|
|
|
- if (two_stage_params.iterations % 2 == 0)
|
|
|
+ n_stage.Run(sequence, tracks);
|
|
|
+
|
|
|
+ // Interpolate tracks
|
|
|
+ for (auto track : tracks)
|
|
|
{
|
|
|
- two_stage.ExtractTracks(tlt_graph_2, two_stage_params.iterations - 1, tracks);
|
|
|
+ track->InterpolateMissingFrames();
|
|
|
}
|
|
|
- else
|
|
|
+
|
|
|
+ // Display the tracking data
|
|
|
+ if (display)
|
|
|
{
|
|
|
- two_stage.ExtractTracks(tlt_graph_1, two_stage_params.iterations - 1, tracks);
|
|
|
+ util::Visualizer vis;
|
|
|
+ vis.Display(tracks, images_folder);
|
|
|
}
|
|
|
|
|
|
+ util::Logger::LogInfo("Finished");
|
|
|
+}
|
|
|
+
|
|
|
+struct
|
|
|
+{
|
|
|
+ int h_res;
|
|
|
+ int v_res;
|
|
|
+ int vicinity_size;
|
|
|
+ size_t max_track_count;
|
|
|
+} berclaz_params;
|
|
|
+
|
|
|
+
|
|
|
+void RunBerclaz(core::DetectionSequence& sequence,
|
|
|
+ const std::string& output_file,
|
|
|
+ const std::string& images_folder,
|
|
|
+ bool display)
|
|
|
+{
|
|
|
+ util::Logger::LogInfo("Running berclaz");
|
|
|
+
|
|
|
+ // Init berclaz
|
|
|
+ algo::Berclaz berclaz(berclaz_params.h_res,
|
|
|
+ berclaz_params.v_res,
|
|
|
+ berclaz_params.vicinity_size);
|
|
|
+ std::vector<core::TrackletPtr> tracks;
|
|
|
+ berclaz.Run(sequence, berclaz_params.max_track_count, tracks);
|
|
|
+
|
|
|
+ util::Logger::LogInfo("Interpolate tracks");
|
|
|
+
|
|
|
// Interpolate tracks
|
|
|
for (auto track : tracks)
|
|
|
{
|
|
@@ -95,9 +120,7 @@ void RunTwoStage(core::DetectionSequence& sequence, const std::string& output_fi
|
|
|
// Display the tracking data
|
|
|
if (display)
|
|
|
{
|
|
|
- util::Logger::LogInfo("Displaying data");
|
|
|
-
|
|
|
- visual::Visualizer vis;
|
|
|
+ util::Visualizer vis;
|
|
|
vis.Display(tracks, images_folder);
|
|
|
}
|
|
|
|
|
@@ -107,91 +130,167 @@ void RunTwoStage(core::DetectionSequence& sequence, const std::string& output_fi
|
|
|
void Run(int argc, char** argv)
|
|
|
{
|
|
|
// Algorithm independent values
|
|
|
- std::string input_file, output_file, images_folder, algorithm;
|
|
|
- bool display;
|
|
|
+ std::string input_file, output_file, images_folder, algorithm, config_path;
|
|
|
+ bool info, debug, display;
|
|
|
|
|
|
// Input dependent variables
|
|
|
+ std::string header;
|
|
|
double temporal_weight, spatial_weight, angular_weight;
|
|
|
+ double image_width, image_height;
|
|
|
|
|
|
boost::program_options::options_description opts("Allowed options");
|
|
|
opts.add_options()
|
|
|
("help",
|
|
|
"produce help message")
|
|
|
("info",
|
|
|
+ boost::program_options::value<bool>(&info)
|
|
|
+ ->default_value(false),
|
|
|
"if the program should show progress information")
|
|
|
("debug",
|
|
|
+ boost::program_options::value<bool>(&debug)
|
|
|
+ ->default_value(false),
|
|
|
"if the program should show debug messages")
|
|
|
+ ("display",
|
|
|
+ boost::program_options::value<bool>(&display)
|
|
|
+ ->default_value(false),
|
|
|
+ "if a window with the images and the detected tracks should be opened")
|
|
|
+ ("config",
|
|
|
+ boost::program_options::value<std::string>(&config_path),
|
|
|
+ "the path to the config file, if no path is given the command line arguments are read")
|
|
|
("input-file,i",
|
|
|
boost::program_options::value<std::string>(&input_file),
|
|
|
"set detections file path")
|
|
|
("output-file,o",
|
|
|
boost::program_options::value<std::string>(&output_file),
|
|
|
"set the output file path")
|
|
|
- ("algorithm,a",
|
|
|
- boost::program_options::value<std::string>(&algorithm),
|
|
|
- "set the algorithm to use, current viable options: two-stage")
|
|
|
- ("display",
|
|
|
- "if a window with the images and the detected tracks should be opened")
|
|
|
("images-folder,f",
|
|
|
boost::program_options::value<std::string>(&images_folder),
|
|
|
"set images folder path")
|
|
|
- ("iterations",
|
|
|
- boost::program_options::value<size_t>(&two_stage_params.iterations)->default_value((2)),
|
|
|
- "(two-stage) number of tracklet extraction iterations")
|
|
|
+ ("input-header",
|
|
|
+ boost::program_options::value<std::string>(&header)
|
|
|
+ ->default_value(""),
|
|
|
+ "sets the input header, this value is optional if the input file has a header labeling the values,"
|
|
|
+ "the delimiter used for the header needs to be the same as for the rest of the file")
|
|
|
+ ("algorithm,a",
|
|
|
+ boost::program_options::value<std::string>(&algorithm),
|
|
|
+ "set the algorithm to use, current viable options: n-stage berclaz")
|
|
|
("max-frame-skip",
|
|
|
- boost::program_options::value<size_t>(&two_stage_params.max_frame_skip)->default_value(1),
|
|
|
- "(two stage) set the maximum number of frames a track can skip between two detections,"
|
|
|
+ boost::program_options::value<size_t>(&n_stage_params.max_frame_skip)
|
|
|
+ ->default_value(1),
|
|
|
+ "(n stage) set the maximum number of frames a track can skip between two detections,"
|
|
|
" if set to less or equal than zero all frames are linked")
|
|
|
("max-tracklet-count",
|
|
|
- boost::program_options::value<size_t>(&two_stage_params.max_tracklet_count)->default_value(1),
|
|
|
- "(two stage) set the maximum number of tracklets to be extracted")
|
|
|
+ boost::program_options::value<std::string>(&n_stage_params.max_tracklet_count)
|
|
|
+ ->default_value("-1,1"),
|
|
|
+ "(n stage) set the maximum number of tracklets to be extracted")
|
|
|
("penalty-value",
|
|
|
- boost::program_options::value<double>(&two_stage_params.penalty_value)->default_value(0.0),
|
|
|
- "(two stage) set the penalty value for edges from and to source and sink")
|
|
|
+ boost::program_options::value<std::string>(&n_stage_params.penalty_value)
|
|
|
+ ->default_value("0,0"),
|
|
|
+ "(n stage) set the penalty value for edges from and to source and sink")
|
|
|
("temporal-weight",
|
|
|
- boost::program_options::value<double>(&temporal_weight)->default_value(1.0),
|
|
|
- "temporal weight for difference calculations between two detections")
|
|
|
+ boost::program_options::value<double>(&temporal_weight)
|
|
|
+ ->default_value(1.0),
|
|
|
+ "(n stage) temporal weight for difference calculations between two detections")
|
|
|
("spatial-weight",
|
|
|
- boost::program_options::value<double>(&spatial_weight)->default_value(1.0),
|
|
|
- "spatial weight for difference calculations between two detections")
|
|
|
+ boost::program_options::value<double>(&spatial_weight)
|
|
|
+ ->default_value(1.0),
|
|
|
+ "(n stage) spatial weight for difference calculations between two detections")
|
|
|
("angular-weight",
|
|
|
- boost::program_options::value<double>(&angular_weight)->default_value(1.0),
|
|
|
- "angular weight for difference calculations between two detections");
|
|
|
+ boost::program_options::value<double>(&angular_weight)
|
|
|
+ ->default_value(1.0),
|
|
|
+ "(n stage) angular weight for difference calculations between two detections")
|
|
|
+ ("horizontal-resolution",
|
|
|
+ boost::program_options::value<int>(&berclaz_params.h_res)
|
|
|
+ ->default_value(10),
|
|
|
+ "(berclaz) the number of horizontal grid cells")
|
|
|
+ ("vertical-resolution",
|
|
|
+ boost::program_options::value<int>(&berclaz_params.v_res)
|
|
|
+ ->default_value(10),
|
|
|
+ "(berclaz) the number of vertical grid cells")
|
|
|
+ ("vicinity-size",
|
|
|
+ boost::program_options::value<int>(&berclaz_params.vicinity_size)
|
|
|
+ ->default_value(1),
|
|
|
+ "(berclaz) the vicinity size, the number of cells a detection can travel between two frames")
|
|
|
+ ("max-track-count",
|
|
|
+ boost::program_options::value<size_t>(&berclaz_params.max_track_count)
|
|
|
+ ->default_value(1),
|
|
|
+ "(berclaz) the maximal number of tracks to extract")
|
|
|
+ ("image-width",
|
|
|
+ boost::program_options::value<double>(&image_width)
|
|
|
+ ->default_value(1920),
|
|
|
+ "the width of the image")
|
|
|
+ ("image-height",
|
|
|
+ boost::program_options::value<double>(&image_height)
|
|
|
+ ->default_value(1080),
|
|
|
+ "the height of the image");
|
|
|
|
|
|
boost::program_options::variables_map opt_var_map;
|
|
|
#pragma clang diagnostic push
|
|
|
#pragma clang diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
|
|
|
- boost::program_options::store(boost::program_options::parse_command_line(argc, argv, opts), opt_var_map);
|
|
|
+ boost::program_options::store(
|
|
|
+ boost::program_options::parse_command_line(argc, argv, opts),
|
|
|
+ opt_var_map);
|
|
|
#pragma clang diagnostic pop
|
|
|
boost::program_options::notify(opt_var_map);
|
|
|
|
|
|
+ // Display help
|
|
|
if (opt_var_map.count("help") != 0)
|
|
|
{
|
|
|
std::cout << opts << std::endl;
|
|
|
exit(0);
|
|
|
}
|
|
|
|
|
|
- if (opt_var_map.count("info") != 0)
|
|
|
+ // Read config
|
|
|
+ if (opt_var_map.count("config") != 0)
|
|
|
+ {
|
|
|
+ std::ifstream config_file(config_path , std::ifstream::in);
|
|
|
+ boost::program_options::store(
|
|
|
+ boost::program_options::parse_config_file(config_file , opts),
|
|
|
+ opt_var_map);
|
|
|
+ config_file.close();
|
|
|
+ boost::program_options::notify(opt_var_map);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Enable info logging
|
|
|
+ if (info != 0)
|
|
|
{
|
|
|
util::Logger::SetInfo(true);
|
|
|
util::Logger::LogInfo("Enabled");
|
|
|
}
|
|
|
|
|
|
- if (opt_var_map.count("debug") != 0)
|
|
|
+ // Enable debug logging
|
|
|
+ if (debug != 0)
|
|
|
{
|
|
|
util::Logger::SetDebug(true);
|
|
|
util::Logger::LogDebug("Enabled");
|
|
|
}
|
|
|
|
|
|
- display = opt_var_map.count("display") != 0;
|
|
|
+ // Reading the input file
|
|
|
+ util::Logger::LogInfo("Reading input");
|
|
|
+ util::ValueMapVector values;
|
|
|
+ if (header.size() > 0)
|
|
|
+ {
|
|
|
+ util::FileIO::ReadCSV(values, header, input_file);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ util::FileIO::ReadCSV(values, input_file);
|
|
|
+ }
|
|
|
|
|
|
+ // Parsing the read input
|
|
|
core::DetectionSequence sequence;
|
|
|
+ util::Parser::ParseObjectDataBox(values, sequence,
|
|
|
+ image_width, image_height,
|
|
|
+ temporal_weight, spatial_weight);
|
|
|
|
|
|
- ReadInput(input_file, sequence, temporal_weight, spatial_weight, angular_weight);
|
|
|
-
|
|
|
- if (algorithm == "two-stage")
|
|
|
+ // Running the specified algorithm
|
|
|
+ if (algorithm == "n-stage")
|
|
|
+ {
|
|
|
+ RunNStage(sequence, output_file, images_folder, display);
|
|
|
+ }
|
|
|
+ else if (algorithm == "berclaz")
|
|
|
{
|
|
|
- RunTwoStage(sequence, output_file, images_folder, display);
|
|
|
+ RunBerclaz(sequence, output_file, images_folder, display);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -235,9 +334,9 @@ void CreateTestGraph(DirectedGraph& graph, Vertex& source, Vertex& sink)
|
|
|
// source = vertices[0];
|
|
|
// sink = vertices[5];
|
|
|
|
|
|
- // Create test graph (disjoint path finding example)
|
|
|
+ // Create test graph
|
|
|
std::vector<Vertex> vertices;
|
|
|
- for (size_t i = 0; i < 8; ++i)
|
|
|
+ for (size_t i = 0; i < 11; ++i)
|
|
|
{
|
|
|
vertices.push_back(
|
|
|
boost::add_vertex(
|
|
@@ -245,51 +344,268 @@ void CreateTestGraph(DirectedGraph& graph, Vertex& source, Vertex& sink)
|
|
|
}
|
|
|
|
|
|
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], 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[3], 1.0, graph);
|
|
|
- boost::add_edge(vertices[4], vertices[5], 3.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], 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);
|
|
|
|
|
|
source = vertices[0];
|
|
|
sink = vertices[7];
|
|
|
}
|
|
|
|
|
|
+void TestKSP()
|
|
|
+{
|
|
|
+ Vertex source, sink;
|
|
|
+ DirectedGraph graph;
|
|
|
+
|
|
|
+ util::Logger::SetDebug(true);
|
|
|
+ util::Logger::SetInfo(true);
|
|
|
+
|
|
|
+ CreateTestGraph(graph, source, sink);
|
|
|
+
|
|
|
+ algo::KShortestPaths ksp(graph, source, sink);
|
|
|
+ MultiPredecessorMap paths = ksp.Run(5);
|
|
|
+
|
|
|
+ util::FileIO::WriteCSVMatlab(graph, "/home/wrede/Dokumente/graph.csv");
|
|
|
+ util::FileIO::WriteCSVMatlab(paths,
|
|
|
+ sink, "/home/wrede/Dokumente/paths.csv");
|
|
|
+}
|
|
|
+
|
|
|
+void TestGrid()
|
|
|
+{
|
|
|
+ int lower_index = 0;
|
|
|
+ int upper_index = 5;
|
|
|
+ double lower_bound = 0.0;
|
|
|
+ double upper_bound = 50.0;
|
|
|
+ util::Grid grid(upper_index, upper_index, upper_index,
|
|
|
+ upper_bound, upper_bound, upper_bound);
|
|
|
+
|
|
|
+ std::uniform_int_distribution<int> unii(lower_index, upper_index - 1);
|
|
|
+ std::uniform_real_distribution<double> unif(lower_bound, upper_bound);
|
|
|
+ std::default_random_engine re;
|
|
|
+
|
|
|
+ // Fill with empty values
|
|
|
+ std::cout << "fill with empty values\n";
|
|
|
+ for (int z = lower_index; z < upper_index; ++z)
|
|
|
+ {
|
|
|
+ for (int y = lower_index; y < upper_index; ++y)
|
|
|
+ {
|
|
|
+ for (int x = lower_index; y < upper_index; ++y)
|
|
|
+ {
|
|
|
+ grid.SetValue(nullptr, x, y, z);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Randomly add data
|
|
|
+ std::cout << "randomly add data\n";
|
|
|
+ for (int i = 0; i < 10; ++i)
|
|
|
+ {
|
|
|
+ int xi = unii(re);
|
|
|
+ int yi = unii(re);
|
|
|
+ int zi = unii(re);
|
|
|
+
|
|
|
+ core::ObjectDataPtr value(new core::ObjectData((size_t)i));
|
|
|
+ grid.SetValue(value, xi, yi, zi);
|
|
|
+
|
|
|
+ std::cout << xi << "," << yi << "," << zi << " = " << *value << std::endl;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Randomly get data
|
|
|
+ std::cout << "randomly get data\n";
|
|
|
+ for (int i = 0; i < 10; ++i)
|
|
|
+ {
|
|
|
+ double x = unif(re);
|
|
|
+ double y = unif(re);
|
|
|
+ double z = unif(re);
|
|
|
+
|
|
|
+ std::cout << x << "," << y << "," << z << " = ";
|
|
|
+ core::ObjectDataPtr value = grid.GetValue(x, y, z);
|
|
|
+ if (value)
|
|
|
+ {
|
|
|
+ std::cout << *value << std::endl;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ std::cout << "nullptr" << std::endl;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void TestBerclazGraph()
|
|
|
+{
|
|
|
+ std::cout << "init\n";
|
|
|
+
|
|
|
+ // Init grid with data
|
|
|
+ util::Grid grid(3, 3, 3, 9.0, 9.0, 9.0);
|
|
|
+ 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(10));
|
|
|
+ grid.SetValue(value, x, y, z);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Add path source->0,0,0->0,0,1->0,0,2->sink
|
|
|
+ core::ObjectDataPtr value0(new core::ObjectData(1));
|
|
|
+ value0->SetDetectionScore(1.0);
|
|
|
+ grid.SetValue(value0, 0, 0, 0);
|
|
|
+ core::ObjectDataPtr value1(new core::ObjectData(2));
|
|
|
+ value1->SetDetectionScore(1.0);
|
|
|
+ grid.SetValue(value1, 0, 0, 1);
|
|
|
+ core::ObjectDataPtr value2(new core::ObjectData(3));
|
|
|
+ value2->SetDetectionScore(1.0);
|
|
|
+ grid.SetValue(value2, 0, 0, 2);
|
|
|
+
|
|
|
+ // Add path source->1,1,0->1,1,0->1,1,2->sink
|
|
|
+ core::ObjectDataPtr value3(new core::ObjectData(4));
|
|
|
+ value3->SetDetectionScore(0.6);
|
|
|
+ grid.SetValue(value3, 0, 1, 0);
|
|
|
+ core::ObjectDataPtr value4(new core::ObjectData(5));
|
|
|
+ value4->SetDetectionScore(0.6);
|
|
|
+ grid.SetValue(value4, 0, 1, 1);
|
|
|
+ core::ObjectDataPtr value5(new core::ObjectData(6));
|
|
|
+ value5->SetDetectionScore(0.6);
|
|
|
+ grid.SetValue(value5, 0, 1, 2);
|
|
|
+
|
|
|
+ // Add path source->2,2,0->2,2,0->2,2,2->sink
|
|
|
+ core::ObjectDataPtr value6(new core::ObjectData(7));
|
|
|
+ value6->SetDetectionScore(0.3);
|
|
|
+ grid.SetValue(value6, 0, 2, 0);
|
|
|
+ core::ObjectDataPtr value7(new core::ObjectData(8));
|
|
|
+ value7->SetDetectionScore(0.3);
|
|
|
+ grid.SetValue(value7, 0, 2, 1);
|
|
|
+ core::ObjectDataPtr value8(new core::ObjectData(9));
|
|
|
+ value8->SetDetectionScore(0.3);
|
|
|
+ grid.SetValue(value8, 0, 2, 2);
|
|
|
+
|
|
|
+ std::cout << "add vertices\n";
|
|
|
+
|
|
|
+ // Add grid vertices
|
|
|
+ DirectedGraph graph;
|
|
|
+ for (int z = 0; z < grid.GetDepthCount(); ++z)
|
|
|
+ {
|
|
|
+ for (int y = 0; y < grid.GetHeightCount(); ++y)
|
|
|
+ {
|
|
|
+ for (int x = 0; x < grid.GetWidthCount(); ++x)
|
|
|
+ {
|
|
|
+ boost::add_vertex(grid.GetValue(x, y, z), graph);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ std::cout << "vertex count = " << boost::num_vertices(graph) << std::endl;
|
|
|
+ std::cout << "edge count = " << boost::num_edges(graph) << std::endl;
|
|
|
+
|
|
|
+ // Add source and sink vertex
|
|
|
+ Vertex source = boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()), graph);
|
|
|
+ Vertex sink = boost::add_vertex(core::ObjectDataPtr(new core::ObjectData()), graph);
|
|
|
+
|
|
|
+ std::cout << "add edges\n";
|
|
|
+
|
|
|
+ // Iterate all vertices but source and sink
|
|
|
+ VertexIndexMap vertices = boost::get(boost::vertex_index, graph);
|
|
|
+ VertexValueMap values = boost::get(boost::vertex_name, graph);
|
|
|
+ int vicinity_size = 1;
|
|
|
+ int layer_size = grid.GetWidthCount() * grid.GetHeightCount();
|
|
|
+ for (int z = 0; z < grid.GetDepthCount(); ++z)
|
|
|
+ {
|
|
|
+ for (int y = 0; y < grid.GetHeightCount(); ++y)
|
|
|
+ {
|
|
|
+ for (int x = 0; x < grid.GetWidthCount(); ++x)
|
|
|
+ {
|
|
|
+ // First vertex index
|
|
|
+ int vi = x + y * grid.GetHeightCount() + z * layer_size;
|
|
|
+
|
|
|
+ // Connect with the next frame only if there is a next frame
|
|
|
+ if (z < grid.GetDepthCount() - 1)
|
|
|
+ {
|
|
|
+ // Get the score, clamp it, prevent division by zero and
|
|
|
+ // logarithm of zero
|
|
|
+ double score = values[vi]->GetDetectionScore();
|
|
|
+ if (score > 0.999999)
|
|
|
+ {
|
|
|
+ score = 0.999999;
|
|
|
+ }
|
|
|
+ else if (score < 0.000001)
|
|
|
+ {
|
|
|
+ score = 0.000001;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Calculate the edge weight
|
|
|
+ double weight = -std::log(score / (1 - score));
|
|
|
+
|
|
|
+ // Iterate all nearby cells in the next frame
|
|
|
+ for (int ny = std::max(0, y - vicinity_size);
|
|
|
+ ny <
|
|
|
+ std::min(grid.GetHeightCount(), y + vicinity_size + 1);
|
|
|
+ ++ny)
|
|
|
+ {
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Connect with source and sink
|
|
|
+ boost::add_edge(source, vertices[vi], 0.0, graph);
|
|
|
+ boost::add_edge(vertices[vi], sink, 0.0, graph);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ std::cout << "vertex count = " << boost::num_vertices(graph) << std::endl;
|
|
|
+ std::cout << "edge count = " << boost::num_edges(graph) << std::endl;
|
|
|
+
|
|
|
+ // Running KSP with 5 possible paths although only 3 are worth it
|
|
|
+ algo::KShortestPaths ksp(graph, source, sink);
|
|
|
+ MultiPredecessorMap ksp_result = ksp.Run(5);
|
|
|
+
|
|
|
+ util::FileIO::WriteCSVMatlab(graph, "/home/wrede/Dokumente/graph.csv");
|
|
|
+ util::FileIO::WriteCSVMatlab(ksp_result,
|
|
|
+ sink, "/home/wrede/Dokumente/paths.csv");
|
|
|
+}
|
|
|
+
|
|
|
int main(int argc, char** argv)
|
|
|
{
|
|
|
- Run(argc, argv);
|
|
|
+ //Run(argc, argv);
|
|
|
|
|
|
//TestTracklet();
|
|
|
|
|
|
-// Vertex source, sink;
|
|
|
-// DirectedGraph graph;
|
|
|
-//
|
|
|
-// util::Logger::SetDebug(true);
|
|
|
-// util::Logger::SetInfo(true);
|
|
|
-//
|
|
|
-// CreateTestGraph(graph, source, sink);
|
|
|
-//
|
|
|
-// algo::KShortestPaths ksp(graph, source, sink);
|
|
|
-// MultiPredecessorMap paths = ksp.Run(3);
|
|
|
-//
|
|
|
-// util::Logger::LogDebug("found paths:");
|
|
|
-// for (Vertex first : paths[sink])
|
|
|
-// {
|
|
|
-// std::string path;
|
|
|
-// path += std::to_string(sink) + "->" + std::to_string(first);
|
|
|
-//
|
|
|
-// for (Vertex u = first, v = (*paths[u].begin());
|
|
|
-// u != v; u = v, v = (*paths[v].begin()))
|
|
|
-// {
|
|
|
-// path += "->" + std::to_string(v);
|
|
|
-// }
|
|
|
-//
|
|
|
-// util::Logger::LogDebug(path);
|
|
|
-// }
|
|
|
+ TestKSP();
|
|
|
+
|
|
|
+ //TestGrid();
|
|
|
+
|
|
|
+ //TestBerclazGraph();
|
|
|
|
|
|
return 0;
|
|
|
}
|