Skip to content

Instantly share code, notes, and snippets.

@simogasp
Last active March 12, 2017 19:57
Show Gist options
  • Save simogasp/12fbd37d5241d9fb3df8aab0efc3c650 to your computer and use it in GitHub Desktop.
Save simogasp/12fbd37d5241d9fb3df8aab0efc3c650 to your computer and use it in GitHub Desktop.
testRaceCondition - it tests a possible race condition when creating points or adding its observations. It's a simplified version of the relevant omvg code. It takes as input a sfmdata and it basically tries to build a copy of the Landmarks in it by running through all the view and adding either a new point if it does not exist in the new set, o…
#include <openMVG/sfm/sfm_data.hpp>
#include <openMVG/sfm/sfm_data_io.hpp>
#include <openMVG/tracks/tracks.hpp>
#include <openMVG/system/timer.hpp>
#include <openMVG/logger.hpp>
#include <omp>
#include <boost/progress.hpp>
#include <boost/program_options.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <chrono>
#include <memory>
namespace po = boost::program_options;
using namespace openMVG;
using Stats = std::map<IndexT, std::size_t>;
/*
*
*/
int main(int argc, char** argv)
{
std::string inputSfmData;
po::options_description desc(
"Program used to test the race condition on sfmdata structure");
desc.add_options()
("help,h", "Print this message")
("sfmdata", po::value<std::string>(&inputSfmData)->required(),
"The sfm_data file in .json/abc format.");
po::variables_map vm;
try
{
po::store(po::parse_command_line(argc, argv, desc), vm);
if(vm.count("help") || (argc == 1))
{
OPENMVG_LOG_DEBUG(desc);
return EXIT_SUCCESS;
}
po::notify(vm);
}
catch(boost::program_options::required_option& e)
{
OPENMVG_LOG_ERROR("ERROR: " << e.what() << std::endl);
OPENMVG_LOG_DEBUG("Usage:\n\n" << desc);
return EXIT_FAILURE;
}
catch(boost::program_options::error& e)
{
OPENMVG_LOG_ERROR("ERROR: " << e.what() << std::endl);
OPENMVG_LOG_DEBUG("Usage:\n\n" << desc);
return EXIT_FAILURE;
}
// just for debugging purpose, print out all the parameters
{
OPENMVG_LOG_DEBUG("Program called with the following parameters:");
OPENMVG_LOG_DEBUG("\tsfmdata: " << inputSfmData);
}
OPENMVG_LOG_INFO("Using " << omp_get_max_threads() << " threads");
OPENMVG_LOG_INFO("Loading sfmdata...");
// load the sfmdata
sfm::SfM_Data sfmdata;
if(!sfm::Load(sfmdata, inputSfmData, sfm::ESfM_Data::ALL))
{
std::cerr << "Error while loading " << inputSfmData << std::endl;
return EXIT_FAILURE;
}
// build the tracks per view
tracks::TracksPerView visibility;
boost::progress_display display(sfmdata.GetViews().size());
// initialize
OPENMVG_LOG_INFO("Initializing visibility");
for(const auto& v : sfmdata.GetViews())
{
const auto idx = v.first;
visibility.emplace(idx, std::vector<std::size_t>() );
++display;
}
OPENMVG_LOG_INFO("Filling up visibility");
display.restart(sfmdata.GetLandmarks().size());
// fill up the visibility
for(const auto& l : sfmdata.GetLandmarks())
{
const auto idx = l.first;
for(const auto& ob : l.second.obs)
{
const auto idView = ob.first;
assert(visibility.find(idView) != visibility.end());
visibility[idView].push_back(idx);
}
++display;
}
//******************************************************
// code to test
sfm::Landmarks points3D;
const auto& valid_views = sfmdata.GetViews();
std::size_t new_added_track = 0;
OPENMVG_LOG_INFO("Rebuilding the landmarks");
display.restart(valid_views.size());
system::Timer timer;
// for each view
#pragma omp parallel for schedule(dynamic)
for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(valid_views.size()); ++i)
{
sfm::Views::const_iterator iter = valid_views.begin();
std::advance(iter, i);
const auto idview = iter->first;
const auto& visiblePoints = visibility.at(idview);
// for each visible 3D point
for(const auto& pt : visiblePoints)
{
// if the 3D point is already added
bool existingPoint = false;
#pragma omp critical
{
existingPoint = points3D.find(pt) != points3D.end();
// existingPoint = points3D.count(pt) != 0;
}
if(existingPoint)
{
#pragma omp critical
{
sfm::Landmark & landmark = points3D[pt];
if (landmark.obs.count(idview) == 0)
{
landmark.obs[idview] = sfm::Observation(Vec2(0,0), 0);
}
}
}
// otherwise create a new point
else
{
#pragma omp critical
{
// Add a new track
// this should never happens as we entered here because the point does not exist
// But.. it happens, quite often!
// And for this reason at the end new_added_track has a bigger value than
// the actual size of points 3D
if(points3D.find(pt) != points3D.end())
{
OPENMVG_LOG_ERROR("point " << pt << " was not supposed to exist");
}
// if we use this instruction, and the point already exists, we are modifying the
// 3D coordinates of the point (!) and adding the observation: for this reason
// the problem is not noticeable at end when comparing the number of observation
// Creating the point and adding it at the end with points3D[pt] = landmark
// it will make it clear that the number of observations is wrong at the end.
// sfm::Landmark & landmark = points3D[pt];
sfm::Landmark landmark;
landmark.X = Vec3(0,0,0);
landmark.obs[idview] = sfm::Observation(Vec2(0,0), 0);
points3D[pt] = landmark;
++new_added_track;
}
}
}
#pragma omp critical
++display;
}
OPENMVG_LOG_INFO("Procedure took " << timer.elapsedMs() << "ms" );
OPENMVG_LOG_INFO("Number of points in the original structure " << sfmdata.GetLandmarks().size() );
OPENMVG_LOG_INFO("Added " << new_added_track << " points.");
OPENMVG_LOG_INFO("points3D contains " << points3D.size() << " points.");
const auto& landmarks = sfmdata.GetLandmarks();
for(const auto& l : points3D)
{
const auto& orig = landmarks.find(l.first);
if(orig == landmarks.end())
{
OPENMVG_LOG_ERROR("point " << l.first << " does not exist in the original sfmdata");
OPENMVG_LOG_ERROR("it has " << l.second.obs.size() << " observations");
}
if(l.second.obs.size() != orig->second.obs.size())
{
OPENMVG_LOG_ERROR("point " << l.first << " has different observations than original");
OPENMVG_LOG_ERROR("it has " << l.second.obs.size() << " observations");
OPENMVG_LOG_ERROR("while the original has " << orig->second.obs.size() << " observations");
}
}
assert(landmarks.size() == points3D.size());
assert(landmarks.size() == new_added_track);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment