Last active
March 12, 2017 19:57
-
-
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…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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