Gating negative octave scaling on decimation

This commit is contained in:
matlabbe
2026-09-19 17:07:47 -07:00
parent 4a8147b940
commit f1347db4f2
4 changed files with 52 additions and 4 deletions
+5 -2
View File
@@ -5673,7 +5673,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)
{
@@ -6263,7 +6266,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);
+3 -1
View File
@@ -792,7 +792,9 @@ Transform Odometry::process(SensorData & data, const Transform & guessIn, Odomet
decimatedKpts[i].pt.x /= _imageDecimation;
decimatedKpts[i].pt.y /= _imageDecimation;
decimatedKpts[i].size /= _imageDecimation;
decimatedKpts[i].octave -= log2value;
// Never below the finest level of the decimated image, which is as fine
// as its detail goes; ORB refuses a negative octave outright.
decimatedKpts[i].octave = std::max(0, int(decimatedKpts[i].octave - log2value));
}
decimatedData.setFeatures(decimatedKpts, decimatedData.keypoints3D(), decimatedData.descriptors());
}
+1 -1
View File
@@ -700,7 +700,7 @@ void SensorCaptureThread::postUpdate(SensorData * dataPtr, SensorCaptureInfo * i
kpts[i].pt.x /= _imageDecimation;
kpts[i].pt.y /= _imageDecimation;
kpts[i].size /= _imageDecimation;
kpts[i].octave -= log2value;
kpts[i].octave = std::max(0, int(kpts[i].octave - log2value));
}
data.setFeatures(kpts, data.keypoints3D(), data.descriptors());
}
+43
View File
@@ -2891,6 +2891,49 @@ TEST(MemoryTest, PreDecimationGivesBackProvidedKeypointsAsTheyCameIn)
EXPECT_EQ(s->getWordsKpts()[0].octave, kpt.octave);
}
TEST(MemoryTest, PreDecimationKeepsProvidedKeypointsAtTheFinestLevelAvailable)
{
// The companion of the test above, for a keypoint found at the finest level there is.
// Scaling it into a decimated image would put it below level 0, which does not exist
// -- the detail it was found at was decimated away -- and which ORB rejects outright
// rather than describing. It stays at 0 instead, and so cannot come back at 0: the
// level it would need to return to is the one that was lost.
ParametersMap params = defaultMemoryParams();
params[Parameters::kKpMaxFeatures()] = "100";
params[Parameters::kMemUseOdomFeatures()] = "true";
params[Parameters::kMemImagePreDecimation()] = "2";
params[Parameters::kMemImagePostDecimation()] = "1";
params[Parameters::kRtabmapImagesAlreadyRectified()] = "true";
Memory memory(params);
cv::Mat image(256, 256, CV_8UC1);
cv::RNG rng(7);
rng.fill(image, cv::RNG::UNIFORM, 0, 255);
const cv::Mat covariance = cv::Mat::eye(6, 6, CV_64FC1) * 0.01;
const CameraModel model(100.0, 100.0, 128.0, 128.0,
CameraModel::opticalRotation(), 0.0, cv::Size(256, 256));
SensorData data;
data.setRGBDImage(image, cv::Mat(), std::vector<CameraModel>{model});
data.setId(0);
cv::KeyPoint kpt(128.0f, 120.0f, 8.0f);
kpt.octave = 0;
data.setFeatures(std::vector<cv::KeyPoint>(1, kpt),
std::vector<cv::Point3f>(1, cv::Point3f(0.0f, 0.0f, 1.0f)),
cv::Mat());
ASSERT_TRUE(memory.update(data, Transform(0, 0, 0, 0, 0, 0), covariance));
const Signature * s = memory.getSignature(memory.getLastSignatureId());
ASSERT_NE(s, nullptr);
ASSERT_EQ(s->getWordsKpts().size(), 1u);
// Where it is and how big it is are unaffected, those having room to scale.
EXPECT_FLOAT_EQ(s->getWordsKpts()[0].pt.x, kpt.pt.x);
EXPECT_FLOAT_EQ(s->getWordsKpts()[0].pt.y, kpt.pt.y);
EXPECT_FLOAT_EQ(s->getWordsKpts()[0].size, kpt.size);
EXPECT_GE(s->getWordsKpts()[0].octave, 0);
}
TEST(MemoryTest, CreateSignaturePostDecimatesImageWhenPostDecimationGreaterThanOne)
{
// kMemImagePostDecimation > 1 causes createSignature to downsample the RGB image