头文件
#include "openMVG/matching_image_collection/Pair_Builder.hpp"
#include "openMVG/sfm/sfm_data.hpp"
#include "openMVG/sfm/sfm_data_io.hpp"
#include "third_party/cmdLine/cmdLine.h"
#include "third_party/stlplus3/filesystemSimplified/file_system.hpp"
#include <iostream>
这里只介绍之前没有介绍过的头文件,如果想了解更多请看我之前发的博客。
Pair_Builder.hpp
- 功能: 该头文件包含了用于从图像集合中构建图像对(即,需要一起处理或匹配的图像对)的类和函数。
那我们接下来直接看主函数
// 主要功能就是构建图像对
int main( int argc, char** argv )
{
CmdLine cmd;
std::string sSfMDataFilename;
std::string sOutputPairsFilename;
// 默认的匹配模式是EXHAUSTIVE暴力匹配,也就是每一张图片都和其他图片一一匹配
// 还有一种匹配模式是相邻的两张图像才进行匹配(PAIR_CONTIGUOUS)
std::string sPairMode = "EXHAUSTIVE";
int iContiguousCount = -1;
// Mandatory elements:
cmd.add( make_option( 'i', sSfMDataFilename, "input_file" ) );
cmd.add( make_option( 'o', sOutputPairsFilename, "output_file" ) );
// Optional elements:
cmd.add( make_option( 'm', sPairMode, "pair_mode" ) );
cmd.add( make_option( 'c', iContiguousCount, "contiguous_count" ) );
try
{
if ( argc == 1 )
throw std::string( "Invalid command line parameter." );
cmd.process( argc, argv );
}
catch ( const std::string& s )
{
usage( argv[ 0 ] );
std::cerr << "[Error] " << s << std::endl;
return EXIT_FAILURE;
}
// 0. Parse parameters
std::cout << " You called:\n"
<< argv[ 0 ] << "\n"
<< "--input_file : " << sSfMDataFilename << "\n"
<< "--output_file : " << sOutputPairsFilename << "\n"
<< "Optional parameters\n"
<< "--pair_mode : " << sPairMode << "\n"
<< "--contiguous_count : " << iContiguousCount << "\n"
<< std::endl;
// 输入和输出两个必要参数不能为空
if ( sSfMDataFilename.empty() )
{
usage( argv[ 0 ] );
std::cerr << "[Error] Input file not set." << std::endl;
exit( EXIT_FAILURE );
}
if ( sOutputPairsFilename.empty() )
{
usage( argv[ 0 ] );
std::cerr << "[Error] Output file not set." << std::endl;
exit( EXIT_FAILURE );
}
EPairMode pairMode;
if ( sPairMode == "EXHAUSTIVE" )
{
pairMode = PAIR_EXHAUSTIVE;
}
else if ( sPairMode == "CONTIGUOUS" )
{
// iContiguousCount 就相当于是举例,如比iContiguousCount = 2的时候,图像1只能和图像2和图像3进行匹配
if ( iContiguousCount == -1 )
{
usage( argv[ 0 ] );
std::cerr << "[Error] Contiguous pair mode selected but contiguous_count not set." << std::endl;
exit( EXIT_FAILURE );
}
pairMode = PAIR_CONTIGUOUS;
}
// 加载数据
std::cout << "Loading scene.";
SfM_Data sfm_data;
if ( !Load( sfm_data, sSfMDataFilename, ESfM_Data( VIEWS | INTRINSICS ) ) )
{
std::cerr << std::endl
<< "The input SfM_Data file \"" << sSfMDataFilename << "\" cannot be read." << std::endl;
exit( EXIT_FAILURE );
}
const size_t NImage = sfm_data.GetViews().size();
// 计算图像对
std::cout << "Computing pairs." << std::endl;
Pair_Set pairs;
switch ( pairMode )
{
case PAIR_EXHAUSTIVE:
{
// 这种匹配方法就是所有图像两两组合的全部情况
pairs = exhaustivePairs( NImage );
break;
}
case PAIR_CONTIGUOUS:
{
pairs = contiguousWithOverlap( NImage, iContiguousCount );
break;
}
default:
{
std::cerr << "Unknown pair mode" << std::endl;
exit( EXIT_FAILURE );
}
}
// 3. Save pairs
std::cout << "Saving pairs." << std::endl;
if ( !savePairs( sOutputPairsFilename, pairs ) )
{
std::cerr << "Failed to save pairs to file: \"" << sOutputPairsFilename << "\"" << std::endl;
exit( EXIT_FAILURE );
}
return EXIT_SUCCESS;
}
暴力匹配
inline Pair_Set exhaustivePairs(const size_t N)
{
Pair_Set pairs;
for (IndexT I = 0; I < static_cast<IndexT>(N); ++I)
for (IndexT J = I+1; J < static_cast<IndexT>(N); ++J)
pairs.insert({I,J});
return pairs;
}
相邻( iContiguousCount = 1)图像匹配
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;
}