Odom: support features-only frames (#1767)

* Odom: support features-only frames

* odom: fixed input keypoint scaling when Odom/Decimation is used

* fixing octave scaling when decimating image in Memory

* Gating negative octave scaling on decimation

* backward compatibility with octave issue

* narrowing the change, cleanup comments

* fixing corrupted file copy on windows
This commit is contained in:
matlabbe
2026-09-19 23:48:45 -07:00
committed by GitHub
parent 1fe713cc1f
commit 9ed83a71db
9 changed files with 234 additions and 10 deletions
+31 -4
View File
@@ -101,6 +101,7 @@ Memory::Memory(const ParametersMap & parameters) :
_stereoFromMotion(Parameters::defaultMemStereoFromMotion()),
_imagePreDecimation(Parameters::defaultMemImagePreDecimation()),
_imagePostDecimation(Parameters::defaultMemImagePostDecimation()),
_legacyDecimatedOctave(false),
_compressionParallelized(Parameters::defaultMemCompressionParallelized()),
_laserScanDownsampleStepSize(Parameters::defaultMemLaserScanDownsampleStepSize()),
_laserScanVoxelSize(Parameters::defaultMemLaserScanVoxelSize()),
@@ -220,6 +221,23 @@ bool Memory::init(const std::string & dbUrl, bool dbOverwritten, const Parameter
if(_dbDriver->openConnection(dbUrl, dbOverwritten, isReadOnly()))
{
success = true;
// Before 0.23.12 the octave of a keypoint scaled into a decimated image was
// moved the wrong way, which changes the pyramid level its descriptor is
// taken from. A map filled that way stays self-consistent only if we keep
// filling it that way; a new one gets the corrected scaling.
_legacyDecimatedOctave =
uStrNumCmp(_dbDriver->getDatabaseVersion(), "0.23.12") < 0;
// Only where the descriptors stored in the map end up different: keypoints
// from odometry, scaled into the pre-decimated image before being described.
if(_legacyDecimatedOctave && _useOdometryFeatures && _imagePreDecimation > 1)
{
UWARN("Database \"%s\" was created by version %s, before the octave of "
"decimated keypoints was corrected (0.23.12). Its features keep "
"being described the old way so that they stay comparable with "
"those already in it.",
dbUrl.c_str(), _dbDriver->getDatabaseVersion().c_str());
}
if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit(std::string("Connecting to database \"") + dbUrl + "\", done!"));
}
else
@@ -5660,7 +5678,13 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
if(_imagePreDecimation > 1 || useProvided3dPoints)
{
float decimationRatio = 1.0f / float(_imagePreDecimation);
double log2value = log(double(_imagePreDecimation))/log(2.0);
// The octave a feature was found at moves with the image it is
// expressed in, by the same ratio as its position: a decimated
// image is already that many pyramid levels down, so scaling the
// keypoints into it lowers their octave. Databases older than
// 0.23.12 were filled with it raised instead; see _legacyDecimatedOctave.
double log2value = log(double(_legacyDecimatedOctave?
double(_imagePreDecimation):double(decimationRatio)))/log(2.0);
for(unsigned int i=0; i < keypoints.size(); ++i)
{
cv::KeyPoint & kpt = keypoints[i];
@@ -5669,7 +5693,10 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
kpt.pt.x *= decimationRatio;
kpt.pt.y *= decimationRatio;
kpt.size *= decimationRatio;
kpt.octave += log2value;
// Never below the finest level of the image it is now
// expressed in: the detail it was found at is not in there
// any more, and ORB refuses a negative octave outright.
kpt.octave = std::max(0, int(kpt.octave + log2value));
}
if(useProvided3dPoints)
{
@@ -6246,7 +6273,7 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
UASSERT(keypoints3D.size() == 0 || keypoints3D.size() == wordIds.size());
unsigned int i=0;
float decimationRatio = float(preDecimation) / float(_imagePostDecimation);
double log2value = log(double(preDecimation))/log(2.0);
double log2value = log(double(decimationRatio))/log(2.0);
for(std::list<int>::iterator iter=wordIds.begin(); iter!=wordIds.end() && i < keypoints.size(); ++iter, ++i)
{
cv::KeyPoint kpt = keypoints[i];
@@ -6256,7 +6283,7 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
kpt.pt.x *= decimationRatio;
kpt.pt.y *= decimationRatio;
kpt.size *= decimationRatio;
kpt.octave += log2value;
kpt.octave = std::max(0, int(kpt.octave + log2value));
}
words.insert(std::make_pair(*iter, words.size()));
wordsKpts.push_back(kpt);