Add FlannIndex abstract interface and implement NanoFlannIndex subclass (#1744)

* Add FlannIndex abstract interface and implement NanoFlannIndex subclass

* Refactored: made NanoFlann a new NN type instead of inheriting FlannIndex. Added tests. Vendoring nanoflann.h directly in the repo. RegistrationVis now use NANOFLANN_INDEX_KDTREE_SINGLE (instead of FLANN_INDEX_KDTREE_SINGLE) flann index for 2d points matching.

* cleanup comments, added FlannIndex doxygen

* Fixing windows tests

* updating flaky test

* Simplified interface, added flann kdtree single approach selectable by parameters.

* RegVis: symmetry of nanoflann for two branches of guess feature matching

* cv::BFMatcher baseline

* Small cmake optimization FLANN_KDTREE_MEM_OPT only defined for FlannIndex

* Refactored where FLANN_KDTREE_MEM_OPT is defined

* fixed file name already exist

* cleanup

* fixup build

---------

Co-authored-by: matlabbe <matlabbe@gmail.com>
This commit is contained in:
Muhammad
2026-08-16 19:51:39 +03:00
committed by GitHub
parent df52523a0c
commit f647014f54
28 changed files with 7537 additions and 179 deletions

View File

@@ -414,6 +414,24 @@ int main(int argc, char * argv[])
std::string pyMatcherPath;
Parameters::parse(parameters, Parameters::kVisPnPReprojError(), reprojError);
Parameters::parse(parameters, Parameters::kPyMatcherPath(), pyMatcherPath);
// PyMatcher cannot match binary features, RegistrationVis falls back to
// brute force with cross check (see the warning above).
const bool pyMatcherOnBinaryFeatures =
reg.getNNType()==6 &&
!dataFrom.getWordsDescriptors().empty() &&
dataFrom.getWordsDescriptors().type()!=CV_32F;
QString nnTypeName = (pyMatcherOnBinaryFeatures?
RegistrationVis::getNNTypeName(5):reg.getNNTypeName()).c_str();
// 5, 6 and 7 are the approaches RegistrationVis matches with itself,
// the others search for the k nearest neighbors and do the ratio test.
const bool nndrUsed = reg.getNNType()<5 || reg.getNNType()>7;
if(reg.getNNType()==6 && !pyMatcherOnBinaryFeatures)
{
// the script actually used is more telling than the generic name
nnTypeName = QString(uSplit(UFile::getName(pyMatcherPath), '.').front().c_str()).replace("rtabmap_", "");
}
dialog.setWindowTitle(QString("Matches (%1/%2) %3 sec [%4=%5 (%6) %7=%8 (%9)%10 %11=%12 (%13) %14=%15]")
.arg(info.inliers)
.arg(info.matches)
@@ -423,11 +441,8 @@ int main(int argc, char * argv[])
.arg(reg.getDetector()?Feature2D::typeName(reg.getDetector()->getType()).c_str():"?")
.arg(Parameters::kVisCorNNType().c_str())
.arg(reg.getNNType())
.arg(reg.getNNType()<VWDictionary::kNNUndef?VWDictionary::nnStrategyName((VWDictionary::NNStrategy)reg.getNNType()).c_str():
reg.getNNType()==5||(reg.getNNType()==6&&!dataFrom.getWordsDescriptors().empty()&& dataFrom.getWordsDescriptors().type()!=CV_32F)?"BFCrossCheck":
reg.getNNType()==6?QString(uSplit(UFile::getName(pyMatcherPath), '.').front().c_str()).replace("rtabmap_", ""):
reg.getNNType()==7?"GMS":"?")
.arg(reg.getNNType()<5?QString(" %1=%2").arg(Parameters::kVisCorNNDR().c_str()).arg(reg.getNNDR()):"")
.arg(nnTypeName)
.arg(nndrUsed?QString(" %1=%2").arg(Parameters::kVisCorNNDR().c_str()).arg(reg.getNNDR()):"")
.arg(Parameters::kVisEstimationType().c_str())
.arg(reg.getEstimationType())
.arg(reg.getEstimationType()==0?"3D->3D":reg.getEstimationType()==1?"3D->2D":reg.getEstimationType()==2?"2D->2D":"?")