/// List the pairs used by the relative rotations inline Pair_Set getPairs(const RelativeRotations & relRots) { Pair_Set pairs; for (const auto & cur_rotation : relRots ) pairs.insert({cur_rotation.i, cur_rotation.j}); return pairs; }
/// Generate the pairs that have a distance inferior to the overlapSize /// Usable to match video sequence inline Pair_Set contiguousWithOverlap(const size_t N, const size_t overlapSize) { Pair_Set pairs; for (IndexT I = 0; I < static_cast<IndexT>(N); ++I) for (IndexT J = I+1; J < I+1+overlapSize && J < static_cast<IndexT>(N); ++J) pairs.insert({I,J}); return pairs; }
TEST(matching_image_collection, IO) { Pair_Set pairSetGT; pairSetGT.insert( std::make_pair(0,1) ); pairSetGT.insert( std::make_pair(1,2) ); pairSetGT.insert( std::make_pair(2,0) ); Pair_Set pairSetGTsorted; pairSetGTsorted.insert( std::make_pair(0,1) ); pairSetGTsorted.insert( std::make_pair(0,2) ); pairSetGTsorted.insert( std::make_pair(1,2) ); EXPECT_TRUE( savePairs("pairsT_IO.txt", pairSetGT)); Pair_Set loaded_Pairs; EXPECT_TRUE( loadPairs(3, "pairsT_IO.txt", loaded_Pairs)); EXPECT_TRUE( std::equal(loaded_Pairs.begin(), loaded_Pairs.end(), pairSetGTsorted.begin()) ); }
TEST(matching_image_collection, IO_InvalidInput) { // A pair with index superior to the expected picture count Pair_Set pairSetGT; pairSetGT.insert( std::make_pair(0,1) ); pairSetGT.insert( std::make_pair(10,20) ); EXPECT_TRUE( savePairs("pairsT_IO_InvalidInput.txt", pairSetGT)); Pair_Set loaded_Pairs; const int expectedPicCount = 2; EXPECT_FALSE( loadPairs(expectedPicCount, "pairsT_IO_InvalidInput.txt", loaded_Pairs)); // A pair with equal index pairSetGT.clear(); pairSetGT.insert( std::make_pair(0,1) ); pairSetGT.insert( std::make_pair(0,0) ); EXPECT_FALSE( loadPairs(expectedPicCount, "pairsT_IO_InvalidInput.txt", loaded_Pairs)); }
/// Load a set of Pair_Set from a file /// I J K L (pair that link I) inline bool loadPairs( const size_t N, // number of image in the current project (to check index validity) const std::string &sFileName, // filename of the list file, Pair_Set & pairs) // output pairs read from the list file { std::ifstream in(sFileName.c_str()); if (!in.is_open()) { std::cerr << std::endl << "loadPairs: Impossible to read the specified file: \"" << sFileName << "\"." << std::endl; return false; } std::string sValue; std::vector<std::string> vec_str; while (std::getline( in, sValue ) ) { vec_str.clear(); stl::split(sValue, ' ', vec_str); const IndexT str_size (vec_str.size()); if (str_size < 2) { std::cerr << "loadPairs: Invalid input file: \"" << sFileName << "\"." << std::endl; return false; } std::stringstream oss; oss.clear(); oss.str(vec_str[0]); IndexT I, J; oss >> I; for (IndexT i=1; i<str_size; ++i) { oss.clear(); oss.str(vec_str[i]); oss >> J; if ( I > N-1 || J > N-1) //I&J always > 0 since we use unsigned type { std::cerr << "loadPairs: Invalid input file. Image out of range. " << "I: " << I << " J:" << J << " N:" << N << std::endl << "File: \"" << sFileName << "\"." << std::endl; return false; } if ( I == J ) { std::cerr << "loadPairs: Invalid input file. Image " << I << " see itself. File: \"" << sFileName << "\"." << std::endl; return false; } // Insert the pair such that .first < .second pairs.insert( {std::min(I, J), std::max(I,J)} ); } } in.close(); return true; }
Pair_Set Frustum_Filter::getFrustumIntersectionPairs ( const std::vector<HalfPlaneObject>& bounding_volume ) const { Pair_Set pairs; // List active view Id std::vector<IndexT> viewIds; viewIds.reserve(z_near_z_far_perView.size()); std::transform(z_near_z_far_perView.cbegin(), z_near_z_far_perView.cend(), std::back_inserter(viewIds), stl::RetrieveKey()); C_Progress_display my_progress_bar( viewIds.size() * (viewIds.size()-1)/2, std::cout, "\nCompute frustum intersection\n"); // Exhaustive comparison (use the fact that the intersect function is symmetric) #ifdef OPENMVG_USE_OPENMP #pragma omp parallel for #endif for (int i = 0; i < (int)viewIds.size(); ++i) { // Prepare vector of intersecting objects (within loop to keep it // thread-safe) std::vector<HalfPlaneObject> objects = bounding_volume; objects.insert(objects.end(), { frustum_perView.at(viewIds[i]), HalfPlaneObject() }); for (size_t j = i+1; j < viewIds.size(); ++j) { objects.back() = frustum_perView.at(viewIds[j]); if (intersect(objects)) { #ifdef OPENMVG_USE_OPENMP #pragma omp critical #endif { pairs.insert({viewIds[i], viewIds[j]}); } } // Progress bar update ++my_progress_bar; } } return pairs; }
/// Test to get back node id of each CC // 1-2 // // 3-4 // | | // 5-6 // // 7-8-9-10 // |/ // 11 TEST(Subgraphs, CC_Subgraph_CC_count) { using namespace openMVG; Pair_Set pairs; { std::set<IndexT> node_largest_cc = graph::KeepLargestCC_Nodes<Pair_Set, IndexT>(pairs); EXPECT_EQ(0, node_largest_cc.size()); } // two pairs.insert(Pair(1,2)); { std::set<IndexT> node_largest_cc = graph::KeepLargestCC_Nodes<Pair_Set, IndexT>(pairs); EXPECT_EQ(2, node_largest_cc.size()); } // four pairs.insert(Pair(3,4)); pairs.insert(Pair(3,5)); pairs.insert(Pair(4,6)); pairs.insert(Pair(5,6)); { std::set<IndexT> node_largest_cc = graph::KeepLargestCC_Nodes<Pair_Set, IndexT>(pairs); EXPECT_EQ(4, node_largest_cc.size()); } // five pairs.insert(Pair(7,8)); pairs.insert(Pair(8,9)); pairs.insert(Pair(9,10)); pairs.insert(Pair(8,11)); pairs.insert(Pair(9,11)); { std::set<IndexT> node_largest_cc = graph::KeepLargestCC_Nodes<Pair_Set, IndexT>(pairs); EXPECT_EQ(5, node_largest_cc.size()); } //-- // Test with a vector of pairs //-- Pair_Vec pairs_vec(pairs.begin(), pairs.end()); //random shuffle to assert that contiguous edges are close together. std::random_shuffle(pairs_vec.begin(), pairs_vec.end()); { std::set<IndexT> node_largest_cc = graph::KeepLargestCC_Nodes<Pair_Vec, IndexT>(pairs_vec); EXPECT_EQ(5, node_largest_cc.size()); } }
/// Build a list of pair that share visibility content from the SfM_Data structure Pair_Set BuildPairsFromStructureObservations(const SfM_Data & sfm_data) { Pair_Set pairs; for (Landmarks::const_iterator itL = sfm_data.GetLandmarks().begin(); itL != sfm_data.GetLandmarks().end(); ++itL) { const Landmark & landmark = itL->second; for (Observations::const_iterator iterI = landmark.obs.begin(); iterI != landmark.obs.end(); ++iterI) { const IndexT id_viewI = iterI->first; Observations::const_iterator iterJ = landmark.obs.begin(); std::advance(iterJ, 1); for (; iterJ != landmark.obs.end(); ++iterJ) { const IndexT id_viewJ = iterJ->first; pairs.insert( std::make_pair(id_viewI,id_viewJ)); } } } return pairs; }