From ec247e7994d03a7987622822dd6eb6bef0ab07d7 Mon Sep 17 00:00:00 2001 From: matlabbe Date: Sat, 3 Oct 2026 16:47:23 -0700 Subject: [PATCH] added lazy decoding check --- corelib/src/Memory.cpp | 6 ++++-- corelib/test/test_memory.cpp | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/corelib/src/Memory.cpp b/corelib/src/Memory.cpp index a392d73f..82eea94e 100644 --- a/corelib/src/Memory.cpp +++ b/corelib/src/Memory.cpp @@ -5246,7 +5246,7 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor if(!isIntermediateNode) { // We need raw images if we need to extract features and/or do tag detection - bool needRawImages = _feature2D->getMaxFeatures() >= 0 && + bool needRawImages = (_feature2D->getMaxFeatures() >= 0 && (!_useOdometryFeatures || data.keypoints().empty() || (int)data.keypoints().size() != data.descriptors().rows || @@ -5254,7 +5254,9 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor _detectMarkers || _rotateImagesUpsideUp || _imagePostDecimation > 1 || - (_createOccupancyGrid && _localMapMaker->isGridFromDepth())); + (_createOccupancyGrid && _localMapMaker->isGridFromDepth()))) || + // Images rectified below: stereo always, RGB-D unless only its features are + (!_imagesAlreadyRectified && !(_rectifyOnlyFeatures && data.stereoCameraModels().empty())); // Note: we could avoid uncompressing scan if we don't do any filtering // and if we don't use it for local occupancy grid diff --git a/corelib/test/test_memory.cpp b/corelib/test/test_memory.cpp index 7a38a3fc..bda4a611 100644 --- a/corelib/test/test_memory.cpp +++ b/corelib/test/test_memory.cpp @@ -4770,3 +4770,39 @@ INSTANTIATE_TEST_SUITE_P( InverseDepthCase{"0.23.0", kCompressedDepthOnly, ".rvl:10:100", true, ".png"}, // decompressed, re-compressed InverseDepthCase{"", kRawDepth, ".rvl", true, ".png"}, // RVL is 16UC1 only: legacy InverseDepthCase{"", kRawDepth, ".jpg", true, ".png"})); // invalid: default ".rvl" + +// Compressed images that Memory rectifies (Rtabmap/ImagesAlreadyRectified=false) are +// decoded for it, even when nothing else needs them (no feature extraction here): they +// are stored rectified, not as received. +TEST(MemoryTest, DecodesCompressedImagesToRectifyThem) +{ + for(bool alreadyRectified : {true, false}) + { + SCOPED_TRACE(alreadyRectified ? "already rectified" : "rectified by Memory"); + ParametersMap params = defaultMemoryParams(); + params[Parameters::kMemBinDataKept()] = "true"; + params[Parameters::kRtabmapImagesAlreadyRectified()] = alreadyRectified ? "true" : "false"; + Memory memory(params); + ASSERT_TRUE(memory.init("")); + + cv::Mat rgb(48, 64, CV_8UC3); + cv::randu(rgb, 0, 255); + const cv::Mat K = (cv::Mat_(3, 3) << 50, 0, 32, 0, 50, 24, 0, 0, 1); + const cv::Mat D = (cv::Mat_(1, 5) << -0.3, 0.1, 0, 0, 0); + const cv::Mat R = cv::Mat::eye(3, 3, CV_64FC1); + const cv::Mat P = (cv::Mat_(3, 4) << 50, 0, 32, 0, 0, 50, 24, 0, 0, 0, 1, 0); + const CameraModel model("cam", cv::Size(64, 48), K, D, R, P, CameraModel::opticalRotation()); + ASSERT_TRUE(model.isValidForRectification()); + const cv::Mat compressed = compressImage2(rgb, ".png"); + SensorData data(compressed, cv::Mat(), model); + + ASSERT_TRUE(memory.update(data, Transform(0, 0, 0, 0, 0, 0), cv::Mat::eye(6, 6, CV_64FC1) * 0.01)); + const Signature * s = memory.getSignature(memory.getLastSignatureId()); + ASSERT_NE(s, nullptr); + const cv::Mat & stored = s->sensorData().imageCompressed(); + ASSERT_FALSE(stored.empty()); + const bool sameBytes = stored.total() == compressed.total() && + memcmp(stored.data, compressed.data, compressed.total()) == 0; + EXPECT_EQ(sameBytes, alreadyRectified); + } +}