Skip to content

Commit

Permalink
[matching] minor fixes for regions matching. openMVG#386
Browse files Browse the repository at this point in the history
  • Loading branch information
pmoulon authored and simogasp committed Oct 2, 2015
1 parent 63b5e0b commit 704f13f
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 160 deletions.
2 changes: 1 addition & 1 deletion src/openMVG/matching/cascade_hasher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ class CascadeHasher {
const int NN = 2
) const
{
typedef L2_Vectorized<unsigned char> MetricT;
typedef L2_Vectorized<typename MatrixT::Scalar> MetricT;
MetricT metric;

static const int kNumTopCandidates = 10;
Expand Down
2 changes: 1 addition & 1 deletion src/openMVG/matching/matcher_cascade_hashing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class ArrayMatcherCascadeHashing : public ArrayMatcher<Scalar, Metric>

// Index the query descriptors
const HashedDescriptions hashed_query = cascade_hasher_.CreateHashedDescriptions(mat_query);
// Match the query descriptors to the data'base'
// Match the query descriptors to the database
cascade_hasher_.Match_HashedDescriptions(
hashed_query, mat_query,
hashed_base_, *memMapping,
Expand Down
195 changes: 63 additions & 132 deletions src/openMVG/matching/regions_matcher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,7 @@ namespace openMVG {
namespace matching {

/**
*
*/
/**
* @brief Match two Regions according a chosen MatcherType using the ratio test
* to assure the robustness of the matches.
* It returns the matching features.
*
* @param[in] dist_ratio The threshold for the ratio test.
* @param[in] eMatcherType The type of matcher to use.
* @param[in] regions_I The first Region to match
* @param[in] regions_J The second Region to match
* @param[out] matches It contains the indices of the matching features
* Match two Regions according a chosen MatcherType.
*/
void DistanceRatioMatch
(
Expand All @@ -43,98 +32,61 @@ void DistanceRatioMatch
matching::IndMatches & matches // corresponding points
);


/**
* @brief Interface for a matcher of Regions that keep on of the Regions stored
* as a "database". The other region is then a query that is matched with respect
* to the database.
*/
class RegionsMatcher
{
public:

/**
* @brief The destructor.
*/
~RegionsMatcher() {}


/**
* @brief Initialize the matcher by setting one region as a "database".
*
* @param[in] regions The Regions to be used as reference when matching another Region.
*/
virtual void Init_database
(
const features::Regions& regions
) = 0;

/**
* @brief Match a Regions to the internal database using the test ratio to improve
* the robustness of the match.
*
* @param[in] f_dist_ratio The threshold for the ratio test.
* @param[in] query_regions The Regions to match.
* @param[out] vec_putative_matches It contains the indices of the matching features
* of the database and the query Regions.
* @return True if everything went well.
*/
virtual bool Match
(
const float f_dist_ratio,
const features::Regions& query_regions,
matching::IndMatches & vec_putative_matches
) =0;
~RegionsMatcher() {}

/**
* @brief Initialize the retrieval database
*/
virtual void Init_database
(
const features::Regions& regions
) = 0;

/**
* @brief Match some regions to the database
*/
virtual bool Match
(
const float f_dist_ratio,
const features::Regions& query_regions,
matching::IndMatches & vec_putative_matches
) =0;
};

/**
* @brief A simple class that allows to match Regions with respect a given Regions
* used as "database".
* Regions matching in query to database mode
*/
class Matcher_Regions_Database
{
public:

/**
* @brief Empty constructor, by default it initializes the matcher to BRUTE_FORCE_L2
* and the database to an empty database.
*/
Matcher_Regions_Database();

/**
* @brief Initialize the internal database
*
* @param[in] eMatcherType The type of matcher to use to match the Regions.
* @param[in] database_regions The Regions that will be used as database to
* match other Regions (query).
*/
Matcher_Regions_Database
(
matching::EMatcherType eMatcherType,
const features::Regions & database_regions // database
);

/**
* @brief Find corresponding points between the query Regions and the database one
*
* @param[in] dist_ratio The threshold for the ratio test.
* @param[in] query_regions The Regions to match.
* @param[out] matches It contains the indices of the matching features
* of the database and the query Regions.
* @return True if everything went well.
*/
bool Match
(
float dist_ratio,
const features::Regions & query_regions,
matching::IndMatches & matches
)const;
Matcher_Regions_Database();

/**
* @brief Initialize the retrieval database
*/
Matcher_Regions_Database
(
matching::EMatcherType eMatcherType,
const features::Regions & database_regions // database
);

/// Find corresponding points between the query regions and the database one
bool Match
(
float dist_ratio, // Distance ratio used to discard spurious correspondence
const features::Regions & query_regions,
matching::IndMatches & matches // photometric corresponding points
)const;

private:
// Matcher Type
matching::EMatcherType _eMatcherType;
// The matching interface
std::unique_ptr<RegionsMatcher> _matching_interface;
// Matcher Type
matching::EMatcherType _eMatcherType;
// The matching interface
std::unique_ptr<RegionsMatcher> _matching_interface;
};

/**
Expand All @@ -143,82 +95,61 @@ class Matcher_Regions_Database
template < class ArrayMatcherT >
class RegionsMatcherT : public RegionsMatcher
{

private:
ArrayMatcherT _matcher;
const features::Regions* _regions;
bool _b_squared_metric; // Store if the metric is squared or not

ArrayMatcherT matcher_;
const features::Regions* regions_;
bool b_squared_metric_; // Store if the metric is squared or not
public:
typedef typename ArrayMatcherT::ScalarT Scalar;
typedef typename ArrayMatcherT::DistanceType DistanceType;

/**
* @brief Empty constructor, by default it initializes the database to an empty database.
*/
RegionsMatcherT() :_regions(nullptr) {}
RegionsMatcherT() :regions_(NULL) {}

/**
* @brief Initialize the matcher with a Regions that will be used as database
*
* @param regions The Regions to be used as database.
* @param b_squared_metric Whether to use a squared metric for the ratio test
* when matching two Regions.
* @brief Init the matcher with some reference regions.
*/
RegionsMatcherT(const features::Regions& regions, bool b_squared_metric = false)
: _regions(&regions), _b_squared_metric(b_squared_metric)
: regions_(&regions), b_squared_metric_(b_squared_metric)
{
if (_regions->RegionCount() == 0)
if (regions_->RegionCount() == 0)
return;

const Scalar * tab = reinterpret_cast<const Scalar *>(_regions->DescriptorRawData());
_matcher.Build(tab, _regions->RegionCount(), _regions->DescriptorLength());
const Scalar * tab = reinterpret_cast<const Scalar *>(regions_->DescriptorRawData());
matcher_.Build(tab, regions_->RegionCount(), regions_->DescriptorLength());
}

/**
* @brief Initialize the matcher with a Regions that will be used as database
*
* @param regions The Regions to be used as database.
*/
void Init_database
(
const features::Regions& regions
)
{
_regions = &regions;
if (_regions->RegionCount() == 0)
regions_ = &regions;
if (regions_->RegionCount() == 0)
return;

const Scalar * tab = reinterpret_cast<const Scalar *>(_regions->DescriptorRawData());
_matcher.Build(tab, _regions->RegionCount(), _regions->DescriptorLength());
const Scalar * tab = reinterpret_cast<const Scalar *>(regions_->DescriptorRawData());
matcher_.Build(tab, regions_->RegionCount(), regions_->DescriptorLength());
}

/**
* @brief Match a Regions to the internal database using the test ratio to improve
* the robustness of the match.
*
* @param f_dist_ratio The threshold for the ratio test.
* @param query_regions The Regions to match.
* @param vec_putative_matches It contains the indices of the matching features
* of the database and the query Regions.
* @return True if everything went well.
* @brief Match some regions to the database of internal regions.
*/
bool Match(
const float f_dist_ratio,
const features::Regions& query_regions,
const features::Regions& queryregions_,
matching::IndMatches & vec_putative_matches)
{
if (_regions == nullptr)
if (regions_ == nullptr)
return false;

const Scalar * queries = reinterpret_cast<const Scalar *>(query_regions.DescriptorRawData());
const Scalar * queries = reinterpret_cast<const Scalar *>(queryregions_.DescriptorRawData());

const size_t NNN__ = 2;
matching::IndMatches vec_nIndice;
std::vector<DistanceType> vec_fDistance;

// Search the 2 closest features neighbours for each query descriptor
if (!_matcher.SearchNeighbours(queries, query_regions.RegionCount(), &vec_nIndice, &vec_fDistance, NNN__))
if (!matcher_.SearchNeighbours(queries, queryregions_.RegionCount(), &vec_nIndice, &vec_fDistance, NNN__))
return false;

std::vector<int> vec_nn_ratio_idx;
Expand All @@ -231,7 +162,7 @@ class RegionsMatcherT : public RegionsMatcher
vec_fDistance.end(), // distance end
NNN__, // Number of neighbor in iterator sequence (minimum required 2)
vec_nn_ratio_idx, // output (indices that respect the distance Ratio)
_b_squared_metric ? Square(f_dist_ratio) : f_dist_ratio);
b_squared_metric_ ? Square(f_dist_ratio) : f_dist_ratio);

vec_putative_matches.reserve(vec_nn_ratio_idx.size());
for (size_t k=0; k < vec_nn_ratio_idx.size(); ++k)
Expand All @@ -245,7 +176,7 @@ class RegionsMatcherT : public RegionsMatcher

// Remove matches that have the same (X,Y) coordinates
matching::IndMatchDecorator<float> matchDeduplicator(vec_putative_matches,
_regions->GetRegionsPositions(), query_regions.GetRegionsPositions());
regions_->GetRegionsPositions(), queryregions_.GetRegionsPositions());
matchDeduplicator.getDeduplicated(vec_putative_matches);

return (!vec_putative_matches.empty());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,8 @@ void Matcher_Regions_AllInMemory::Match(
#ifdef OPENMVG_USE_OPENMP
std::cout << "Using the OPENMP thread interface" << std::endl;
#endif
bool b_multithreaded_pair_search = false;
switch(_eMatcherType)
{
case BRUTE_FORCE_L2:
std::cout << "Using BRUTE_FORCE_L2 matcher" << std::endl;
break;
case BRUTE_FORCE_HAMMING:
std::cout << "Using BRUTE_FORCE_HAMMING matcher" << std::endl;
break;
case ANN_L2:
std::cout << "Using ANN_L2 matcher" << std::endl;
break;
case CASCADE_HASHING_L2:
std::cout << "Using CASCADE_HASHING_L2 matcher" << std::endl;
b_multithreaded_pair_search = true;
// -> set to true only here, since OpenMP instructions are not used in this matcher
break;
default:
std::cout << "Using unknown matcher type" << std::endl;
}
const bool b_multithreaded_pair_search = (_eMatcherType == CASCADE_HASHING_L2);
// -> set to true for CASCADE_HASHING_L2, since OpenMP instructions are not used in this matcher

C_Progress_display my_progress_bar( pairs.size() );

Expand Down Expand Up @@ -92,14 +74,18 @@ void Matcher_Regions_AllInMemory::Match(
const size_t J = indexToCompare[j];

const features::Regions &regionsJ = *regions_provider->regions_per_view.at(J).get();
if (regionsJ.RegionCount() == 0)
continue;

if (regionsI.Type_id() != regionsJ.Type_id())
if (regionsJ.RegionCount() == 0
|| regionsI.Type_id() != regionsJ.Type_id())
{
#ifdef OPENMVG_USE_OPENMP
#pragma omp critical
#endif
++my_progress_bar;
continue;
}

IndMatches vec_putatives_matches;
matcher.Match(Square(_f_dist_ratio), regionsJ, vec_putatives_matches);
matcher.Match(_f_dist_ratio, regionsJ, vec_putatives_matches);

#ifdef OPENMVG_USE_OPENMP
#pragma omp critical
Expand Down
8 changes: 7 additions & 1 deletion src/software/SfM/main_ComputeMatches.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,37 +252,43 @@ int main(int argc, char **argv)
}

// Allocate the right Matcher according the Matching requested method
std::unique_ptr<Matcher_Regions_AllInMemory> collectionMatcher;
std::unique_ptr<Matcher> collectionMatcher;
if (sNearestMatchingMethod == "AUTO")
{
if (regions_type->IsScalar())
{
std::cout << "Using ANN_L2 matcher" << std::endl;
collectionMatcher.reset(new Matcher_Regions_AllInMemory(fDistRatio, ANN_L2));
}
else
if (regions_type->IsBinary())
{
std::cout << "Using BRUTE_FORCE_HAMMING matcher" << std::endl;
collectionMatcher.reset(new Matcher_Regions_AllInMemory(fDistRatio, BRUTE_FORCE_HAMMING));
}
}
else
if (sNearestMatchingMethod == "BRUTEFORCEL2")
{
std::cout << "Using BRUTE_FORCE_L2 matcher" << std::endl;
collectionMatcher.reset(new Matcher_Regions_AllInMemory(fDistRatio, BRUTE_FORCE_L2));
}
else
if (sNearestMatchingMethod == "BRUTEFORCEHAMMING")
{
std::cout << "Using BRUTE_FORCE_HAMMING matcher" << std::endl;
collectionMatcher.reset(new Matcher_Regions_AllInMemory(fDistRatio, BRUTE_FORCE_HAMMING));
}
else
if (sNearestMatchingMethod == "ANNL2")
{
std::cout << "Using ANN_L2 matcher" << std::endl;
collectionMatcher.reset(new Matcher_Regions_AllInMemory(fDistRatio, ANN_L2));
}
else
if (sNearestMatchingMethod == "CASCADEHASHINGL2")
{
std::cout << "Using CASCADE_HASHING_L2 matcher" << std::endl;
collectionMatcher.reset(new Matcher_Regions_AllInMemory(fDistRatio, CASCADE_HASHING_L2));
}
if (!collectionMatcher)
Expand Down

0 comments on commit 704f13f

Please sign in to comment.